fix(ivy): i18n - ensure that escaped chars are handled in localized strings (#34065)
When creating synthesized tagged template literals, one must provide both the "cooked" text and the "raw" (unparsed) text. Previously there were no good APIs for creating the AST nodes with raw text for such literals. Recently the APIs were improved to support this, and they do an extra check to ensure that the raw text parses to be equal to the cooked text. It turns out there is a bug in this check - see https://github.com/microsoft/TypeScript/issues/35374. This commit works around the bug by synthesizing a "head" node and morphing it by changing its `kind` into the required node type. // FW-1747 PR Close #34065
This commit is contained in:

committed by
Miško Hevery

parent
d5aedbe892
commit
ee7857300b
@ -78,7 +78,7 @@ function tokenizeBackTickString(str: string): Piece[] {
|
||||
const pieces: Piece[] = ['`'];
|
||||
// Unescape backticks that are inside the backtick string
|
||||
// (we had to double escape them in the test string so they didn't look like string markers)
|
||||
str = str.replace(/\\\\\\`/, '\\`');
|
||||
str = str.replace(/\\\\\\`/g, '\\`');
|
||||
const backTickPieces = str.slice(2, -2).split(BACKTICK_INTERPOLATION);
|
||||
backTickPieces.forEach((backTickPiece) => {
|
||||
if (BACKTICK_INTERPOLATION.test(backTickPiece)) {
|
||||
|
@ -956,23 +956,40 @@ describe('i18n support in the template compiler', () => {
|
||||
|
||||
it('should properly escape quotes in content', () => {
|
||||
const input = `
|
||||
<div i18n>Some text 'with single quotes', "with double quotes" and without quotes.</div>
|
||||
<div i18n>Some text 'with single quotes', "with double quotes", \`with backticks\` and without quotes.</div>
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
var $I18N_0$;
|
||||
if (ngI18nClosureMode) {
|
||||
const $MSG_EXTERNAL_4924931801512133405$$APP_SPEC_TS_0$ = goog.getMsg("Some text 'with single quotes', \"with double quotes\" and without quotes.");
|
||||
const $MSG_EXTERNAL_4924931801512133405$$APP_SPEC_TS_0$ = goog.getMsg("Some text 'with single quotes', \"with double quotes\", ` +
|
||||
'`with backticks`' + String.raw ` and without quotes.");
|
||||
$I18N_0$ = $MSG_EXTERNAL_4924931801512133405$$APP_SPEC_TS_0$;
|
||||
}
|
||||
else {
|
||||
$I18N_0$ = $localize \`Some text 'with single quotes', "with double quotes" and without quotes.\`;
|
||||
$I18N_0$ = $localize \`Some text 'with single quotes', "with double quotes", \\\`with backticks\\\` and without quotes.\`;
|
||||
}
|
||||
`;
|
||||
|
||||
verify(input, output);
|
||||
});
|
||||
|
||||
it('should handle interpolations wrapped in backticks', () => {
|
||||
const input = '<div i18n>`{{ count }}`</div>';
|
||||
const output = String.raw `
|
||||
var $I18N_0$;
|
||||
if (ngI18nClosureMode) {
|
||||
const $MSG_APP_SPEC_TS_1$ = goog.getMsg("` +
|
||||
'`{$interpolation}`' + String.raw `", { "interpolation": "\uFFFD0\uFFFD" });
|
||||
$I18N_0$ = $MSG_APP_SPEC_TS_1$;
|
||||
}
|
||||
else {
|
||||
$I18N_0$ = $localize \`\\\`$` +
|
||||
String.raw `{"\uFFFD0\uFFFD"}:INTERPOLATION:\\\`\`;
|
||||
}`;
|
||||
verify(input, output);
|
||||
});
|
||||
|
||||
it('should handle i18n attributes with plain-text content', () => {
|
||||
const input = `
|
||||
<div i18n>My i18n block #1</div>
|
||||
|
Reference in New Issue
Block a user