test(compiler): check extracted translations for line endings (#36741)
When there are `CRLF` line endings some translations get different message ids. This commit adds tests to track this in ViewEngine. PR Close #36741
This commit is contained in:
parent
aa0dd0d5ff
commit
7bc5bcde34
|
@ -7,13 +7,18 @@
|
|||
*/
|
||||
|
||||
import {NgLocalization} from '@angular/common';
|
||||
import {Component, DebugElement} from '@angular/core';
|
||||
import {ComponentFixture} from '@angular/core/testing';
|
||||
|
||||
import {Serializer} from '@angular/compiler/src/i18n';
|
||||
import {MessageBundle} from '@angular/compiler/src/i18n/message_bundle';
|
||||
import {HtmlParser} from '@angular/compiler/src/ml_parser/html_parser';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler/src/ml_parser/interpolation_config';
|
||||
import {Component, DebugElement, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
import {SpyResourceLoader} from '../spies';
|
||||
|
||||
@Component({
|
||||
selector: 'i18n-cmp',
|
||||
template: '',
|
||||
|
@ -97,6 +102,15 @@ export function validateHtml(
|
|||
expectHtml(el, '#i18n-13').toBe('<div id="i18n-13" title="dans une section traductible"></div>');
|
||||
expectHtml(el, '#i18n-15').toMatch(/ca <b>devrait<\/b> marcher/);
|
||||
expectHtml(el, '#i18n-16').toMatch(/avec un ID explicite/);
|
||||
|
||||
expectHtml(el, '#i18n-17-5').toContain('Pas de réponse');
|
||||
cmp.response.getItemsList = () => ['a'];
|
||||
tb.detectChanges();
|
||||
expectHtml(el, '#i18n-17-5').toContain('Une réponse');
|
||||
cmp.response.getItemsList = () => ['a', 'b'];
|
||||
tb.detectChanges();
|
||||
expectHtml(el, '#i18n-17-5').toContain('2 réponses');
|
||||
|
||||
expectHtml(el, '#i18n-18')
|
||||
.toEqual('<div id="i18n-18">FOO<a title="dans une section traductible">BAR</a></div>');
|
||||
}
|
||||
|
@ -150,7 +164,7 @@ export const HTML = `
|
|||
<div id="i18n-17" i18n="@@i18n17">{count, plural, =0 {zero} =1 {one} =2 {two} other {<b>many</b>}}</div>
|
||||
|
||||
<!-- make sure that ICU messages are not treated as text nodes -->
|
||||
<div i18n="desc">{
|
||||
<div id="i18n-17-5" i18n="desc">{
|
||||
response.getItemsList().length,
|
||||
plural,
|
||||
=0 {Found no results}
|
||||
|
@ -160,5 +174,29 @@ export const HTML = `
|
|||
|
||||
<div i18n id="i18n-18">foo<a i18n-title title="in a translatable section">bar</a></div>
|
||||
|
||||
<div i18n>{{ 'test' //i18n(ph="map name") }}</div>
|
||||
<div id="i18n-19" i18n>{{ 'test' //i18n(ph="map name") }}</div>
|
||||
`;
|
||||
|
||||
export async function configureCompiler(translationsToMerge: string, format: string) {
|
||||
TestBed.configureCompiler({
|
||||
providers: [
|
||||
SpyResourceLoader.PROVIDE,
|
||||
FrLocalization.PROVIDE,
|
||||
{provide: TRANSLATIONS, useValue: translationsToMerge},
|
||||
{provide: TRANSLATIONS_FORMAT, useValue: format},
|
||||
]
|
||||
});
|
||||
TestBed.configureTestingModule({declarations: [I18nComponent]});
|
||||
}
|
||||
|
||||
export function createComponent(html: string) {
|
||||
const tb: ComponentFixture<I18nComponent> =
|
||||
TestBed.overrideTemplate(I18nComponent, html).createComponent(I18nComponent);
|
||||
return {tb, cmp: tb.componentInstance, el: tb.debugElement};
|
||||
}
|
||||
|
||||
export function serializeTranslations(html: string, serializer: Serializer) {
|
||||
const catalog = new MessageBundle(new HtmlParser, [], {});
|
||||
catalog.updateFromTemplate(html, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
return catalog.write(serializer);
|
||||
}
|
||||
|
|
|
@ -6,53 +6,53 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgLocalization} from '@angular/common';
|
||||
import {ResourceLoader} from '@angular/compiler';
|
||||
import {MessageBundle} from '@angular/compiler/src/i18n/message_bundle';
|
||||
import {Xliff2} from '@angular/compiler/src/i18n/serializers/xliff2';
|
||||
import {HtmlParser} from '@angular/compiler/src/ml_parser/html_parser';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler/src/ml_parser/interpolation_config';
|
||||
import {DebugElement, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {async} from '@angular/core/testing';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
import {SpyResourceLoader} from '../spies';
|
||||
import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common';
|
||||
|
||||
import {FrLocalization, HTML, I18nComponent, validateHtml} from './integration_common';
|
||||
|
||||
{
|
||||
describe('i18n XLIFF 2.0 integration spec', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureCompiler({
|
||||
providers: [
|
||||
SpyResourceLoader.PROVIDE,
|
||||
FrLocalization.PROVIDE,
|
||||
{provide: TRANSLATIONS, useValue: XLIFF2_TOMERGE},
|
||||
{provide: TRANSLATIONS_FORMAT, useValue: 'xlf2'},
|
||||
]
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({declarations: [I18nComponent]});
|
||||
}));
|
||||
describe('i18n XLIFF integration spec', () => {
|
||||
describe('(with LF line endings)', () => {
|
||||
beforeEach(
|
||||
async(() => configureCompiler(XLIFF2_TOMERGE + LF_LINE_ENDING_XLIFF2_TOMERGE, 'xlf2')));
|
||||
|
||||
it('should extract from templates', () => {
|
||||
const catalog = new MessageBundle(new HtmlParser, [], {});
|
||||
const serializer = new Xliff2();
|
||||
catalog.updateFromTemplate(HTML, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
const serializedXliff2 = serializeTranslations(HTML, serializer);
|
||||
|
||||
expect(catalog.write(serializer)).toContain(XLIFF2_EXTRACTED);
|
||||
XLIFF2_EXTRACTED.forEach(x => {
|
||||
expect(serializedXliff2).toContain(x);
|
||||
});
|
||||
expect(serializedXliff2).toContain(LF_LINE_ENDING_XLIFF2_EXTRACTED);
|
||||
});
|
||||
|
||||
it('should translate templates', () => {
|
||||
const tb: ComponentFixture<I18nComponent> =
|
||||
TestBed.overrideTemplate(I18nComponent, HTML).createComponent(I18nComponent);
|
||||
const cmp: I18nComponent = tb.componentInstance;
|
||||
const el: DebugElement = tb.debugElement;
|
||||
|
||||
const {tb, cmp, el} = createComponent(HTML);
|
||||
validateHtml(tb, cmp, el);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('(with CRLF line endings', () => {
|
||||
beforeEach(
|
||||
async(() => configureCompiler(XLIFF2_TOMERGE + CRLF_LINE_ENDING_XLIFF2_TOMERGE, 'xlf2')));
|
||||
|
||||
it('should extract from templates (with CRLF line endings)', () => {
|
||||
const serializer = new Xliff2();
|
||||
const serializedXliff = serializeTranslations(HTML.replace(/\n/g, '\r\n'), serializer);
|
||||
|
||||
XLIFF2_EXTRACTED.forEach(x => {
|
||||
expect(serializedXliff).toContain(x);
|
||||
});
|
||||
expect(serializedXliff).toContain(CRLF_LINE_ENDING_XLIFF2_EXTRACTED);
|
||||
});
|
||||
|
||||
it('should translate templates (with CRLF line endings)', () => {
|
||||
const {tb, cmp, el} = createComponent(HTML.replace(/\n/g, '\r\n'));
|
||||
validateHtml(tb, cmp, el);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const XLIFF2_TOMERGE = `
|
||||
<unit id="615790887472569365">
|
||||
|
@ -202,12 +202,6 @@ const XLIFF2_TOMERGE = `
|
|||
<target>{VAR_PLURAL, plural, =0 {zero} =1 {un} =2 {deux} other {<pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">beaucoup</pc>} }</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4085484936881858615">
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {une réponse} other {Trouvé <ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> réponses} }</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4035252431381981115">
|
||||
<segment>
|
||||
<source>foo<pc id="0" equivStart="START_LINK" equivEnd="CLOSE_LINK" type="link" dispStart="<a>" dispEnd="</a>">bar</pc></source>
|
||||
|
@ -221,24 +215,40 @@ const XLIFF2_TOMERGE = `
|
|||
</segment>
|
||||
</unit>`;
|
||||
|
||||
const XLIFF2_EXTRACTED = `
|
||||
<unit id="615790887472569365">
|
||||
const LF_LINE_ENDING_XLIFF2_TOMERGE = ` <unit id="4085484936881858615">
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {Une réponse} other {<ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> réponses} }</target>
|
||||
</segment>
|
||||
</unit>
|
||||
`;
|
||||
|
||||
const CRLF_LINE_ENDING_XLIFF2_TOMERGE = ` <unit id="4085484936881858615">
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {Une réponse} other {<ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> réponses} }</target>
|
||||
</segment>
|
||||
</unit>
|
||||
`;
|
||||
|
||||
const XLIFF2_EXTRACTED = [
|
||||
` <unit id="615790887472569365">
|
||||
<notes>
|
||||
<note category="location">file.ts:3</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>i18n attribute on tags</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="3707494640264351337">
|
||||
</unit>`,
|
||||
` <unit id="3707494640264351337">
|
||||
<notes>
|
||||
<note category="location">file.ts:5</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>nested</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5539162898278769904">
|
||||
</unit>`,
|
||||
` <unit id="5539162898278769904">
|
||||
<notes>
|
||||
<note category="meaning">different meaning</note>
|
||||
<note category="location">file.ts:7</note>
|
||||
|
@ -246,8 +256,8 @@ const XLIFF2_EXTRACTED = `
|
|||
<segment>
|
||||
<source>nested</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="3780349238193953556">
|
||||
</unit>`,
|
||||
` <unit id="3780349238193953556">
|
||||
<notes>
|
||||
<note category="location">file.ts:9</note>
|
||||
<note category="location">file.ts:10</note>
|
||||
|
@ -255,40 +265,40 @@ const XLIFF2_EXTRACTED = `
|
|||
<segment>
|
||||
<source><pc id="0" equivStart="START_ITALIC_TEXT" equivEnd="CLOSE_ITALIC_TEXT" type="fmt" dispStart="<i>" dispEnd="</i>">with placeholders</pc></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5415448997399451992">
|
||||
</unit>`,
|
||||
` <unit id="5415448997399451992">
|
||||
<notes>
|
||||
<note category="location">file.ts:11</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><pc id="0" equivStart="START_TAG_DIV" equivEnd="CLOSE_TAG_DIV" type="other" dispStart="<div>" dispEnd="</div>">with <pc id="1" equivStart="START_TAG_DIV" equivEnd="CLOSE_TAG_DIV" type="other" dispStart="<div>" dispEnd="</div>">nested</pc> placeholders</pc></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5525133077318024839">
|
||||
</unit>`,
|
||||
` <unit id="5525133077318024839">
|
||||
<notes>
|
||||
<note category="location">file.ts:14</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>on not translatable node</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2174788525135228764">
|
||||
</unit>`,
|
||||
` <unit id="2174788525135228764">
|
||||
<notes>
|
||||
<note category="location">file.ts:14</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><b>bold</b></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8670732454866344690">
|
||||
</unit>`,
|
||||
` <unit id="8670732454866344690">
|
||||
<notes>
|
||||
<note category="location">file.ts:15</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>on translatable node</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4593805537723189714">
|
||||
</unit>`,
|
||||
` <unit id="4593805537723189714">
|
||||
<notes>
|
||||
<note category="location">file.ts:20</note>
|
||||
<note category="location">file.ts:37</note>
|
||||
|
@ -296,8 +306,8 @@ const XLIFF2_EXTRACTED = `
|
|||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">many</pc>} }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="703464324060964421">
|
||||
</unit>`,
|
||||
` <unit id="703464324060964421">
|
||||
<notes>
|
||||
<note category="location">file.ts:22,24</note>
|
||||
</notes>
|
||||
|
@ -306,16 +316,16 @@ const XLIFF2_EXTRACTED = `
|
|||
<ph id="0" equiv="ICU" disp="{sex, select, male {...} female {...} other {...}}"/>
|
||||
</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5430374139308914421">
|
||||
</unit>`,
|
||||
` <unit id="5430374139308914421">
|
||||
<notes>
|
||||
<note category="location">file.ts:23</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_SELECT, select, male {m} female {f} other {other} }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="1300564767229037107">
|
||||
</unit>`,
|
||||
` <unit id="1300564767229037107">
|
||||
<notes>
|
||||
<note category="location">file.ts:25,27</note>
|
||||
</notes>
|
||||
|
@ -324,40 +334,40 @@ const XLIFF2_EXTRACTED = `
|
|||
<ph id="0" equiv="ICU" disp="{sexB, select, male {...} female {...}}"/>
|
||||
</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2500580913783245106">
|
||||
</unit>`,
|
||||
` <unit id="2500580913783245106">
|
||||
<notes>
|
||||
<note category="location">file.ts:26</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_SELECT, select, male {m} female {f} }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4851788426695310455">
|
||||
</unit>`,
|
||||
` <unit id="4851788426695310455">
|
||||
<notes>
|
||||
<note category="location">file.ts:29</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><ph id="0" equiv="INTERPOLATION" disp="{{ "count = " + count }}"/></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="9013357158046221374">
|
||||
</unit>`,
|
||||
` <unit id="9013357158046221374">
|
||||
<notes>
|
||||
<note category="location">file.ts:30</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>sex = <ph id="0" equiv="INTERPOLATION" disp="{{ sex }}"/></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="8324617391167353662">
|
||||
</unit>`,
|
||||
` <unit id="8324617391167353662">
|
||||
<notes>
|
||||
<note category="location">file.ts:31</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><ph id="0" equiv="CUSTOM_NAME" disp="{{ "custom name" //i18n(ph="CUSTOM_NAME") }}"/></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7685649297917455806">
|
||||
</unit>`,
|
||||
` <unit id="7685649297917455806">
|
||||
<notes>
|
||||
<note category="location">file.ts:36</note>
|
||||
<note category="location">file.ts:54</note>
|
||||
|
@ -365,8 +375,8 @@ const XLIFF2_EXTRACTED = `
|
|||
<segment>
|
||||
<source>in a translatable section</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2329001734457059408">
|
||||
</unit>`,
|
||||
` <unit id="2329001734457059408">
|
||||
<notes>
|
||||
<note category="location">file.ts:34,38</note>
|
||||
</notes>
|
||||
|
@ -377,32 +387,50 @@ const XLIFF2_EXTRACTED = `
|
|||
<pc id="2" equivStart="START_TAG_DIV_1" equivEnd="CLOSE_TAG_DIV" type="other" dispStart="<div>" dispEnd="</div>"><ph id="3" equiv="ICU" disp="{count, plural, =0 {...} =1 {...} =2 {...} other {...}}"/></pc>
|
||||
</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="1491627405349178954">
|
||||
</unit>`,
|
||||
` <unit id="1491627405349178954">
|
||||
<notes>
|
||||
<note category="location">file.ts:40</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>it <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">should</pc> work</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="i18n16">
|
||||
</unit>`,
|
||||
` <unit id="i18n16">
|
||||
<notes>
|
||||
<note category="location">file.ts:42</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>with an explicit ID</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="i18n17">
|
||||
</unit>`,
|
||||
` <unit id="i18n17">
|
||||
<notes>
|
||||
<note category="location">file.ts:43</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">many</pc>} }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4085484936881858615">
|
||||
</unit>`,
|
||||
` <unit id="4035252431381981115">
|
||||
<notes>
|
||||
<note category="location">file.ts:54</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>foo<pc id="0" equivStart="START_LINK" equivEnd="CLOSE_LINK" type="link" dispStart="<a>" dispEnd="</a>">bar</pc></source>
|
||||
</segment>
|
||||
</unit>`,
|
||||
` <unit id="5339604010413301604">
|
||||
<notes>
|
||||
<note category="location">file.ts:56</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><ph id="0" equiv="MAP NAME" disp="{{ 'test' //i18n(ph="map name") }}"/></source>
|
||||
</segment>
|
||||
</unit>`
|
||||
];
|
||||
|
||||
const LF_LINE_ENDING_XLIFF2_EXTRACTED = ` <unit id="4085484936881858615">
|
||||
<notes>
|
||||
<note category="description">desc</note>
|
||||
<note category="location">file.ts:46,52</note>
|
||||
|
@ -410,20 +438,14 @@ const XLIFF2_EXTRACTED = `
|
|||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> results} }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="4035252431381981115">
|
||||
</unit>`;
|
||||
|
||||
const CRLF_LINE_ENDING_XLIFF2_EXTRACTED = ` <unit id="4085484936881858615">
|
||||
<notes>
|
||||
<note category="location">file.ts:54</note>
|
||||
<note category="description">desc</note>
|
||||
<note category="location">file.ts:46,52</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>foo<pc id="0" equivStart="START_LINK" equivEnd="CLOSE_LINK" type="link" dispStart="<a>" dispEnd="</a>">bar</pc></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="5339604010413301604">
|
||||
<notes>
|
||||
<note category="location">file.ts:56</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><ph id="0" equiv="MAP NAME" disp="{{ 'test' //i18n(ph="map name") }}"/></source>
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph id="0" equiv="INTERPOLATION" disp="{{response.getItemsList().length}}"/> results} }</source>
|
||||
</segment>
|
||||
</unit>`;
|
||||
|
|
|
@ -6,53 +6,52 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgLocalization} from '@angular/common';
|
||||
import {ResourceLoader} from '@angular/compiler';
|
||||
import {MessageBundle} from '@angular/compiler/src/i18n/message_bundle';
|
||||
import {Xliff} from '@angular/compiler/src/i18n/serializers/xliff';
|
||||
import {HtmlParser} from '@angular/compiler/src/ml_parser/html_parser';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler/src/ml_parser/interpolation_config';
|
||||
import {DebugElement, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {async} from '@angular/core/testing';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
import {SpyResourceLoader} from '../spies';
|
||||
import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common';
|
||||
|
||||
import {FrLocalization, HTML, I18nComponent, validateHtml} from './integration_common';
|
||||
|
||||
{
|
||||
describe('i18n XLIFF integration spec', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureCompiler({
|
||||
providers: [
|
||||
SpyResourceLoader.PROVIDE,
|
||||
FrLocalization.PROVIDE,
|
||||
{provide: TRANSLATIONS, useValue: XLIFF_TOMERGE},
|
||||
{provide: TRANSLATIONS_FORMAT, useValue: 'xliff'},
|
||||
]
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({declarations: [I18nComponent]});
|
||||
}));
|
||||
describe('i18n XLIFF integration spec', () => {
|
||||
describe('(with LF line endings)', () => {
|
||||
beforeEach(async(() => configureCompiler(XLIFF_TOMERGE + LF_LINE_ENDING_XLIFF_TOMERGE, 'xlf')));
|
||||
|
||||
it('should extract from templates', () => {
|
||||
const catalog = new MessageBundle(new HtmlParser, [], {});
|
||||
const serializer = new Xliff();
|
||||
catalog.updateFromTemplate(HTML, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
const serializedXliff = serializeTranslations(HTML, serializer);
|
||||
|
||||
expect(catalog.write(serializer)).toContain(XLIFF_EXTRACTED);
|
||||
XLIFF_EXTRACTED.forEach(x => {
|
||||
expect(serializedXliff).toContain(x);
|
||||
});
|
||||
expect(serializedXliff).toContain(LF_LINE_ENDING_XLIFF_EXTRACTED);
|
||||
});
|
||||
|
||||
it('should translate templates', () => {
|
||||
const tb: ComponentFixture<I18nComponent> =
|
||||
TestBed.overrideTemplate(I18nComponent, HTML).createComponent(I18nComponent);
|
||||
const cmp: I18nComponent = tb.componentInstance;
|
||||
const el: DebugElement = tb.debugElement;
|
||||
|
||||
const {tb, cmp, el} = createComponent(HTML);
|
||||
validateHtml(tb, cmp, el);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('(with CRLF line endings', () => {
|
||||
beforeEach(
|
||||
async(() => configureCompiler(XLIFF_TOMERGE + CRLF_LINE_ENDING_XLIFF_TOMERGE, 'xlf')));
|
||||
|
||||
it('should extract from templates (with CRLF line endings)', () => {
|
||||
const serializer = new Xliff();
|
||||
const serializedXliff = serializeTranslations(HTML.replace(/\n/g, '\r\n'), serializer);
|
||||
|
||||
XLIFF_EXTRACTED.forEach(x => {
|
||||
expect(serializedXliff).toContain(x);
|
||||
});
|
||||
expect(serializedXliff).toContain(CRLF_LINE_ENDING_XLIFF_EXTRACTED);
|
||||
});
|
||||
|
||||
it('should translate templates (with CRLF line endings)', () => {
|
||||
const {tb, cmp, el} = createComponent(HTML.replace(/\n/g, '\r\n'));
|
||||
validateHtml(tb, cmp, el);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const XLIFF_TOMERGE = `
|
||||
<trans-unit id="3cb04208df1c2f62553ed48e75939cf7107f9dad" datatype="html">
|
||||
|
@ -156,44 +155,53 @@ const XLIFF_TOMERGE = `
|
|||
<source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<x id="START_BOLD_TEXT" ctype="x-b" equiv-text="<b>"/>many<x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="</b>"/>} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {zero} =1 {un} =2 {deux} other {<x id="START_BOLD_TEXT" ctype="x-b"/>beaucoup<x id="CLOSE_BOLD_TEXT" ctype="x-b"/>} }</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2370d995bdcc1e7496baa32df20654aff65c2d10" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <x id="INTERPOLATION" equiv-text="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {une réponse} other {Found <x id="INTERPOLATION"/> réponse} }</target>
|
||||
<note priority="1" from="description">desc</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="296ab5eab8d370822488c152586db3a5875ee1a2" datatype="html">
|
||||
<source>foo<x id="START_LINK" ctype="x-a" equiv-text="<a>"/>bar<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/></source>
|
||||
<target>FOO<x id="START_LINK" ctype="x-a"/>BAR<x id="CLOSE_LINK" ctype="x-a"/></target>
|
||||
<target>FOO<x id="START_LINK" ctype="x-a"/>BAR<x id="CLOSE_LINK" ctype=" x-a"/></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2e013b311caa0916478941a985887e091d8288b6" datatype="html">
|
||||
<source><x id="MAP NAME" equiv-text="{{ 'test' //i18n(ph="map name") }}"/></source>
|
||||
<target><x id="MAP NAME"/></target>
|
||||
</trans-unit>`;
|
||||
|
||||
const XLIFF_EXTRACTED = `
|
||||
<trans-unit id="3cb04208df1c2f62553ed48e75939cf7107f9dad" datatype="html">
|
||||
const LF_LINE_ENDING_XLIFF_TOMERGE =
|
||||
` <trans-unit id="2370d995bdcc1e7496baa32df20654aff65c2d10" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <x id="INTERPOLATION" equiv-text="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {Une réponse} other {<x id="INTERPOLATION"/> réponses} }</target>
|
||||
<note priority="1" from="description">desc</note>
|
||||
</trans-unit>`;
|
||||
|
||||
const CRLF_LINE_ENDING_XLIFF_TOMERGE =
|
||||
` <trans-unit id="73a09babbde7a003ece74b02acfd22057507717b" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <x id="INTERPOLATION" equiv-text="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {Une réponse} other {<x id="INTERPOLATION"/> réponses} }</target>
|
||||
<note priority="1" from="description">desc</note>
|
||||
</trans-unit>`;
|
||||
|
||||
const XLIFF_EXTRACTED: string[] = [
|
||||
` <trans-unit id="3cb04208df1c2f62553ed48e75939cf7107f9dad" datatype="html">
|
||||
<source>i18n attribute on tags</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">3</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="52895b1221effb3f3585b689f049d2784d714952" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="52895b1221effb3f3585b689f049d2784d714952" datatype="html">
|
||||
<source>nested</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">5</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="88d5f22050a9df477ee5646153558b3a4862d47e" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="88d5f22050a9df477ee5646153558b3a4862d47e" datatype="html">
|
||||
<source>nested</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">7</context>
|
||||
</context-group>
|
||||
<note priority="1" from="meaning">different meaning</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="34fec9cc62e28e8aa6ffb306fa8569ef0a8087fe" datatype="html">
|
||||
</trans-unit>`,
|
||||
`<trans-unit id="34fec9cc62e28e8aa6ffb306fa8569ef0a8087fe" datatype="html">
|
||||
<source><x id="START_ITALIC_TEXT" ctype="x-i" equiv-text="<i>"/>with placeholders<x id="CLOSE_ITALIC_TEXT" ctype="x-i" equiv-text="</i>"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
|
@ -203,36 +211,36 @@ const XLIFF_EXTRACTED = `
|
|||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">10</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="651d7249d3a225037eb66f3433d98ad4a86f0a22" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="651d7249d3a225037eb66f3433d98ad4a86f0a22" datatype="html">
|
||||
<source><x id="START_TAG_DIV" ctype="x-div" equiv-text="<div>"/>with <x id="START_TAG_DIV" ctype="x-div" equiv-text="<div>"/>nested<x id="CLOSE_TAG_DIV" ctype="x-div" equiv-text="</div>"/> placeholders<x id="CLOSE_TAG_DIV" ctype="x-div" equiv-text="</div>"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">11</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1fe4616cce80a57c7707bac1c97054aa8e244a67" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="1fe4616cce80a57c7707bac1c97054aa8e244a67" datatype="html">
|
||||
<source>on not translatable node</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">14</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="480aaeeea1570bc1dde6b8404e380dee11ed0759" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="480aaeeea1570bc1dde6b8404e380dee11ed0759" datatype="html">
|
||||
<source><b>bold</b></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">14</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="67162b5af5f15fd0eb6480c88688dafdf952b93a" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="67162b5af5f15fd0eb6480c88688dafdf952b93a" datatype="html">
|
||||
<source>on translatable node</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">15</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="dc5536bb9e0e07291c185a0d306601a2ecd4813f" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="dc5536bb9e0e07291c185a0d306601a2ecd4813f" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<x id="START_BOLD_TEXT" ctype="x-b" equiv-text="<b>"/>many<x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="</b>"/>} }</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
|
@ -242,8 +250,8 @@ const XLIFF_EXTRACTED = `
|
|||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">37</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="49feb201083cbd2c8bfc48a4ae11f105fb984876" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="49feb201083cbd2c8bfc48a4ae11f105fb984876" datatype="html">
|
||||
<source>
|
||||
<x id="ICU" equiv-text="{sex, select, male {...} female {...} other {...}}"/>
|
||||
</source>
|
||||
|
@ -251,15 +259,15 @@ const XLIFF_EXTRACTED = `
|
|||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">22</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="f3be30eb9a18f6e336cc3ca4dd66bbc3a35c5f97" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="f3be30eb9a18f6e336cc3ca4dd66bbc3a35c5f97" datatype="html">
|
||||
<source>{VAR_SELECT, select, male {m} female {f} other {other} }</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">23</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="cc16e9745fa0b95b2ebc2f18b47ed8e64fe5f0f9" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="cc16e9745fa0b95b2ebc2f18b47ed8e64fe5f0f9" datatype="html">
|
||||
<source>
|
||||
<x id="ICU" equiv-text="{sexB, select, male {...} female {...}}"/>
|
||||
</source>
|
||||
|
@ -267,36 +275,36 @@ const XLIFF_EXTRACTED = `
|
|||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">25</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4573f2edb0329d69afc2ab8c73c71e2f8b08f807" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="4573f2edb0329d69afc2ab8c73c71e2f8b08f807" datatype="html">
|
||||
<source>{VAR_SELECT, select, male {m} female {f} }</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">26</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="d9879678f727b244bc7c7e20f22b63d98cb14890" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="d9879678f727b244bc7c7e20f22b63d98cb14890" datatype="html">
|
||||
<source><x id="INTERPOLATION" equiv-text="{{ "count = " + count }}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="50dac33dc6fc0578884baac79d875785ed77c928" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="50dac33dc6fc0578884baac79d875785ed77c928" datatype="html">
|
||||
<source>sex = <x id="INTERPOLATION" equiv-text="{{ sex }}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">30</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="a46f833b1fe6ca49e8b97c18f4b7ea0b930c9383" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="a46f833b1fe6ca49e8b97c18f4b7ea0b930c9383" datatype="html">
|
||||
<source><x id="CUSTOM_NAME" equiv-text="{{ "custom name" //i18n(ph="CUSTOM_NAME") }}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">31</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2ec983b4893bcd5b24af33bebe3ecba63868453c" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="2ec983b4893bcd5b24af33bebe3ecba63868453c" datatype="html">
|
||||
<source>in a translatable section</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
|
@ -306,8 +314,8 @@ const XLIFF_EXTRACTED = `
|
|||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7f6272480ea8e7ffab548da885ab8105ee2caa93" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="7f6272480ea8e7ffab548da885ab8105ee2caa93" datatype="html">
|
||||
<source>
|
||||
<x id="START_HEADING_LEVEL1" ctype="x-h1" equiv-text="<h1>"/>Markers in html comments<x id="CLOSE_HEADING_LEVEL1" ctype="x-h1" equiv-text="</h1>"/>
|
||||
<x id="START_TAG_DIV" ctype="x-div" equiv-text="<div>"/><x id="CLOSE_TAG_DIV" ctype="x-div" equiv-text="</div>"/>
|
||||
|
@ -317,47 +325,60 @@ const XLIFF_EXTRACTED = `
|
|||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="93a30c67d4e6c9b37aecfe2ac0f2b5d366d7b520" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="93a30c67d4e6c9b37aecfe2ac0f2b5d366d7b520" datatype="html">
|
||||
<source>it <x id="START_BOLD_TEXT" ctype="x-b" equiv-text="<b>"/>should<x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="</b>"/> work</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">40</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="i18n16" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="i18n16" datatype="html">
|
||||
<source>with an explicit ID</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">42</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="i18n17" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="i18n17" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<x id="START_BOLD_TEXT" ctype="x-b" equiv-text="<b>"/>many<x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="</b>"/>} }</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">43</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2370d995bdcc1e7496baa32df20654aff65c2d10" datatype="html">
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="296ab5eab8d370822488c152586db3a5875ee1a2" datatype="html">
|
||||
<source>foo<x id="START_LINK" ctype="x-a" equiv-text="<a>"/>bar<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
</trans-unit>`,
|
||||
` <trans-unit id="2e013b311caa0916478941a985887e091d8288b6" datatype="html">
|
||||
<source><x id="MAP NAME" equiv-text="{{ 'test' //i18n(ph="map name") }}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">56</context>
|
||||
</context-group>
|
||||
</trans-unit>`
|
||||
];
|
||||
|
||||
const LF_LINE_ENDING_XLIFF_EXTRACTED =
|
||||
` <trans-unit id="2370d995bdcc1e7496baa32df20654aff65c2d10" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <x id="INTERPOLATION" equiv-text="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">46</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">desc</note>
|
||||
</trans-unit>`;
|
||||
|
||||
const CRLF_LINE_ENDING_XLIFF_EXTRACTED =
|
||||
` <trans-unit id="73a09babbde7a003ece74b02acfd22057507717b" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <x id="INTERPOLATION" equiv-text="{{response.getItemsList().length}}"/> results} }</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">46</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">desc</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="296ab5eab8d370822488c152586db3a5875ee1a2" datatype="html">
|
||||
<source>foo<x id="START_LINK" ctype="x-a" equiv-text="<a>"/>bar<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2e013b311caa0916478941a985887e091d8288b6" datatype="html">
|
||||
<source><x id="MAP NAME" equiv-text="{{ 'test' //i18n(ph="map name") }}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">56</context>
|
||||
</context-group>
|
||||
</trans-unit>`;
|
||||
|
|
|
@ -6,53 +6,52 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgLocalization} from '@angular/common';
|
||||
import {ResourceLoader} from '@angular/compiler';
|
||||
import {MessageBundle} from '@angular/compiler/src/i18n/message_bundle';
|
||||
import {Xmb} from '@angular/compiler/src/i18n/serializers/xmb';
|
||||
import {HtmlParser} from '@angular/compiler/src/ml_parser/html_parser';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler/src/ml_parser/interpolation_config';
|
||||
import {DebugElement, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {async} from '@angular/core/testing';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
import {SpyResourceLoader} from '../spies';
|
||||
import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common';
|
||||
|
||||
import {FrLocalization, HTML, I18nComponent, validateHtml} from './integration_common';
|
||||
|
||||
{
|
||||
describe('i18n XMB/XTB integration spec', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureCompiler({
|
||||
providers: [
|
||||
SpyResourceLoader.PROVIDE,
|
||||
FrLocalization.PROVIDE,
|
||||
{provide: TRANSLATIONS, useValue: XTB},
|
||||
{provide: TRANSLATIONS_FORMAT, useValue: 'xtb'},
|
||||
]
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({declarations: [I18nComponent]});
|
||||
}));
|
||||
describe('i18n XMB/XTB integration spec', () => {
|
||||
describe('(with LF line endings)', () => {
|
||||
beforeEach(async(() => configureCompiler(XTB + LF_LINE_ENDING_XTB, 'xtb')));
|
||||
|
||||
it('should extract from templates', () => {
|
||||
const catalog = new MessageBundle(new HtmlParser, [], {});
|
||||
const serializer = new Xmb();
|
||||
catalog.updateFromTemplate(HTML, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
const serializedXmb = serializeTranslations(HTML, serializer);
|
||||
|
||||
expect(catalog.write(serializer)).toContain(XMB);
|
||||
XMB.forEach(x => {
|
||||
expect(serializedXmb).toContain(x);
|
||||
});
|
||||
expect(serializedXmb).toContain(LF_LINE_ENDING_XMB);
|
||||
});
|
||||
|
||||
it('should translate templates', () => {
|
||||
const tb: ComponentFixture<I18nComponent> =
|
||||
TestBed.overrideTemplate(I18nComponent, HTML).createComponent(I18nComponent);
|
||||
const cmp: I18nComponent = tb.componentInstance;
|
||||
const el: DebugElement = tb.debugElement;
|
||||
|
||||
const {tb, cmp, el} = createComponent(HTML);
|
||||
validateHtml(tb, cmp, el);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('(with CRLF line endings', () => {
|
||||
beforeEach(async(() => configureCompiler(XTB + CRLF_LINE_ENDING_XTB, 'xtb')));
|
||||
|
||||
it('should extract from templates (with CRLF line endings)', () => {
|
||||
const serializer = new Xmb();
|
||||
const serializedXmb = serializeTranslations(HTML.replace(/\n/g, '\r\n'), serializer);
|
||||
|
||||
XMB.forEach(x => {
|
||||
expect(serializedXmb).toContain(x);
|
||||
});
|
||||
expect(serializedXmb).toContain(CRLF_LINE_ENDING_XMB);
|
||||
});
|
||||
|
||||
it('should translate templates (with CRLF line endings)', () => {
|
||||
const {tb, cmp, el} = createComponent(HTML.replace(/\n/g, '\r\n'));
|
||||
validateHtml(tb, cmp, el);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const XTB = `
|
||||
<translationbundle>
|
||||
|
@ -82,40 +81,48 @@ const XTB = `
|
|||
<translation id="i18n16">avec un ID explicite</translation>
|
||||
<translation id="i18n17">{VAR_PLURAL, plural, =0 {zero} =1 {un} =2 {deux} other {<ph
|
||||
name="START_BOLD_TEXT"><ex><b></ex></ph>beaucoup<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></ph>} }</translation>
|
||||
<translation id="4085484936881858615">{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {une réponse} other {<ph name="INTERPOLATION"><ex>INTERPOLATION</ex></ph> réponse} }</translation>
|
||||
<translation id="4085484936881858615">{VAR_PLURAL, plural, =0 {Pas de réponse} =1 {Une réponse} other {<ph name="INTERPOLATION"><ex>INTERPOLATION</ex></ph> réponses} }</translation>
|
||||
<translation id="4035252431381981115">FOO<ph name="START_LINK"><ex><a></ex></ph>BAR<ph name="CLOSE_LINK"><ex></a></ex></ph></translation>
|
||||
<translation id="5339604010413301604"><ph name="MAP_NAME"><ex>MAP_NAME</ex></ph></translation>
|
||||
</translationbundle>`;
|
||||
|
||||
const XMB = `<msg id="615790887472569365"><source>file.ts:3</source>i18n attribute on tags</msg>
|
||||
<msg id="3707494640264351337"><source>file.ts:5</source>nested</msg>
|
||||
<msg id="5539162898278769904" meaning="different meaning"><source>file.ts:7</source>nested</msg>
|
||||
<msg id="3780349238193953556"><source>file.ts:9</source><source>file.ts:10</source><ph name="START_ITALIC_TEXT"><ex><i></ex><i></ph>with placeholders<ph name="CLOSE_ITALIC_TEXT"><ex></i></ex></i></ph></msg>
|
||||
<msg id="5415448997399451992"><source>file.ts:11</source><ph name="START_TAG_DIV"><ex><div></ex><div></ph>with <ph name="START_TAG_DIV"><ex><div></ex><div></ph>nested<ph name="CLOSE_TAG_DIV"><ex></div></ex></div></ph> placeholders<ph name="CLOSE_TAG_DIV"><ex></div></ex></div></ph></msg>
|
||||
<msg id="5525133077318024839"><source>file.ts:14</source>on not translatable node</msg>
|
||||
<msg id="2174788525135228764"><source>file.ts:14</source><b>bold</b></msg>
|
||||
<msg id="8670732454866344690"><source>file.ts:15</source>on translatable node</msg>
|
||||
<msg id="4593805537723189714"><source>file.ts:20</source><source>file.ts:37</source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<ph name="START_BOLD_TEXT"><ex><b></ex><b></ph>many<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></b></ph>} }</msg>
|
||||
<msg id="703464324060964421"><source>file.ts:22,24</source>
|
||||
const LF_LINE_ENDING_XTB = ``;
|
||||
const CRLF_LINE_ENDING_XTB = ``;
|
||||
|
||||
const XMB = [
|
||||
`<msg id="615790887472569365"><source>file.ts:3</source>i18n attribute on tags</msg>`,
|
||||
`<msg id="3707494640264351337"><source>file.ts:5</source>nested</msg>`,
|
||||
`<msg id="5539162898278769904" meaning="different meaning"><source>file.ts:7</source>nested</msg>`,
|
||||
`<msg id="3780349238193953556"><source>file.ts:9</source><source>file.ts:10</source><ph name="START_ITALIC_TEXT"><ex><i></ex><i></ph>with placeholders<ph name="CLOSE_ITALIC_TEXT"><ex></i></ex></i></ph></msg>`,
|
||||
`<msg id="5415448997399451992"><source>file.ts:11</source><ph name="START_TAG_DIV"><ex><div></ex><div></ph>with <ph name="START_TAG_DIV"><ex><div></ex><div></ph>nested<ph name="CLOSE_TAG_DIV"><ex></div></ex></div></ph> placeholders<ph name="CLOSE_TAG_DIV"><ex></div></ex></div></ph></msg>`,
|
||||
`<msg id="5525133077318024839"><source>file.ts:14</source>on not translatable node</msg>`,
|
||||
`<msg id="2174788525135228764"><source>file.ts:14</source><b>bold</b></msg>`,
|
||||
`<msg id="8670732454866344690"><source>file.ts:15</source>on translatable node</msg>`,
|
||||
`<msg id="4593805537723189714"><source>file.ts:20</source><source>file.ts:37</source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<ph name="START_BOLD_TEXT"><ex><b></ex><b></ph>many<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></b></ph>} }</msg>`,
|
||||
`<msg id="703464324060964421"><source>file.ts:22,24</source>
|
||||
<ph name="ICU"><ex>{sex, select, male {...} female {...} other {...}}</ex>{sex, select, male {...} female {...} other {...}}</ph>
|
||||
</msg>
|
||||
<msg id="5430374139308914421"><source>file.ts:23</source>{VAR_SELECT, select, male {m} female {f} other {other} }</msg>
|
||||
<msg id="1300564767229037107"><source>file.ts:25,27</source>
|
||||
</msg>`,
|
||||
`<msg id="5430374139308914421"><source>file.ts:23</source>{VAR_SELECT, select, male {m} female {f} other {other} }</msg>`,
|
||||
`<msg id="1300564767229037107"><source>file.ts:25,27</source>
|
||||
<ph name="ICU"><ex>{sexB, select, male {...} female {...}}</ex>{sexB, select, male {...} female {...}}</ph>
|
||||
</msg>
|
||||
<msg id="2500580913783245106"><source>file.ts:26</source>{VAR_SELECT, select, male {m} female {f} }</msg>
|
||||
<msg id="4851788426695310455"><source>file.ts:29</source><ph name="INTERPOLATION"><ex>{{ "count = " + count }}</ex>{{ "count = " + count }}</ph></msg>
|
||||
<msg id="9013357158046221374"><source>file.ts:30</source>sex = <ph name="INTERPOLATION"><ex>{{ sex }}</ex>{{ sex }}</ph></msg>
|
||||
<msg id="8324617391167353662"><source>file.ts:31</source><ph name="CUSTOM_NAME"><ex>{{ "custom name" //i18n(ph="CUSTOM_NAME") }}</ex>{{ "custom name" //i18n(ph="CUSTOM_NAME") }}</ph></msg>
|
||||
<msg id="7685649297917455806"><source>file.ts:36</source><source>file.ts:54</source>in a translatable section</msg>
|
||||
<msg id="2329001734457059408"><source>file.ts:34,38</source>
|
||||
</msg>`,
|
||||
`<msg id="2500580913783245106"><source>file.ts:26</source>{VAR_SELECT, select, male {m} female {f} }</msg>`,
|
||||
`<msg id="4851788426695310455"><source>file.ts:29</source><ph name="INTERPOLATION"><ex>{{ "count = " + count }}</ex>{{ "count = " + count }}</ph></msg>`,
|
||||
`<msg id="9013357158046221374"><source>file.ts:30</source>sex = <ph name="INTERPOLATION"><ex>{{ sex }}</ex>{{ sex }}</ph></msg>`,
|
||||
`<msg id="8324617391167353662"><source>file.ts:31</source><ph name="CUSTOM_NAME"><ex>{{ "custom name" //i18n(ph="CUSTOM_NAME") }}</ex>{{ "custom name" //i18n(ph="CUSTOM_NAME") }}</ph></msg>`,
|
||||
`<msg id="7685649297917455806"><source>file.ts:36</source><source>file.ts:54</source>in a translatable section</msg>`,
|
||||
`<msg id="2329001734457059408"><source>file.ts:34,38</source>
|
||||
<ph name="START_HEADING_LEVEL1"><ex><h1></ex><h1></ph>Markers in html comments<ph name="CLOSE_HEADING_LEVEL1"><ex></h1></ex></h1></ph>
|
||||
<ph name="START_TAG_DIV"><ex><div></ex><div></ph><ph name="CLOSE_TAG_DIV"><ex></div></ex></div></ph>
|
||||
<ph name="START_TAG_DIV_1"><ex><div></ex><div></ph><ph name="ICU"><ex>{count, plural, =0 {...} =1 {...} =2 {...} other {...}}</ex>{count, plural, =0 {...} =1 {...} =2 {...} other {...}}</ph><ph name="CLOSE_TAG_DIV"><ex></div></ex></div></ph>
|
||||
</msg>
|
||||
<msg id="1491627405349178954"><source>file.ts:40</source>it <ph name="START_BOLD_TEXT"><ex><b></ex><b></ph>should<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></b></ph> work</msg>
|
||||
<msg id="i18n16"><source>file.ts:42</source>with an explicit ID</msg>
|
||||
<msg id="i18n17"><source>file.ts:43</source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<ph name="START_BOLD_TEXT"><ex><b></ex><b></ph>many<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></b></ph>} }</msg>
|
||||
<msg id="4085484936881858615" desc="desc"><source>file.ts:46,52</source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph name="INTERPOLATION"><ex>{{response.getItemsList().length}}</ex>{{response.getItemsList().length}}</ph> results} }</msg>
|
||||
<msg id="4035252431381981115"><source>file.ts:54</source>foo<ph name="START_LINK"><ex><a></ex><a></ph>bar<ph name="CLOSE_LINK"><ex></a></ex></a></ph></msg>
|
||||
<msg id="5339604010413301604"><source>file.ts:56</source><ph name="MAP_NAME"><ex>{{ 'test' //i18n(ph="map name") }}</ex>{{ 'test' //i18n(ph="map name") }}</ph></msg>`;
|
||||
</msg>`,
|
||||
`<msg id="1491627405349178954"><source>file.ts:40</source>it <ph name="START_BOLD_TEXT"><ex><b></ex><b></ph>should<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></b></ph> work</msg>`,
|
||||
`<msg id="i18n16"><source>file.ts:42</source>with an explicit ID</msg>`,
|
||||
`<msg id="i18n17"><source>file.ts:43</source>{VAR_PLURAL, plural, =0 {zero} =1 {one} =2 {two} other {<ph name="START_BOLD_TEXT"><ex><b></ex><b></ph>many<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></b></ph>} }</msg>`,
|
||||
`<msg id="4085484936881858615" desc="desc"><source>file.ts:46,52</source>{VAR_PLURAL, plural, =0 {Found no results} =1 {Found one result} other {Found <ph name="INTERPOLATION"><ex>{{response.getItemsList().length}}</ex>{{response.getItemsList().length}}</ph> results} }</msg>`,
|
||||
`<msg id="4035252431381981115"><source>file.ts:54</source>foo<ph name="START_LINK"><ex><a></ex><a></ph>bar<ph name="CLOSE_LINK"><ex></a></ex></a></ph></msg>`,
|
||||
`<msg id="5339604010413301604"><source>file.ts:56</source><ph name="MAP_NAME"><ex>{{ 'test' //i18n(ph="map name") }}</ex>{{ 'test' //i18n(ph="map name") }}</ph></msg>`
|
||||
];
|
||||
|
||||
const LF_LINE_ENDING_XMB = ``;
|
||||
const CRLF_LINE_ENDING_XMB = ``;
|
||||
|
|
Loading…
Reference in New Issue