fix(ivy): do not use MSG_ prefix for i18nPostprocess invocation (FW-779) (#27468)

Closure Compiler doesn't allow non-goo.getMsg const names to start with `MSG_`, so we should use different prefix for const that references a result of the `i18nPostprocess` fn invocation. With this update we also append file-based prefix to i18n constants (via $$ postfix) to ensure the names are unique across codebase of a project (otherwise it might lead to errors while compiling a project with Closure Compiler).

PR Close #27468
This commit is contained in:
Andrew Kushnir 2018-12-04 15:56:47 -08:00 committed by Miško Hevery
parent 44dfa606ed
commit fdf39985f0
4 changed files with 226 additions and 193 deletions

View File

@ -683,7 +683,7 @@ describe('ngtsc behavioral tests', () => {
`); `);
env.driveMain(); env.driveMain();
const jsContents = env.getContents('test.js'); const jsContents = env.getContents('test.js');
expect(jsContents).toContain('i18n(1, MSG_EXTERNAL_8321000940098097247);'); expect(jsContents).toContain('i18n(1, MSG_EXTERNAL_8321000940098097247$$TEST_TS_0);');
}); });
it('should take i18nUseExternalIds config option into account', () => { it('should take i18nUseExternalIds config option into account', () => {

View File

@ -14,7 +14,12 @@ import * as o from '../../../output/output_ast';
/* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */ /* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */
const TRANSLATION_PREFIX = 'MSG_'; const CLOSURE_TRANSLATION_PREFIX = 'MSG_';
const CLOSURE_TRANSLATION_MATCHER_REGEXP = new RegExp(`^${CLOSURE_TRANSLATION_PREFIX}`);
/* Prefix for non-`goog.getMsg` i18n-related vars */
const TRANSLATION_PREFIX = 'I18N_';
/** Closure uses `goog.getMsg(message)` to lookup translations */ /** Closure uses `goog.getMsg(message)` to lookup translations */
const GOOG_GET_MSG = 'goog.getMsg'; const GOOG_GET_MSG = 'goog.getMsg';
@ -219,7 +224,7 @@ export function formatI18nPlaceholderName(name: string): string {
* @returns Complete translation const prefix * @returns Complete translation const prefix
*/ */
export function getTranslationConstPrefix(extra: string): string { export function getTranslationConstPrefix(extra: string): string {
return `${TRANSLATION_PREFIX}${extra}`.toUpperCase(); return `${CLOSURE_TRANSLATION_PREFIX}${extra}`.toUpperCase();
} }
/** /**
@ -242,8 +247,14 @@ export function getTranslationDeclStmts(
statements.push(docStatements); statements.push(docStatements);
} }
if (transformFn) { if (transformFn) {
const raw = o.variable(`${variable.name}$$RAW`); statements.push(i18nTranslationToDeclStmt(variable, message, params));
statements.push(i18nTranslationToDeclStmt(raw, message, params));
// Closure Compiler doesn't allow non-goo.getMsg const names to start with `MSG_`,
// so we update variable name prefix in case post processing is required, so we can
// assign the result of post-processing function to the var that starts with `I18N_`
const raw = o.variable(variable.name !);
variable.name = variable.name !.replace(CLOSURE_TRANSLATION_MATCHER_REGEXP, TRANSLATION_PREFIX);
statements.push( statements.push(
variable.set(transformFn(raw)).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final])); variable.set(transformFn(raw)).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
} else { } else {

View File

@ -314,11 +314,13 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
i18nAllocateRef(messageId: string): o.ReadVarExpr { i18nAllocateRef(messageId: string): o.ReadVarExpr {
let name: string; let name: string;
const suffix = this.fileBasedI18nSuffix.toUpperCase();
if (this.i18nUseExternalIds) { if (this.i18nUseExternalIds) {
const prefix = getTranslationConstPrefix(`EXTERNAL_`); const prefix = getTranslationConstPrefix(`EXTERNAL_`);
name = `${prefix}${messageId}`; const uniqueSuffix = this.constantPool.uniqueName(suffix);
name = `${prefix}${messageId}$$${uniqueSuffix}`;
} else { } else {
const prefix = getTranslationConstPrefix(this.fileBasedI18nSuffix); const prefix = getTranslationConstPrefix(suffix);
name = this.constantPool.uniqueName(prefix); name = this.constantPool.uniqueName(prefix);
} }
return o.variable(name); return o.variable(name);