-
Notifications
You must be signed in to change notification settings - Fork 406
Description
Current Behavior
When a template has <t t-esc="expr">defaultValue</t>, the defaultValue is hardcoded into the generated code WITHOUT translation.
Example generated code:
return text(withDefault(ctx['userName'], `Unknown User`)); // NOT translatedExpected Behavior
The defaultValue should be translated (if translateFn is provided), similar to how compileTSet() already does it.
Example generated code:
return text(withDefault(ctx['userName'], `Utilisateur Inconnu`)); // Translated!Bug Location
File: src/compiler/code_generator.ts
Lines: 802-805 (in compileTEsc() method)
if (ast.defaultValue) {
this.helpers.add("withDefault");
// FIXME: defaultValue is not translated
expr = `withDefault(${expr}, ${toStringExpression(ast.defaultValue)})`;
}Similar Working Pattern (Reference)
File: src/compiler/code_generator.ts
Lines: 1121-1124 (in compileTSet() method)
if (ast.defaultValue) {
const defaultValue = toStringExpression(
ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue
);
// ... rest of code
}This shows the correct pattern: check ctx.translate, then call this.translate() on the defaultValue.
Test Cases Created
I've created Jest tests to verify the fix. Run with: npm test -- compileTEsc_fix
import { compile } from "../src/compiler";
describe("compileTEsc fix - translation of defaultValue", () => {
it("should translate defaultValue when translateFn is provided", () => {
const template = `<t t-esc="userName">Unknown User</t>`;
const mockTranslateFn = (text: string, ctx: string) => {
const translations: { [key: string]: string } = {
"Unknown User": "Utilisateur Inconnu",
};
return translations[text] || text;
};
const fn = compile(template, {
translateFn: mockTranslateFn,
hasGlobalValues: false,
});
const generatedCode = fn.toString();
expect(generatedCode).toContain("Utilisateur Inconnu");
});
it("should NOT translate defaultValue when no translateFn is provided", () => {
const template = `<t t-esc="userName">Unknown User</t>`;
const fn = compile(template, {
hasGlobalValues: false,
});
const generatedCode = fn.toString();
expect(generatedCode).toContain("Unknown User");
});
it("should fallback to original when translation not found", () => {
const template = `<t t-esc="userName">Some Rare Text</t>`;
const mockTranslateFn = (text: string, ctx: string) => {
const translations: { [key: string]: string } = {
"Unknown User": "Utilisateur Inconnu",
};
return translations[text] || text;
};
const fn = compile(template, {
translateFn: mockTranslateFn,
hasGlobalValues: false,
});
const generatedCode = fn.toString();
expect(generatedCode).toContain("Some Rare Text");
});
it("should handle empty defaultValue", () => {
const template = `<t t-esc="userName"></t>`;
const mockTranslateFn = (text: string, ctx: string) => {
return text;
};
const fn = compile(template, {
translateFn: mockTranslateFn,
hasGlobalValues: false,
});
const generatedCode = fn.toString();
expect(generatedCode).toBeDefined();
expect(generatedCode.length).toBeGreaterThan(0);
});
it("should preserve spaces in translated defaultValue", () => {
const template = `<t t-esc="userName"> Welcome Back </t>`;
const mockTranslateFn = (text: string, ctx: string) => {
const translations: { [key: string]: string } = {
" Welcome Back ": " Bienvenue Retour ",
};
return translations[text] || text;
};
const fn = compile(template, {
translateFn: mockTranslateFn,
hasGlobalValues: false,
});
const generatedCode = fn.toString();
expect(generatedCode).toContain("Bienvenue Retour");
});
});Test Results (Current - Failing)
Tests: 2 failed, 3 passed, 5 total
- ✓ Test 2 (no translateFn): PASS
- ✓ Test 3 (no match): PASS
- ✓ Test 4 (empty defaultValue): PASS
- ✗ Test 1 (translate enabled): FAIL
- ✗ Test 5 (preserve spaces): FAIL
Question for Maintainers
Is this the correct approach and test coverage for fixing this bug? If yes, I can proceed with implementing the fix. If there's a different approach or additional considerations, please let me know.
Related Code References
- Bug location:
src/compiler/code_generator.tslines 802-805 (compileTEsc method) - Similar working pattern:
src/compiler/code_generator.tslines 1121-1124 (compileTSet method) - Related files:
src/compiler/index.ts(compile function)src/compiler/parser.ts(AST parsing)