refactor(ivy): update the compiler to emit $localize
tags (#31609)
This commit changes the Angular compiler (ivy-only) to generate `$localize` tagged strings for component templates that use `i18n` attributes. BREAKING CHANGE Since `$localize` is a global function, it must be included in any applications that use i18n. This is achieved by importing the `@angular/localize` package into an appropriate bundle, where it will be executed before the renderer needs to call `$localize`. For CLI based projects, this is best done in the `polyfills.ts` file. ```ts import '@angular/localize'; ``` For non-CLI applications this could be added as a script to the index.html file or another suitable script file. PR Close #31609
This commit is contained in:

committed by
Misko Hevery

parent
b21397bde9
commit
fa79f51645
@ -361,6 +361,19 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
|
||||
return null;
|
||||
}
|
||||
|
||||
visitLocalizedString(ast: o.LocalizedString, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(ast, '$localize `' + ast.messageParts[0]);
|
||||
for (let i = 1; i < ast.messageParts.length; i++) {
|
||||
ctx.print(ast, '${');
|
||||
ast.expressions[i - 1].visitExpression(this, ctx);
|
||||
// Add the placeholder name annotation to support runtime inlining
|
||||
ctx.print(ast, `}:${ast.placeHolderNames[i - 1]}:`);
|
||||
ctx.print(ast, ast.messageParts[i]);
|
||||
}
|
||||
ctx.print(ast, '`');
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any;
|
||||
|
||||
visitConditionalExpr(ast: o.ConditionalExpr, ctx: EmitterVisitorContext): any {
|
||||
|
@ -480,6 +480,26 @@ export class LiteralExpr extends Expression {
|
||||
}
|
||||
|
||||
|
||||
export class LocalizedString extends Expression {
|
||||
constructor(
|
||||
public messageParts: string[], public placeHolderNames: string[],
|
||||
public expressions: Expression[], sourceSpan?: ParseSourceSpan|null) {
|
||||
super(STRING_TYPE, sourceSpan);
|
||||
}
|
||||
|
||||
isEquivalent(e: Expression): boolean {
|
||||
// return e instanceof LocalizedString && this.message === e.message;
|
||||
return false;
|
||||
}
|
||||
|
||||
isConstant() { return false; }
|
||||
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitLocalizedString(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ExternalExpr extends Expression {
|
||||
constructor(
|
||||
public value: ExternalReference, type?: Type|null, public typeParams: Type[]|null = null,
|
||||
@ -749,6 +769,7 @@ export interface ExpressionVisitor {
|
||||
visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any;
|
||||
visitInstantiateExpr(ast: InstantiateExpr, context: any): any;
|
||||
visitLiteralExpr(ast: LiteralExpr, context: any): any;
|
||||
visitLocalizedString(ast: LocalizedString, context: any): any;
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any;
|
||||
visitConditionalExpr(ast: ConditionalExpr, context: any): any;
|
||||
visitNotExpr(ast: NotExpr, context: any): any;
|
||||
@ -1074,6 +1095,14 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
|
||||
|
||||
visitLiteralExpr(ast: LiteralExpr, context: any): any { return this.transformExpr(ast, context); }
|
||||
|
||||
visitLocalizedString(ast: LocalizedString, context: any): any {
|
||||
return this.transformExpr(
|
||||
new LocalizedString(
|
||||
ast.messageParts, ast.placeHolderNames,
|
||||
this.visitAllExpressions(ast.expressions, context), ast.sourceSpan),
|
||||
context);
|
||||
}
|
||||
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any {
|
||||
return this.transformExpr(ast, context);
|
||||
}
|
||||
@ -1291,6 +1320,9 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
|
||||
visitLiteralExpr(ast: LiteralExpr, context: any): any {
|
||||
return this.visitExpression(ast, context);
|
||||
}
|
||||
visitLocalizedString(ast: LocalizedString, context: any): any {
|
||||
return this.visitExpression(ast, context);
|
||||
}
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any {
|
||||
if (ast.typeParams) {
|
||||
ast.typeParams.forEach(type => type.visitType(this, context));
|
||||
@ -1551,6 +1583,12 @@ export function literal(
|
||||
return new LiteralExpr(value, type, sourceSpan);
|
||||
}
|
||||
|
||||
export function localizedString(
|
||||
messageParts: string[], placeholderNames: string[], expressions: Expression[],
|
||||
sourceSpan?: ParseSourceSpan | null): LocalizedString {
|
||||
return new LocalizedString(messageParts, placeholderNames, expressions, sourceSpan);
|
||||
}
|
||||
|
||||
export function isNull(exp: Expression): boolean {
|
||||
return exp instanceof LiteralExpr && exp.value === null;
|
||||
}
|
||||
|
@ -5,11 +5,7 @@
|
||||
* 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 {CompileReflector} from '../compile_reflector';
|
||||
|
||||
import * as o from './output_ast';
|
||||
import {debugOutputAstAsTypeScript} from './ts_emitter';
|
||||
|
||||
@ -239,6 +235,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
return new clazz(...args);
|
||||
}
|
||||
visitLiteralExpr(ast: o.LiteralExpr, ctx: _ExecutionContext): any { return ast.value; }
|
||||
visitLocalizedString(ast: o.LocalizedString, context: any): any { return null; }
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any {
|
||||
return this.reflector.resolveExternalReference(ast.value);
|
||||
}
|
||||
|
Reference in New Issue
Block a user