diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts index 5cfb37f14e..0d921754c9 100644 --- a/packages/core/src/render3/i18n.ts +++ b/packages/core/src/render3/i18n.ts @@ -556,8 +556,8 @@ export function ɵɵi18nPostprocess( const templateIdsStack: number[] = [ROOT_TEMPLATE_ID]; result = result.replace(PP_PLACEHOLDERS_REGEXP, (m: any, phs: string, tmpl: string): string => { const content = phs || tmpl; - if (!matches[content]) { - const placeholders: PostprocessPlaceholder[] = []; + const placeholders: PostprocessPlaceholder[] = matches[content] || []; + if (!placeholders.length) { content.split('|').forEach((placeholder: string) => { const match = placeholder.match(PP_TEMPLATE_ID_REGEXP); const templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID; @@ -566,11 +566,12 @@ export function ɵɵi18nPostprocess( }); matches[content] = placeholders; } - if (!matches[content].length) { + + if (!placeholders.length) { throw new Error(`i18n postprocess: unmatched placeholder - ${content}`); } + const currentTemplateId = templateIdsStack[templateIdsStack.length - 1]; - const placeholders = matches[content]; let idx = 0; // find placeholder index that matches current template id for (let i = 0; i < placeholders.length; i++) { @@ -590,12 +591,6 @@ export function ɵɵi18nPostprocess( placeholders.splice(idx, 1); return placeholder; }); - - // verify that we injected all values - const hasUnmatchedValues = Object.keys(matches).some(key => !!matches[key].length); - if (hasUnmatchedValues) { - throw new Error(`i18n postprocess: unmatched values - ${JSON.stringify(matches)}`); - } } // return current result if no replacements specified diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts index 046aad5755..51f615d830 100644 --- a/packages/core/test/acceptance/i18n_spec.ts +++ b/packages/core/test/acceptance/i18n_spec.ts @@ -847,8 +847,7 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => { .toEqual('
Bonjour monde!
'); }); - // FW-1312: Wrong i18n code generated by the compiler when the template has 2 empty `span` - xit('should project translations with selectors', () => { + it('should project translations with selectors', () => { @Component({selector: 'child', template: ``}) class Child { } diff --git a/packages/core/test/render3/i18n_spec.ts b/packages/core/test/render3/i18n_spec.ts index 10df144f31..154e974cde 100644 --- a/packages/core/test/render3/i18n_spec.ts +++ b/packages/core/test/render3/i18n_spec.ts @@ -780,22 +780,10 @@ describe('Runtime i18n', () => { }); it('should throw in case we have invalid string', () => { - const arr = ['�*1:1��#2:1�', '�#4:2�', '�6:4�', '�/#2:1��/*1:1�']; - const str = `[${arr.join('|')}]`; - - const cases = [ - // less placeholders than we have - [`Start: ${str}, ${str} and ${str} end.`, {}], - - // more placeholders than we have - [`Start: ${str}, ${str} and ${str}, ${str} ${str} end.`, {}], - - // not enough ICU replacements - ['My ICU #1: �I18N_EXP_ICU�, My ICU #2: �I18N_EXP_ICU�', {ICU: ['ICU_VALUE_1']}] - ]; - cases.forEach(([input, replacements, output]) => { - expect(() => ɵɵi18nPostprocess(input as string, replacements as any)).toThrowError(); - }); + expect( + () => ɵɵi18nPostprocess( + 'My ICU #1: �I18N_EXP_ICU�, My ICU #2: �I18N_EXP_ICU�', {ICU: ['ICU_VALUE_1']})) + .toThrowError(); }); }); });