refactor(compiler): Add more comments for i18n template pipeline phases (#52503)

Adds some additional comments about the i18n termplate pipeline phases
to more clearly document how they work.

PR Close #52503
This commit is contained in:
Miles Malerba
2023-11-03 13:47:06 -07:00
committed by Andrew Scott
parent fa9bca23f7
commit 91dbcb5eab
5 changed files with 18 additions and 3 deletions
@@ -10,7 +10,14 @@ import * as ir from '../../ir';
import {CompilationJob} from '../compilation';
/**
* Create i18n context ops that will be used to generate the final i18n messages.
* Create one helper context op per i18n block (including generate descending blocks).
*
* Also, if an ICU exists inside an i18n block that also contains other localizable content (such as
* string), create an additional helper context op for the ICU.
*
* These context ops are later used for generating i18n messages. (Although we generate at least one
* context op per nested view, we will collect them up the tree later, to generate a top-level
* message.)
*/
export function createI18nContexts(job: CompilationJob) {
let currentI18nOp: ir.I18nStartOp|null = null;
@@ -35,10 +42,13 @@ export function createI18nContexts(job: CompilationJob) {
throw Error('Unexpected ICU outside of an i18n block.');
}
if (op.message.id !== currentI18nOp.message.id) {
// There was an enclosing i18n block around this ICU somewhere.
xref = job.allocateXrefId();
unit.create.push(ir.createI18nContextOp(xref, currentI18nOp.xref, op.message, null!));
op.context = xref;
} else {
// The i18n block was generated because of this ICU, OR it was explicit, but the ICU is
// the only localizable content inside of it.
op.context = currentI18nOp.context;
}
break;
@@ -51,6 +51,7 @@ export function createI18nIcuExpressions(job: CompilationJob) {
ir.createI18nExpressionOp(
i18nContext.xref, i18nBlock.xref, i18nBlock.handle,
new ir.LexicalReadExpr(icuOp.icu.expression), icuOp.icu.expressionPlaceholder,
// ICU-based i18n Expressions are resolved during post-processing.
ir.I18nParamResolutionTime.Postproccessing, null!));
break;
}
@@ -52,6 +52,8 @@ export function extractI18nText(job: CompilationJob): void {
for (let i = 0; i < op.interpolation.expressions.length; i++) {
const expr = op.interpolation.expressions[i];
const placeholder = op.i18nPlaceholders[i];
// For now, this i18nExpression depends on the slot context of the enclosing i18n block.
// Later, we will modify this, and advance to a different point.
ops.push(ir.createI18nExpressionOp(
i18nOp.context!, i18nOp.xref, i18nOp.handle, expr, placeholder.name,
ir.I18nParamResolutionTime.Creation, expr.sourceSpan ?? op.sourceSpan));
@@ -10,7 +10,7 @@ import * as ir from '../../ir';
import {ComponentCompilationJob} from '../compilation';
/**
* Merge i18n contexts for child i18n blocks into their parent context.
* Merge i18n contexts for child i18n blocks into their ancestor root contexts.
*/
export function mergeI18nContexts(job: ComponentCompilationJob) {
// Record all of the i18n and extracted message ops for use later.
@@ -12,7 +12,9 @@ import {ComponentCompilationJob, ViewCompilationUnit} from '../compilation';
/**
* Propagate i18n blocks down through child templates that act as placeholders in the root i18n
* message.
* message. Specifically, perform an in-order traversal of all the views, and add i18nStart/i18nEnd
* op pairs into descending views. Also, assign an increasing sub-template index to each
* descending view.
*/
export function propagateI18nBlocks(job: ComponentCompilationJob): void {
propagateI18nBlocksToTemplates(job.root, 0);