fix(ngcc): render legacy i18n message ids by default (#34135)
By ensuring that legacy i18n message ids are rendered into the templates of components for packages processed by ngcc, we ensure that these packages can be used in an application that may provide translations in a legacy format. Fixes #34056 PR Close #34135
This commit is contained in:
parent
cebe49d3c9
commit
f16f6a290b
|
@ -52,6 +52,17 @@ if (require.main === module) {
|
|||
'The Angular CLI does this already, so it is safe to use this option if the project is being built via the CLI.',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('legacy-message-ids', {
|
||||
describe: 'Render `$localize` messages with legacy format ids.\n' +
|
||||
'The default value is `true`. Only set this to `false` if you do not want legacy message ids to\n' +
|
||||
'be rendered. For example, if you are not using legacy message ids in your translation files\n' +
|
||||
'AND are not doing compile-time inlining of translations, in which case the extra message ids\n' +
|
||||
'would add unwanted size to the final source bundle.\n' +
|
||||
'It is safe to leave this set to true if you are doing compile-time inlining because the extra\n' +
|
||||
'legacy message ids will all be stripped during translation.',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
})
|
||||
.option('async', {
|
||||
describe:
|
||||
'Whether to compile asynchronously. This is enabled by default as it allows compilations to be parallelized.\n' +
|
||||
|
@ -81,6 +92,7 @@ if (require.main === module) {
|
|||
const compileAllFormats = !options['first-only'];
|
||||
const createNewEntryPointFormats = options['create-ivy-entry-points'];
|
||||
const logLevel = options['l'] as keyof typeof LogLevel | undefined;
|
||||
const enableI18nLegacyMessageIdFormat = options['legacy-message-ids'];
|
||||
|
||||
(async() => {
|
||||
try {
|
||||
|
@ -93,6 +105,7 @@ if (require.main === module) {
|
|||
compileAllFormats,
|
||||
createNewEntryPointFormats,
|
||||
logger,
|
||||
enableI18nLegacyMessageIdFormat,
|
||||
async: options['async'],
|
||||
});
|
||||
|
||||
|
|
|
@ -97,6 +97,19 @@ export interface SyncNgccOptions {
|
|||
* Default: `false` (i.e. run synchronously)
|
||||
*/
|
||||
async?: false;
|
||||
|
||||
/**
|
||||
* Render `$localize` messages with legacy format ids.
|
||||
*
|
||||
* The default value is `true`. Only set this to `false` if you do not want legacy message ids to
|
||||
* be rendered. For example, if you are not using legacy message ids in your translation files
|
||||
* AND are not doing compile-time inlining of translations, in which case the extra message ids
|
||||
* would add unwanted size to the final source bundle.
|
||||
*
|
||||
* It is safe to leave this set to true if you are doing compile-time inlining because the extra
|
||||
* legacy message ids will all be stripped during translation.
|
||||
*/
|
||||
enableI18nLegacyMessageIdFormat?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,8 +137,8 @@ export function mainNgcc(options: SyncNgccOptions): void;
|
|||
export function mainNgcc(
|
||||
{basePath, targetEntryPointPath, propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES,
|
||||
compileAllFormats = true, createNewEntryPointFormats = false,
|
||||
logger = new ConsoleLogger(LogLevel.info), pathMappings, async = false}: NgccOptions): void|
|
||||
Promise<void> {
|
||||
logger = new ConsoleLogger(LogLevel.info), pathMappings, async = false,
|
||||
enableI18nLegacyMessageIdFormat = true}: NgccOptions): void|Promise<void> {
|
||||
// Execute in parallel, if async execution is acceptable and there are more than 1 CPU cores.
|
||||
const inParallel = async && (os.cpus().length > 1);
|
||||
|
||||
|
@ -242,7 +255,7 @@ export function mainNgcc(
|
|||
|
||||
const bundle = makeEntryPointBundle(
|
||||
fileSystem, entryPoint, formatPath, isCore, format, processDts, pathMappings, true,
|
||||
false);
|
||||
enableI18nLegacyMessageIdFormat);
|
||||
|
||||
logger.info(`Compiling ${entryPoint.name} : ${formatProperty} as ${format}`);
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@ runInEachFileSystem(() => {
|
|||
expect(jsContents).not.toMatch(/\$localize\s*`/);
|
||||
expect(jsContents)
|
||||
.toMatch(
|
||||
/\$localize\(ɵngcc\d+\.__makeTemplateObject\(\[":some:`description`:A message"], \[":some\\\\:\\\\`description\\\\`:A message"]\)\);/);
|
||||
/\$localize\(ɵngcc\d+\.__makeTemplateObject\(\[":some:`description`\\u241Fefc92f285b3c24b083a8a594f62c7fccf3118766\\u241F3806630072763809030:A message"], \[":some\\\\:\\\\`description\\\\`\\u241Fefc92f285b3c24b083a8a594f62c7fccf3118766\\u241F3806630072763809030:A message"]\)\);/);
|
||||
});
|
||||
|
||||
describe('in async mode', () => {
|
||||
|
@ -1219,6 +1219,62 @@ runInEachFileSystem(() => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('legacy message ids', () => {
|
||||
it('should render legacy message ids when compiling i18n tags in component templates', () => {
|
||||
compileIntoApf('test-package', {
|
||||
'/index.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: '[base]',
|
||||
template: '<div i18n>Some message</div>'
|
||||
})
|
||||
export class AppComponent {}
|
||||
`,
|
||||
});
|
||||
|
||||
mainNgcc({
|
||||
basePath: '/node_modules',
|
||||
targetEntryPointPath: 'test-package',
|
||||
propertiesToConsider: ['esm2015'],
|
||||
});
|
||||
|
||||
|
||||
const jsContents = fs.readFile(_(`/node_modules/test-package/esm2015/src/index.js`));
|
||||
expect(jsContents)
|
||||
.toContain(
|
||||
'$localize `:␟888aea0e46f7e9dddbd95fc1ef380a3ff70ada9d␟1812794354835616626:Some message');
|
||||
});
|
||||
|
||||
it('should not render legacy message ids when compiling i18n tags in component templates if `enableI18nLegacyMessageIdFormat` is false',
|
||||
() => {
|
||||
compileIntoApf('test-package', {
|
||||
'/index.ts': `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: '[base]',
|
||||
template: '<div i18n>Some message</div>'
|
||||
})
|
||||
export class AppComponent {}
|
||||
`,
|
||||
});
|
||||
|
||||
mainNgcc({
|
||||
basePath: '/node_modules',
|
||||
targetEntryPointPath: 'test-package',
|
||||
propertiesToConsider: ['esm2015'],
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
});
|
||||
|
||||
|
||||
const jsContents = fs.readFile(_(`/node_modules/test-package/esm2015/src/index.js`));
|
||||
expect(jsContents).not.toContain('␟888aea0e46f7e9dddbd95fc1ef380a3ff70ada9d');
|
||||
expect(jsContents).not.toContain('␟1812794354835616626');
|
||||
expect(jsContents).not.toContain('␟');
|
||||
});
|
||||
});
|
||||
|
||||
function loadPackage(
|
||||
packageName: string, basePath: AbsoluteFsPath = _('/node_modules')): EntryPointPackageJson {
|
||||
return JSON.parse(fs.readFile(fs.resolve(basePath, packageName, 'package.json')));
|
||||
|
|
Loading…
Reference in New Issue