Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ivy): i18n - turn on legacy message-id support by default #33053

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"extends": "./tsconfig.app.json",
"angularCompilerOptions": {
"enableIvy": true,
"i18nLegacyMessageIdFormat": "xlf"
"i18nInFormat": "xlf"
}
}
9 changes: 0 additions & 9 deletions packages/compiler-cli/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export function main(
if (configErrors.length) {
return reportErrorsAndExit(configErrors, /*options*/ undefined, consoleError);
}
warnForDeprecatedOptions(options);
if (watch) {
const result = watchMode(project, options, consoleError);
return reportErrorsAndExit(result.firstCompileResult, options, consoleError);
Expand Down Expand Up @@ -227,14 +226,6 @@ export function watchMode(
}, options, options => createEmitCallback(options)));
}

function warnForDeprecatedOptions(options: api.CompilerOptions) {
if (options.i18nLegacyMessageIdFormat !== undefined) {
console.warn(
'The `i18nLegacyMessageIdFormat` option is deprecated.\n' +
'Migrate your legacy translation files to the new `$localize` message id format and remove this option.');
}
}

// CLI entry point
if (require.main === module) {
const args = process.argv.slice(2);
Expand Down
7 changes: 6 additions & 1 deletion packages/compiler-cli/src/ngtsc/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ export class NgtscProgram implements api.Program {
this.reflector, evaluator, metaRegistry, this.metaReader !, scopeReader, scopeRegistry,
this.isCore, this.resourceManager, this.rootDirs,
this.options.preserveWhitespaces || false, this.options.i18nUseExternalIds !== false,
this.options.i18nLegacyMessageIdFormat || '', this.moduleResolver, this.cycleAnalyzer,
this.getI18nLegacyMessageFormat(), this.moduleResolver, this.cycleAnalyzer,
this.refEmitter, this.defaultImportTracker, this.incrementalState),
new DirectiveDecoratorHandler(
this.reflector, evaluator, metaRegistry, this.defaultImportTracker, this.isCore),
Expand All @@ -529,6 +529,11 @@ export class NgtscProgram implements api.Program {
this.sourceToFactorySymbols, scopeRegistry);
}

private getI18nLegacyMessageFormat(): string {
return this.options.enableI18nLegacyMessageIdFormat !== false && this.options.i18nInFormat ||
'';
}

private get reflector(): TypeScriptReflectionHost {
if (this._reflector === undefined) {
this._reflector = new TypeScriptReflectionHost(this.tsProgram.getTypeChecker());
Expand Down
13 changes: 6 additions & 7 deletions packages/compiler-cli/src/transformers/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,16 @@ export interface CompilerOptions extends ts.CompilerOptions {
i18nUseExternalIds?: boolean;

/**
* Render `$localize` message ids with the specified legacy format (xlf, xlf2 or xmb).
* Render `$localize` message ids with the legacy format (xlf, xlf2 or xmb) specified in
* `i18nInFormat`.
*
* This is only active if we are building with `enableIvy: true` and a valid
* `i18nInFormat` has been provided. The default value for now is `true`.
mhevery marked this conversation as resolved.
Show resolved Hide resolved
*
* Use this option when use are using the `$localize` based localization messages but
* have not migrated the translation files to use the new `$localize` message id format.
*
* @deprecated
* `i18nLegacyMessageIdFormat` should only be used while migrating from legacy message id
* formatted translation files and will be removed at the same time as ViewEngine support is
* removed.
*/
i18nLegacyMessageIdFormat?: string;
enableI18nLegacyMessageIdFormat?: boolean;

// Whether to remove blank text nodes from compiled templates. It is `false` by default starting
// from Angular 6.
Expand Down
69 changes: 44 additions & 25 deletions packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2052,60 +2052,79 @@ runInEachFileSystem(os => {
expect(jsContents).not.toContain('MSG_EXTERNAL_');
});

it('should render legacy id when i18nLegacyMessageIdFormat config is set to xlf', () => {
env.tsconfig({i18nLegacyMessageIdFormat: 'xlf'});
env.write(`test.ts`, `
it('should render legacy id when `enableI18nLegacyMessageIdFormat` is not false and `i18nInFormat` is set to "xlf"',
() => {
env.tsconfig({i18nInFormat: 'xlf'});
env.write(`test.ts`, `
import {Component} from '@angular/core';
@Component({
selector: 'test',
template: '<div i18n>Some text</div>'
})
class FooCmp {}`);
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@5dbba0a3da8dff890e20cf76eb075d58900fbcd3:Some text');
});
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@5dbba0a3da8dff890e20cf76eb075d58900fbcd3:Some text');
});

it('should render legacy id when i18nLegacyMessageIdFormat config is set to xlf2', () => {
env.tsconfig({i18nLegacyMessageIdFormat: 'xlf2'});
env.write(`test.ts`, `
it('should render legacy id when `enableI18nLegacyMessageIdFormat` is not false and `i18nInFormat` is set to "xlf2"',
() => {
env.tsconfig({i18nInFormat: 'xlf2'});
env.write(`test.ts`, `
import {Component} from '@angular/core';
@Component({
selector: 'test',
template: '<div i18n>Some text</div>'
})
class FooCmp {}`);
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@8321000940098097247:Some text');
});
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@8321000940098097247:Some text');
});

it('should render legacy id when i18nLegacyMessageIdFormat config is set to xmb', () => {
env.tsconfig({i18nLegacyMessageIdFormat: 'xmb'});
env.write(`test.ts`, `
it('should render legacy id when `enableI18nLegacyMessageIdFormat` is not false and `i18nInFormat` is set to "xmb"',
() => {
env.tsconfig({i18nInFormat: 'xmb'});
env.write(`test.ts`, `
import {Component} from '@angular/core';
@Component({
selector: 'test',
template: '<div i18n>Some text</div>'
})
class FooCmp {}`);
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@8321000940098097247:Some text');
});
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@8321000940098097247:Some text');
});

it('should render custom id even if i18nLegacyMessageIdFormat config is set', () => {
env.tsconfig({i18nLegacyMessageIdFormat: 'xlf'});
env.write(`test.ts`, `
it('should render custom id even if `enableI18nLegacyMessageIdFormat` is not false and `i18nInFormat` is set',
() => {
env.tsconfig({i18nFormatIn: 'xlf'});
env.write(`test.ts`, `
import {Component} from '@angular/core';
@Component({
selector: 'test',
template: '<div i18n="@@custom">Some text</div>'
})
class FooCmp {}`);
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@custom:Some text');
});

it('should not render legacy id when `enableI18nLegacyMessageIdFormat` is set to false', () => {
env.tsconfig({enableI18nLegacyMessageIdFormat: false, i18nInFormat: 'xmb'});
env.write(`test.ts`, `
import {Component} from '@angular/core';
@Component({
selector: 'test',
template: '<div i18n>Some text</div>'
})
class FooCmp {}`);
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(':@@custom:Some text');
// Note that the colon would only be there if there is an id attached to the string.
expect(jsContents).not.toContain(':Some text');
});

it('@Component\'s `interpolation` should override default interpolation config', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/i18n/i18n_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {ParseSourceSpan} from '../parse_util';
export class Message {
sources: MessageSpan[];
id: string = this.customId;
/** The id to use if there is no custom id and if `i18nLegacyMessageIdFormat` is true */
/** The id to use if there is no custom id and if `i18nLegacyMessageIdFormat` is not empty */
legacyId?: string = '';

/**
Expand Down