/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import {runInEachFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing'; import {loadStandardTestFiles} from '@angular/compiler-cli/src/ngtsc/testing'; import {platform} from 'os'; import {NgtscTestEnvironment} from './env'; const testFiles = loadStandardTestFiles({fakeCore: true, fakeCommon: true}); runInEachFileSystem(os => { let env!: NgtscTestEnvironment; if (os === 'Windows' || platform() === 'win32') { // xi18n tests are skipped on Windows as the paths in the expected message files are platform- // sensitive. These tests will be deleted when xi18n is removed, so it's not a major priority // to make them work with Windows. return; } describe('ngtsc xi18n', () => { beforeEach(() => { env = NgtscTestEnvironment.setup(testFiles); env.tsconfig(); writeTestCode(env); }); it('should extract xmb', () => { env.driveXi18n('xmb', 'messages.xmb'); expect(env.getContents('messages.xmb')).toEqual(EXPECTED_XMB); }); it('should extract xlf', () => { // Note that only in XLF mode do we pass a locale into the extraction. env.driveXi18n('xlf', 'messages.xlf', 'fr'); expect(env.getContents('messages.xlf')).toEqual(EXPECTED_XLIFF); }); it('should extract xlf', () => { env.driveXi18n('xlf2', 'messages.xliff2.xlf'); expect(env.getContents('messages.xliff2.xlf')).toEqual(EXPECTED_XLIFF2); }); it('should not emit js', () => { env.driveXi18n('xlf2', 'messages.xliff2.xlf'); env.assertDoesNotExist('src/module.js'); }); }); }); const EXPECTED_XMB = ` ]> src/basic.html:1src/comp2.ts:1src/basic.html:1translate me src/basic.html:3,4src/comp2.ts:3,4src/comp2.ts:2,3src/basic.html:3,4 Welcome src/icu.html:1,3src/icu.html:5{VAR_PLURAL, plural, =1 {book} other {books} } src/icu.html:4,6 foo { count, plural, =1 {...} other {...}}{ count, plural, =1 {...} other {...}} src/placeholders.html:1,3Name: <b><b>{{ name // i18n(ph="name") }}{{ name // i18n(ph="name") }}</b></b> `; const EXPECTED_XLIFF = ` translate me src/basic.html 1 src/comp2.ts 1 src/basic.html 1 desc meaning Welcome src/basic.html 3 src/comp2.ts 3 src/comp2.ts 2 src/basic.html 3 {VAR_PLURAL, plural, =1 {book} other {books} } src/icu.html 1 with ICU foo src/icu.html 4 with ICU and other things {VAR_PLURAL, plural, =1 {book} other {books} } src/icu.html 5 Name: src/placeholders.html 1 with placeholders `; const EXPECTED_XLIFF2 = ` desc meaning src/basic.html:1 src/comp2.ts:1 src/basic.html:1 translate me src/basic.html:3,4 src/comp2.ts:3,4 src/comp2.ts:2,3 src/basic.html:3,4 Welcome with ICU src/icu.html:1,3 src/icu.html:5 {VAR_PLURAL, plural, =1 {book} other {books} } with ICU and other things src/icu.html:4,6 foo with placeholders src/placeholders.html:1,3 Name: `; /** * Note: the indentation here is load-bearing. */ function writeTestCode(env: NgtscTestEnvironment): void { const welcomeMessage = ` Welcome `; env.write('src/basic.html', `

${welcomeMessage}

`); env.write('src/comp1.ts', ` import {Component} from '@angular/core'; @Component({ selector: 'basic', templateUrl: './basic.html', }) export class BasicCmp1 {}`); env.write('src/comp2.ts', ` import {Component} from '@angular/core'; @Component({ selector: 'basic2', template: \`

${welcomeMessage}

\`, }) export class BasicCmp2 {} @Component({ selector: 'basic4', template: \`

${welcomeMessage}

\`, }) export class BasicCmp4 {}`); env.write('src/comp3.ts', ` import {Component} from '@angular/core'; @Component({ selector: 'basic3', templateUrl: './basic.html', }) export class BasicCmp3 {}`); env.write('src/placeholders.html', `
Name: {{ name // i18n(ph="name") }}
`); env.write('src/placeholder_cmp.ts', ` import {Component} from '@angular/core'; @Component({ selector: 'placeholders', templateUrl: './placeholders.html', }) export class PlaceholderCmp { name = 'whatever'; }`); env.write('src/icu.html', `
{ count, plural, =1 {book} other {books} }
foo { count, plural, =1 {book} other {books} }
`); env.write('src/icu_cmp.ts', ` import {Component} from '@angular/core'; @Component({ selector: 'icu', templateUrl: './icu.html', }) export class IcuCmp { count = 3; }`); env.write('src/module.ts', ` import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {BasicCmp1} from './comp1'; import {BasicCmp2, BasicCmp4} from './comp2'; import {BasicCmp3} from './comp3'; import {PlaceholderCmp} from './placeholder_cmp'; import {IcuCmp} from './icu_cmp'; @NgModule({ declarations: [ BasicCmp1, BasicCmp2, BasicCmp3, BasicCmp4, PlaceholderCmp, IcuCmp, ], imports: [CommonModule], }) export class I18nModule {} `); }