From b5e8c28640ba9eb064bef08cd4366d417b656589 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 10 Mar 2021 12:01:07 +0000 Subject: [PATCH] fix(localize): render correct closing tag placeholder names in XLIFF 2 (#41152) When there are elements in a translated message, the start and end tags are encoded as placeholders. The names of these placeholders are computed from the name of the element. For example ` will be `START_LINK` and `` will be `CLOSE_LINK`. If there are more than one element with the same name, but different attributes, then the starting placeholder name is made unique. For example `` would be `START_LINK`, while `` in the same message would then be called `START_LINK_1`. But the closing tags will not be made unique since there are no attrbutes; the always have the same text ``, which will produce, for example, `CLOSE_LINK`. Previously, when extracting XLIFF 2 formatted translation files, the closing tag placeholder names were computed incorrectly from the opening tag placeholder names. For example `CLOSE_LINK_1`. This commit strips these `_1` type endings from the start tag placeholder name when computing the closing tag placeholder name. It also ensures that the `type` of the placeholder is computed accurately in these cases too. Fixes #41142 PR Close #41152 --- .../xliff2_translation_serializer.ts | 6 ++++-- .../xliff2_translation_serializer_spec.ts | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/localize/src/tools/src/extract/translation_files/xliff2_translation_serializer.ts b/packages/localize/src/tools/src/extract/translation_files/xliff2_translation_serializer.ts index a5a75f7ec5..eff40c08cf 100644 --- a/packages/localize/src/tools/src/extract/translation_files/xliff2_translation_serializer.ts +++ b/packages/localize/src/tools/src/extract/translation_files/xliff2_translation_serializer.ts @@ -113,7 +113,9 @@ export class Xliff2TranslationSerializer implements TranslationSerializer { const text = substitutionLocations?.[placeholderName]?.text; if (placeholderName.startsWith('START_')) { - const closingPlaceholderName = placeholderName.replace(/^START/, 'CLOSE'); + // Replace the `START` with `CLOSE` and strip off any `_1` ids from the end. + const closingPlaceholderName = + placeholderName.replace(/^START/, 'CLOSE').replace(/_\d+$/, ''); const closingText = substitutionLocations?.[closingPlaceholderName]?.text; const attrs: Record = { id: `${this.currentPlaceholderId++}`, @@ -186,7 +188,7 @@ export class Xliff2TranslationSerializer implements TranslationSerializer { * and links are special cases. */ function getTypeForPlaceholder(placeholder: string): string|null { - const tag = placeholder.replace(/^(START_|CLOSE_)/, ''); + const tag = placeholder.replace(/^(START_|CLOSE_)/, '').replace(/_\d+$/, ''); switch (tag) { case 'BOLD_TEXT': case 'EMPHASISED_TEXT': diff --git a/packages/localize/src/tools/test/extract/translation_files/xliff2_translation_serializer_spec.ts b/packages/localize/src/tools/test/extract/translation_files/xliff2_translation_serializer_spec.ts index 247184be82..fbd5ab49d5 100644 --- a/packages/localize/src/tools/test/extract/translation_files/xliff2_translation_serializer_spec.ts +++ b/packages/localize/src/tools/test/extract/translation_files/xliff2_translation_serializer_spec.ts @@ -301,6 +301,27 @@ runInEachFileSystem(() => { 'abc', ); }); + + it('should render the "type" for link elements', () => { + const serializer = new Xliff2TranslationSerializer( + 'xx', absoluteFrom('/project'), useLegacyIds, options); + const output = serializer.serialize( + [mockMessage('6', ['a', 'b', 'c'], ['START_LINK', 'CLOSE_LINK'], {})]); + expect(output).toContain( + 'abc', + ); + }); + + it('should render generic close tag placeholders for additional elements', () => { + const serializer = new Xliff2TranslationSerializer( + 'xx', absoluteFrom('/project'), useLegacyIds, options); + const output = serializer.serialize([mockMessage( + '6', ['a', 'b', 'c', 'd', 'e'], + ['START_LINK', 'CLOSE_LINK', 'START_LINK_1', 'CLOSE_LINK'], {})]); + expect(output).toContain( + 'abcde', + ); + }); }); }); });