diff --git a/packages/compiler/src/render3/view/i18n/context.ts b/packages/compiler/src/render3/view/i18n/context.ts index 2be25642a4..f740c939b0 100644 --- a/packages/compiler/src/render3/view/i18n/context.ts +++ b/packages/compiler/src/render3/view/i18n/context.ts @@ -15,7 +15,6 @@ import {assembleBoundTextPlaceholders, getSeqNumberGenerator, updatePlaceholderM enum TagType { ELEMENT, TEMPLATE, - PROJECTION } /** @@ -105,10 +104,12 @@ export class I18nContext { this.appendTag(TagType.ELEMENT, node as i18n.TagPlaceholder, index, closed); } appendProjection(node: i18n.I18nMeta, index: number) { - // add open and close tags at the same time, - // since we process projected content separately - this.appendTag(TagType.PROJECTION, node as i18n.TagPlaceholder, index, false); - this.appendTag(TagType.PROJECTION, node as i18n.TagPlaceholder, index, true); + // Add open and close tags at the same time, since `` has no content, + // so when we come across `` we can register both open and close tags. + // Note: runtime i18n logic doesn't distinguish `` tag placeholders and + // regular element tag placeholders, so we generate element placeholders for both types. + this.appendTag(TagType.ELEMENT, node as i18n.TagPlaceholder, index, false); + this.appendTag(TagType.ELEMENT, node as i18n.TagPlaceholder, index, true); } /** @@ -215,9 +216,6 @@ function serializePlaceholderValue(value: any): string { case TagType.TEMPLATE: return template(value, value.closed); - case TagType.PROJECTION: - return projection(value, value.closed); - default: return value; } diff --git a/packages/core/src/render3/i18n/i18n_parse.ts b/packages/core/src/render3/i18n/i18n_parse.ts index 5952589415..60584ad733 100644 --- a/packages/core/src/render3/i18n/i18n_parse.ts +++ b/packages/core/src/render3/i18n/i18n_parse.ts @@ -39,7 +39,7 @@ const ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/; const MARKER = `�`; const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi; -const PH_REGEXP = /�(\/?[#*!]\d+):?\d*�/gi; +const PH_REGEXP = /�(\/?[#*]\d+):?\d*�/gi; /** * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see: @@ -120,7 +120,7 @@ export function i18nStartFirstCreatePass( // At this point value is something like: '/#1:2' (originally coming from '�/#1:2�') const isClosing = value.charCodeAt(0) === CharCode.SLASH; const type = value.charCodeAt(isClosing ? 1 : 0); - ngDevMode && assertOneOf(type, CharCode.STAR, CharCode.HASH, CharCode.EXCLAMATION); + ngDevMode && assertOneOf(type, CharCode.STAR, CharCode.HASH); const index = HEADER_OFFSET + Number.parseInt(value.substring((isClosing ? 2 : 1))); if (isClosing) { existingTNodeStack.shift(); diff --git a/packages/core/src/util/char_code.ts b/packages/core/src/util/char_code.ts index 0a6fe41461..c14efdacbd 100644 --- a/packages/core/src/util/char_code.ts +++ b/packages/core/src/util/char_code.ts @@ -12,7 +12,6 @@ export const enum CharCode { UPPER_CASE = ~32, // & with this will make the char uppercase SPACE = 32, // " " - EXCLAMATION = 33, // "!" DOUBLE_QUOTE = 34, // "\"" HASH = 35, // "#" SINGLE_QUOTE = 39, // "'"