feat(ivy): ICU support for Ivy (#26794)

PR Close #26794
This commit is contained in:
Andrew Kushnir
2018-10-18 10:08:51 -07:00
committed by Misko Hevery
parent a4934a74b6
commit 92e80af875
28 changed files with 3106 additions and 933 deletions

View File

@ -7,21 +7,12 @@
*/
import * as o from './output/output_ast';
import {I18nMeta, parseI18nMeta} from './render3/view/i18n';
import {OutputContext, error} from './util';
const CONSTANT_PREFIX = '_c';
// Closure variables holding messages must be named `MSG_[A-Z0-9]+`
const TRANSLATION_PREFIX = 'MSG_';
export const enum DefinitionKind {Injector, Directive, Component, Pipe}
/**
* Closure uses `goog.getMsg(message)` to lookup translations
*/
const GOOG_GET_MSG = 'goog.getMsg';
/**
* Context to use when producing a key.
*
@ -78,8 +69,6 @@ class FixupExpression extends o.Expression {
*/
export class ConstantPool {
statements: o.Statement[] = [];
private translations = new Map<string, o.Expression>();
private deferredTranslations = new Map<o.ReadVarExpr, number>();
private literals = new Map<string, FixupExpression>();
private literalFactories = new Map<string, o.Expression>();
private injectorDefinitions = new Map<any, FixupExpression>();
@ -115,60 +104,6 @@ export class ConstantPool {
return fixup;
}
getDeferredTranslationConst(suffix: string): o.ReadVarExpr {
const index = this.statements.push(new o.ExpressionStatement(o.NULL_EXPR)) - 1;
const variable = o.variable(this.freshTranslationName(suffix));
this.deferredTranslations.set(variable, index);
return variable;
}
setDeferredTranslationConst(variable: o.ReadVarExpr, message: string): void {
const index = this.deferredTranslations.get(variable) !;
this.statements[index] = this.getTranslationDeclStmt(variable, message);
}
getTranslationDeclStmt(variable: o.ReadVarExpr, message: string): o.DeclareVarStmt {
const fnCall = o.variable(GOOG_GET_MSG).callFn([o.literal(message)]);
return variable.set(fnCall).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]);
}
appendTranslationMeta(meta: string|I18nMeta) {
const parsedMeta = typeof meta === 'string' ? parseI18nMeta(meta) : meta;
const docStmt = i18nMetaToDocStmt(parsedMeta);
if (docStmt) {
this.statements.push(docStmt);
}
}
// Generates closure specific code for translation.
//
// ```
// /**
// * @desc description?
// * @meaning meaning?
// */
// const MSG_XYZ = goog.getMsg('message');
// ```
getTranslation(message: string, meta: string, suffix: string): o.Expression {
const parsedMeta = parseI18nMeta(meta);
// The identity of an i18n message depends on the message and its meaning
const key = parsedMeta.meaning ? `${message}\u0000\u0000${parsedMeta.meaning}` : message;
const exp = this.translations.get(key);
if (exp) {
return exp;
}
const variable = o.variable(this.freshTranslationName(suffix));
this.appendTranslationMeta(parsedMeta);
this.statements.push(this.getTranslationDeclStmt(variable, message));
this.translations.set(key, variable);
return variable;
}
getDefinition(type: any, kind: DefinitionKind, ctx: OutputContext, forceShared: boolean = false):
o.Expression {
const definitions = this.definitionsOf(kind);
@ -279,10 +214,6 @@ export class ConstantPool {
private freshName(): string { return this.uniqueName(CONSTANT_PREFIX); }
private freshTranslationName(suffix: string): string {
return this.uniqueName(TRANSLATION_PREFIX + suffix).toUpperCase();
}
private keyOf(expression: o.Expression) {
return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT);
}
@ -349,21 +280,4 @@ function invalid<T>(arg: o.Expression | o.Statement): never {
function isVariable(e: o.Expression): e is o.ReadVarExpr {
return e instanceof o.ReadVarExpr;
}
// Converts i18n meta informations for a message (id, description, meaning)
// to a JsDoc statement formatted as expected by the Closure compiler.
function i18nMetaToDocStmt(meta: I18nMeta): o.JSDocCommentStmt|null {
const tags: o.JSDocTag[] = [];
if (meta.id || meta.description) {
const text = meta.id ? `[BACKUP_MESSAGE_ID:${meta.id}] ${meta.description}` : meta.description;
tags.push({tagName: o.JSDocTagName.Desc, text: text !.trim()});
}
if (meta.meaning) {
tags.push({tagName: o.JSDocTagName.Meaning, text: meta.meaning});
}
return tags.length == 0 ? null : new o.JSDocCommentStmt(tags);
}
}