Skip to content

Commit f9cf59b

Browse files
committed
fix: added explicit utf-8 encoding for PowerShell users
1 parent 006c337 commit f9cf59b

2 files changed

Lines changed: 118 additions & 29 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ This will update `packages/studio-web/src/i18n/messages.json` with the English s
267267
Add or correct their translations in `messages.es.json` and `messages.fr.json`.
268268
(See `packages/studio-web/extract-i18n-lang.ts` for partial automation of that task.)
269269

270+
npx tsx packages/studio-web/extract-i18n-lang.ts --help
271+
270272
Finally, run this check to confirm all the required strings are present in each language:
271273

272274
npx nx check-l10n studio-web
Lines changed: 116 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,106 @@
1-
// Update the language files with the new keys from the English file
2-
// Usage:
3-
// npx tsx extract-i18n-lang.ts src/i18n/messages.json src/i18n/messages.fr.json > src/i18n/messages.fr-updated.json
4-
// npx tsx extract-i18n-lang.ts src/i18n/messages.json src/i18n/messages.es.json > src/i18n/messages.es-updated.json
5-
// and then manually inspect the results, translate the new keys and copy the
6-
// updated files back to the original files.
7-
81
import fs from "fs";
92
import process from "process";
3+
import { parseArgs } from "node:util";
104

11-
// Get the messages file from the command line
12-
const englishMessagesFile = process.argv[2];
13-
const languageMessagesFile = process.argv[3];
5+
function showHelp() {
6+
console.log(`Update the language files with the new keys from the English file.
147
15-
// Check if filename is provided
16-
if (!englishMessagesFile || !languageMessagesFile) {
17-
console.error(
18-
"Please provide the English message file and translated message file as first and second CLI argument",
19-
);
20-
process.exit(1);
8+
Then manually inspect the results, translate the new keys and copy the
9+
updated files back to the original files.
10+
11+
Usage:
12+
npx tsx extract-i18n-lang.ts [options] englishFile otherLanguageFile
13+
14+
Options:
15+
--output filePath writes the utf-8 encoded data to the specified output file
16+
-i, --inplace overwrites the translated language file
17+
-h, --help displays this message
18+
19+
Examples:
20+
npx tsx extract-i18n-lang.ts src/i18n/messages.json src/i18n/messages.fr.json > src/i18n/messages.fr-updated.json
21+
npx tsx extract-i18n-lang.ts src/i18n/messages.json src/i18n/messages.es.json > src/i18n/messages.es-updated.json
22+
23+
npx tsx extract-i18n-lang.ts --output src/i18n/messages.es-updated.json src/i18n/messages.json src/i18n/messages.es.json
24+
npx tsx extract-i18n-lang.ts --inplace src/i18n/messages.json src/i18n/messages.es.json
25+
26+
Note:
27+
In a Windows PowerShell environment, please use either the --output or the --inplace flags.
28+
`);
29+
}
30+
31+
function parseCommandLine() {
32+
const { values: flags, positionals: args } = parseArgs({
33+
args: process.argv.slice(2),
34+
options: {
35+
output: {
36+
type: "string",
37+
default: "-",
38+
},
39+
inplace: { type: "boolean", short: "i" },
40+
help: { type: "boolean", short: "h" },
41+
},
42+
allowPositionals: true,
43+
});
44+
45+
// show help message
46+
if (flags.help) {
47+
showHelp();
48+
process.exit(0);
49+
}
50+
51+
// Check if filenames are provided
52+
if (args.length < 2) {
53+
console.error(
54+
"Please provide the English message file and translated message file as first and second CLI argument",
55+
);
56+
process.exit(1);
57+
}
58+
59+
// In-place implementation, replace the output file with the
60+
// source of the translated data, but only if the user has not
61+
// specified an output file path.
62+
if (flags.output === "-" && flags.inplace) {
63+
flags.output = args[1];
64+
}
65+
66+
// If a Windows user is using stdout, provide a warning message. This is really targeted
67+
// at PowerShell users but we cannot reliably determine which shell is being used.
68+
if (process.platform === "win32" && flags.output === "-") {
69+
console.error(
70+
"Windows warning: please provide either the --output or --inplace flags to generate a valid utf-8 file",
71+
);
72+
}
73+
74+
return { flags, args };
75+
}
76+
77+
interface TranslationFile {
78+
locale: string;
79+
translations: {
80+
[key: string]: string;
81+
};
82+
}
83+
84+
function readJSON(filePath: string): TranslationFile {
85+
try {
86+
const rawData = fs.readFileSync(filePath, "utf8");
87+
return JSON.parse(rawData);
88+
} catch (err: any) {
89+
console.error(
90+
`An error occurred while reading "${filePath}":\n ${"message" in err ? err.message : err}`,
91+
);
92+
process.exit(1);
93+
}
2194
}
2295

23-
// Read the English file synchronously
24-
const englishDataRaw = fs.readFileSync(englishMessagesFile, "utf8");
25-
const englishData = JSON.parse(englishDataRaw);
26-
//console.log(englishDataParsed);
96+
// Get the arguments from the command line
97+
const { flags, args } = parseCommandLine();
98+
99+
const englishMessagesFile = args[0];
100+
const languageMessagesFile = args[1];
27101

28-
// Read the language file synchronously
29-
const languageDataRaw = fs.readFileSync(languageMessagesFile, "utf8");
30-
let languageData = JSON.parse(languageDataRaw);
31-
//assert(englishData, 'English data is null');
32-
//assert(languageData, 'Language data is null');
102+
const englishData = readJSON(englishMessagesFile);
103+
const languageData = readJSON(languageMessagesFile);
33104

34105
for (const key in englishData.translations) {
35106
if (!languageData.translations[key]) {
@@ -46,12 +117,28 @@ for (const key in languageData.translations) {
46117
delete languageData.translations[key];
47118
}
48119
}
49-
//console.log(languageData)
50120

51-
let sortedTranslations: any = {};
121+
const sortedTranslations: any = {};
52122
for (const key in englishData.translations) {
53123
sortedTranslations[key] = languageData.translations[key];
54124
}
55-
//console.log(sortedTranslations);
56125
languageData.translations = sortedTranslations;
57-
console.log(JSON.stringify(languageData, null, 2));
126+
127+
// Save the new translated file to the user provided output path.
128+
try {
129+
const writer =
130+
flags.output !== "-" ? fs.openSync(flags.output, "w") : process.stdout.fd;
131+
132+
fs.writeSync(
133+
writer,
134+
Buffer.from(JSON.stringify(languageData, null, 2), "utf-8"),
135+
);
136+
137+
fs.closeSync(writer);
138+
} catch (err: any) {
139+
console.error(
140+
`An error occurred while saving the new translation file:\n` +
141+
` ${"message" in err ? err.message : err}`,
142+
);
143+
process.exit(1);
144+
}

0 commit comments

Comments
 (0)