From aa441274c7c588aeed504e1ee1ef19c44d411d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 16 May 2023 10:18:43 +0200 Subject: [PATCH] [FIX] compiler: apply translations to t-set text body Before this commit, the translate function was not applied to text content inside the body of a t-set (unless that content was itself inside some html). This is not clearly not intended. To fix it, we just need to call the translate function at the appropriate moment. closes #1434 --- src/compiler/code_generator.ts | 13 ++- .../__snapshots__/translation.test.ts.snap | 89 +++++++++++++++++++ tests/compiler/translation.test.ts | 70 +++++++++++++++ 3 files changed, 168 insertions(+), 4 deletions(-) diff --git a/src/compiler/code_generator.ts b/src/compiler/code_generator.ts index d56bbb2b..3c0d6498 100644 --- a/src/compiler/code_generator.ts +++ b/src/compiler/code_generator.ts @@ -447,6 +447,11 @@ export class CodeGenerator { .join(""); } + translate(str: string): string { + const match = translationRE.exec(str) as any; + return match[1] + this.translateFn(match[2]) + match[3]; + } + /** * @returns the newly created block name, if any */ @@ -527,8 +532,7 @@ export class CodeGenerator { let value = ast.value; if (value && ctx.translate !== false) { - const match = translationRE.exec(value) as any; - value = match[1] + this.translateFn(match[2]) + match[3]; + value = this.translate(value); } if (!ctx.inPreTag) { value = value.replace(whitespaceRE, " "); @@ -1095,10 +1099,11 @@ export class CodeGenerator { } else { let value: string; if (ast.defaultValue) { + const defaultValue = ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue; if (ast.value) { - value = `withDefault(${expr}, \`${ast.defaultValue}\`)`; + value = `withDefault(${expr}, \`${defaultValue}\`)`; } else { - value = `\`${ast.defaultValue}\``; + value = `\`${defaultValue}\``; } } else { value = expr; diff --git a/tests/compiler/__snapshots__/translation.test.ts.snap b/tests/compiler/__snapshots__/translation.test.ts.snap index f40bedda..6e493cb3 100644 --- a/tests/compiler/__snapshots__/translation.test.ts.snap +++ b/tests/compiler/__snapshots__/translation.test.ts.snap @@ -1,5 +1,79 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`translation support body of t-sets are translated 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, withDefault, setContextValue } = helpers; + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1 + setContextValue(ctx, \\"label\\", \`translated\`); + return text(ctx['label']); + } +}" +`; + +exports[`translation support body of t-sets inside translation=off are not translated 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, withDefault, setContextValue } = helpers; + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1 + setContextValue(ctx, \\"label\\", \`untranslated\`); + return text(ctx['label']); + } +}" +`; + +exports[`translation support body of t-sets with html content are translated 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, withDefault, LazyValue, safeOutput } = helpers; + + let block1 = createBlock(\`
translated
\`); + + function value1(ctx, node, key = \\"\\") { + return block1(); + } + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1 + ctx[\`label\`] = new LazyValue(value1, ctx, this, node, key); + return safeOutput(ctx['label']); + } +}" +`; + +exports[`translation support body of t-sets with text and html content are translated 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, withDefault, LazyValue, safeOutput } = helpers; + + let block3 = createBlock(\`
translated
\`); + + function value1(ctx, node, key = \\"\\") { + const b2 = text(\` translated \`); + const b3 = block3(); + return multi([b2, b3]); + } + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1 + ctx[\`label\`] = new LazyValue(value1, ctx, this, node, key); + return safeOutput(ctx['label']); + } +}" +`; + exports[`translation support can set and remove translatable attributes 1`] = ` "function anonymous(app, bdom, helpers ) { @@ -52,6 +126,21 @@ exports[`translation support some attributes are translated 1`] = ` }" `; +exports[`translation support t-set and falsy t-value: t-body are translated 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, withDefault, setContextValue } = helpers; + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1 + setContextValue(ctx, \\"label\\", withDefault(false, \`translated\`)); + return text(ctx['label']); + } +}" +`; + exports[`translation support translation is done on the trimmed text, with extra spaces readded after 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/compiler/translation.test.ts b/tests/compiler/translation.test.ts index 71dc6ba6..852f8d21 100644 --- a/tests/compiler/translation.test.ts +++ b/tests/compiler/translation.test.ts @@ -100,4 +100,74 @@ describe("translation support", () => { expect(translateFn).toHaveBeenCalledWith("some word"); expect(fixture.innerHTML).toBe("
un mot
"); }); + + test("body of t-sets are translated", async () => { + class SomeComponent extends Component { + static template = xml` + untranslated + `; + } + + const translateFn = () => "translated"; + + await mount(SomeComponent, fixture, { translateFn }); + expect(fixture.innerHTML).toBe("translated"); + }); + + test("body of t-sets inside translation=off are not translated", async () => { + class SomeComponent extends Component { + static template = xml` + + untranslated + + `; + } + + const translateFn = () => "translated"; + + await mount(SomeComponent, fixture, { translateFn }); + expect(fixture.innerHTML).toBe("untranslated"); + }); + + test("body of t-sets with html content are translated", async () => { + class SomeComponent extends Component { + static template = xml` +
untranslated
+ `; + } + + const translateFn = () => "translated"; + + await mount(SomeComponent, fixture, { translateFn }); + expect(fixture.innerHTML).toBe("
translated
"); + }); + + test("body of t-sets with text and html content are translated", async () => { + class SomeComponent extends Component { + static template = xml` + + some text +
untranslated
+
+ `; + } + + const translateFn = () => "translated"; + + await mount(SomeComponent, fixture, { translateFn }); + expect(fixture.innerHTML).toBe(" translated
translated
"); + }); + + test("t-set and falsy t-value: t-body are translated", async () => { + class SomeComponent extends Component { + static template = xml` + untranslated + `; + } + + const translateFn = () => "translated"; + + await mount(SomeComponent, fixture, { translateFn }); + expect(fixture.innerHTML).toBe("translated"); + }); });