Skip to content

Commit

Permalink
Multiple fixes
Browse files Browse the repository at this point in the history
* Fix Windows path handlng fixes microsoft/vscode#161945
* Add a script name instead of relying on name at runtime fixes microsoft/vscode#161946
* Fix escaping ampersands
  • Loading branch information
TylerLeonhardt committed Sep 27, 2022
1 parent 21384e3 commit cb91447
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 17 deletions.
4 changes: 2 additions & 2 deletions l10n-dev/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion l10n-dev/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vscode/l10n-dev",
"version": "0.0.9",
"version": "0.0.11",
"description": "Development time npm module to generate strings bundles from TypeScript files",
"author": "Microsoft Corporation",
"license": "MIT",
Expand Down
17 changes: 11 additions & 6 deletions l10n-dev/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { hideBin } from 'yargs/helpers';
import { l10nJsonFormat } from "./common";

yargs(hideBin(process.argv))
.scriptName("vscode-l10n-dev")
.usage('$0 <cmd> [args]')
.command(
'export [args] <path..>',
Expand Down Expand Up @@ -84,12 +85,12 @@ yargs(hideBin(process.argv))

function l10nExportStrings(paths: string[], outDir: string): void {
console.log('Searching for TypeScript files...');
const matches = paths.map(p => glob.sync(p)).flat();
const matches = paths.map(p => glob.sync(toPosixPath(p))).flat();
const tsFileContents = matches.reduce<string[]>((prev, curr) => {
if (curr.endsWith('.ts')) {
prev.push(readFileSync(path.resolve(curr), 'utf8'));
}
const results = glob.sync(path.join(curr, `{,!(node_modules)/**}`, '*.ts'));
const results = glob.sync(path.posix.join(curr, `{,!(node_modules)/**}`, '*.ts'));
for (const result of results) {
prev.push(readFileSync(path.resolve(result), 'utf8'));
}
Expand All @@ -116,7 +117,7 @@ function l10nExportStrings(paths: string[], outDir: string): void {

function l10nGenerateXlf(paths: string[], language: string, outFile: string): void {
console.log('Searching for L10N JSON files...');
const matches = paths.map(p => glob.sync(p)).flat();
const matches = paths.map(p => glob.sync(toPosixPath(p))).flat();
const l10nFileContents = matches.reduce<Map<string, l10nJsonFormat>>((prev, curr) => {
if (curr.endsWith('.l10n.json')) {
const name = path.basename(curr).split('.l10n.json')[0] ?? '';
Expand All @@ -127,7 +128,7 @@ function l10nGenerateXlf(paths: string[], language: string, outFile: string): vo
prev.set('package', JSON.parse(readFileSync(path.resolve(curr), 'utf8')));
return prev;
}
const results = glob.sync(path.join(curr, `{,!(node_modules)/**}`, '{*.l10n.json,package.nls.json}'));
const results = glob.sync(path.posix.join(curr, `{,!(node_modules)/**}`, '{*.l10n.json,package.nls.json}'));
for (const result of results) {
if (result.endsWith('.l10n.json')) {
const name = path.basename(curr).split('.l10n.json')[0] ?? '';
Expand Down Expand Up @@ -155,12 +156,12 @@ function l10nGenerateXlf(paths: string[], language: string, outFile: string): vo

async function l10nImportXlf(paths: string[], outDir: string): Promise<void> {
console.log('Searching for XLF files...');
const matches = paths.map(p => glob.sync(p)).flat();
const matches = paths.map(p => glob.sync(toPosixPath(p))).flat();
const xlfFiles = matches.reduce<string[]>((prev, curr) => {
if (curr.endsWith('.xlf')) {
prev.push(readFileSync(path.resolve(curr), 'utf8'));
}
const results = glob.sync(path.join(curr, `{,!(node_modules)/**}`, '*.xlf'));
const results = glob.sync(path.posix.join(curr, `{,!(node_modules)/**}`, '*.xlf'));
for (const result of results) {
prev.push(readFileSync(path.resolve(result), 'utf8'));
}
Expand Down Expand Up @@ -189,3 +190,7 @@ async function l10nImportXlf(paths: string[], outDir: string): Promise<void> {
}
console.log(`Wrote ${count} localized L10N JSON files to: ${outDir}`);
}

function toPosixPath(pathToConvert: string): string {
return pathToConvert.split(path.win32.sep).join(path.posix.sep);
}
51 changes: 45 additions & 6 deletions l10n-dev/src/xlf/test/xlf.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,26 @@ describe('XLF', () => {
assert.strictEqual(result, '<?xml version="1.0" encoding="utf-8"?>\r\n<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">\r\n <file original="bundle" source-language="en" datatype="plaintext"><body>\r\n <trans-unit id="Hello">\r\n <source xml:lang="en">Hello</source>\r\n </trans-unit>\r\n </body></file>\r\n</xliff>');
});

it('escapes double quotes', () => {

it('escapes things correctly', () => {
const xlf = new XLF();
xlf.addFile('bundle', { '""': 'Hello' });
// Use to of each to ensure we don't accidentally just grab the first one
xlf.addFile('bundle', {
'""': 'quotes',
"''": 'apostrophes',
'<<': 'less than',
'>>': 'greater than',
'&&': 'ampersands'
});
const result = xlf.toString();
assert.strictEqual(result, '<?xml version="1.0" encoding="utf-8"?>\r\n<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">\r\n <file original="bundle" source-language="en" datatype="plaintext"><body>\r\n <trans-unit id="&quot;&quot;">\r\n <source xml:lang="en">Hello</source>\r\n </trans-unit>\r\n </body></file>\r\n</xliff>');
const header = '<?xml version="1.0" encoding="utf-8"?>\r\n<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">\r\n <file original="bundle" source-language="en" datatype="plaintext"><body>';
const quotes = '\r\n <trans-unit id="&quot;&quot;">\r\n <source xml:lang="en">quotes</source>\r\n </trans-unit>';
const apostrophes = '\r\n <trans-unit id="&apos;&apos;">\r\n <source xml:lang="en">apostrophes</source>\r\n </trans-unit>';
const lessThan = '\r\n <trans-unit id="&lt;&lt;">\r\n <source xml:lang="en">less than</source>\r\n </trans-unit>';
const greaterThan = '\r\n <trans-unit id="&gt;&gt;">\r\n <source xml:lang="en">greater than</source>\r\n </trans-unit>';
const amp = '\r\n <trans-unit id="&amp;&amp;">\r\n <source xml:lang="en">ampersands</source>\r\n </trans-unit>';
const footer = '\r\n </body></file>\r\n</xliff>';
assert.strictEqual(result, header + quotes + apostrophes + lessThan + greaterThan + amp + footer);
});

it('parses double quotes correctly', async () => {
Expand All @@ -28,8 +43,24 @@ describe('XLF', () => {
<file original="package" source-language="en" datatype="plaintext" target-language="de">
<body>
<trans-unit id="&quot;&quot;">
<source xml:lang="en">Hello</source>
<target state="translated">World</target>
<source xml:lang="en">&quot;&quot;</source>
<target state="translated">&quot;&quot;</target>
</trans-unit>
<trans-unit id="&apos;&apos;">
<source xml:lang="en">&apos;&apos;</source>
<target state="translated">&apos;&apos;</target>
</trans-unit>
<trans-unit id="&lt;&lt;">
<source xml:lang="en">&lt;&lt;</source>
<target state="translated">&lt;&lt;</target>
</trans-unit>
<trans-unit id="&gt;&gt;">
<source xml:lang="en">&gt;&gt;</source>
<target state="translated">&gt;&gt;</target>
</trans-unit>
<trans-unit id="&amp;&amp;">
<source xml:lang="en">&amp;&amp;</source>
<target state="translated">&amp;&amp;</target>
</trans-unit>
</body>
</file>
Expand All @@ -40,6 +71,14 @@ describe('XLF', () => {
assert.strictEqual(result[0]!.language, 'de');
assert.strictEqual(result[0]!.name, 'package');
assert.ok(result[0]!.messages['""']);
assert.strictEqual(result[0]!.messages['""'], 'World');
assert.strictEqual(result[0]!.messages['""'], '""');
assert.ok(result[0]!.messages["''"]);
assert.strictEqual(result[0]!.messages["''"], "''");
assert.ok(result[0]!.messages['<<']);
assert.strictEqual(result[0]!.messages['<<'], '<<');
assert.ok(result[0]!.messages['>>']);
assert.strictEqual(result[0]!.messages['>>'], '>>');
assert.ok(result[0]!.messages['&&']);
assert.strictEqual(result[0]!.messages['&&'], '&&');
});
});
15 changes: 13 additions & 2 deletions l10n-dev/src/xlf/xlf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class XLF {
throw new Error('No item ID or value specified.');
}

this.appendNewLine(`<trans-unit id="${item.id.replace(/"/g, '&quot;')}">`, 4);
this.appendNewLine(`<trans-unit id="${encodeEntities(item.id)}">`, 4);
this.appendNewLine(`<source xml:lang="${this.sourceLanguage}">${item.message}</source>`, 6);

if (item.comment) {
Expand Down Expand Up @@ -165,6 +165,12 @@ function encodeEntities(value: string): string {
for (let i = 0; i < value.length; i++) {
const ch = value[i]!;
switch (ch) {
case '"':
result.push('&quot;');
break;
case "'":
result.push('&apos;');
break;
case '<':
result.push('&lt;');
break;
Expand All @@ -182,5 +188,10 @@ function encodeEntities(value: string): string {
}

function decodeEntities(value: string): string {
return value.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
return value
.replace(/&quot;/g, '"')
.replace(/&apos;/g, "'")
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&amp;/g, '&');
}

0 comments on commit cb91447

Please sign in to comment.