mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 05:55:11 -05:00
Modernize localize script, use new XML library
This file is pretty much the same as it was when it was committed in 2017; these days, we can write clearer code with async/await and new FS APIs. Additionally, we can improve the performance of this script by using a newer/faster/maintained XML library. This will enable us to run the script unconditionally in a later commit.
This commit is contained in:
@@ -1,8 +1,28 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import xml2js from "xml2js";
|
||||
import { XMLParser } from "fast-xml-parser";
|
||||
|
||||
function main() {
|
||||
/** @typedef {{
|
||||
LCX: {
|
||||
$_TgtCul: string;
|
||||
Item: {
|
||||
Item: {
|
||||
Item: {
|
||||
$_ItemId: string;
|
||||
Str: {
|
||||
Val: string;
|
||||
Tgt: {
|
||||
Val: string;
|
||||
};
|
||||
};
|
||||
}[];
|
||||
};
|
||||
};
|
||||
}
|
||||
}} ParsedLCL */
|
||||
void 0;
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length !== 3) {
|
||||
console.log("Usage:");
|
||||
@@ -15,38 +35,33 @@ function main() {
|
||||
const diagnosticsMapFilePath = args[2];
|
||||
|
||||
// generate the lcg file for enu
|
||||
generateLCGFile();
|
||||
await generateLCGFile();
|
||||
|
||||
// generate other langs
|
||||
fs.readdir(inputPath, (err, files) => {
|
||||
handleError(err);
|
||||
files.forEach(visitDirectory);
|
||||
});
|
||||
const files = await fs.promises.readdir(inputPath);
|
||||
await Promise.all(files.map(visitDirectory));
|
||||
|
||||
return;
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
function visitDirectory(name) {
|
||||
async function visitDirectory(name) {
|
||||
const inputFilePath = path.join(inputPath, name, "diagnosticMessages", "diagnosticMessages.generated.json.lcl");
|
||||
|
||||
fs.readFile(inputFilePath, (err, data) => {
|
||||
handleError(err);
|
||||
xml2js.parseString(data.toString(), (err, result) => {
|
||||
handleError(err);
|
||||
if (!result || !result.LCX || !result.LCX.$ || !result.LCX.$.TgtCul) {
|
||||
console.error("Unexpected XML file structure. Expected to find result.LCX.$.TgtCul.");
|
||||
process.exit(1);
|
||||
}
|
||||
const outputDirectoryName = getPreferredLocaleName(result.LCX.$.TgtCul).toLowerCase();
|
||||
if (!outputDirectoryName) {
|
||||
console.error(`Invalid output locale name for '${result.LCX.$.TgtCul}'.`);
|
||||
process.exit(1);
|
||||
}
|
||||
writeFile(path.join(outputPath, outputDirectoryName, "diagnosticMessages.generated.json"), xmlObjectToString(result));
|
||||
});
|
||||
});
|
||||
const contents = await fs.promises.readFile(inputFilePath);
|
||||
/** @type {ParsedLCL} */
|
||||
// eslint-disable-next-line local/object-literal-surrounding-space
|
||||
const result = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: "$_"}).parse(contents);
|
||||
if (!result || !result.LCX || !result.LCX.$_TgtCul) {
|
||||
console.error("Unexpected XML file structure. Expected to find result.LCX.$_TgtCul.");
|
||||
process.exit(1);
|
||||
}
|
||||
const outputDirectoryName = getPreferredLocaleName(result.LCX.$_TgtCul).toLowerCase();
|
||||
if (!outputDirectoryName) {
|
||||
console.error(`Invalid output locale name for '${result.LCX.$_TgtCul}'.`);
|
||||
process.exit(1);
|
||||
}
|
||||
await writeFile(path.join(outputPath, outputDirectoryName, "diagnosticMessages.generated.json"), xmlObjectToString(result));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,24 +96,14 @@ function main() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {null | object} err
|
||||
*/
|
||||
function handleError(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} o
|
||||
* @param {ParsedLCL} o
|
||||
*/
|
||||
function xmlObjectToString(o) {
|
||||
/** @type {any} */
|
||||
const out = {};
|
||||
for (const item of o.LCX.Item[0].Item[0].Item) {
|
||||
let ItemId = item.$.ItemId;
|
||||
let val = item.Str[0].Tgt ? item.Str[0].Tgt[0].Val[0] : item.Str[0].Val[0];
|
||||
for (const item of o.LCX.Item.Item.Item) {
|
||||
let ItemId = item.$_ItemId;
|
||||
let val = item.Str.Tgt ? item.Str.Tgt.Val : item.Str.Val;
|
||||
|
||||
if (typeof ItemId !== "string" || typeof val !== "string") {
|
||||
console.error("Unexpected XML file structure");
|
||||
@@ -115,55 +120,26 @@ function main() {
|
||||
return JSON.stringify(out, undefined, 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} directoryPath
|
||||
* @param {() => void} action
|
||||
*/
|
||||
function ensureDirectoryExists(directoryPath, action) {
|
||||
fs.exists(directoryPath, exists => {
|
||||
if (!exists) {
|
||||
const basePath = path.dirname(directoryPath);
|
||||
if (basePath !== directoryPath) {
|
||||
return ensureDirectoryExists(basePath, () => fs.mkdir(directoryPath, action));
|
||||
}
|
||||
}
|
||||
action();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @param {string} contents
|
||||
*/
|
||||
function writeFile(fileName, contents) {
|
||||
ensureDirectoryExists(path.dirname(fileName), () => {
|
||||
fs.writeFile(fileName, contents, handleError);
|
||||
});
|
||||
async function writeFile(fileName, contents) {
|
||||
await fs.promises.mkdir(path.dirname(fileName), { recursive: true });
|
||||
await fs.promises.writeFile(fileName, contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, string>} o
|
||||
*/
|
||||
function objectToList(o) {
|
||||
const list = [];
|
||||
for (const key in o) {
|
||||
list.push({ key, value: o[key] });
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
function generateLCGFile() {
|
||||
return fs.readFile(diagnosticsMapFilePath, (err, data) => {
|
||||
handleError(err);
|
||||
writeFile(
|
||||
path.join(outputPath, "enu", "diagnosticMessages.generated.json.lcg"),
|
||||
getLCGFileXML(
|
||||
objectToList(JSON.parse(data.toString()))
|
||||
.sort((a, b) => a.key > b.key ? 1 : -1) // lcg sorted by property keys
|
||||
.reduce((s, { key, value }) => s + getItemXML(key, value), "")
|
||||
));
|
||||
});
|
||||
async function generateLCGFile() {
|
||||
const contents = await fs.promises.readFile(diagnosticsMapFilePath, "utf-8");
|
||||
await writeFile(
|
||||
path.join(outputPath, "enu", "diagnosticMessages.generated.json.lcg"),
|
||||
getLCGFileXML(
|
||||
Object.entries(JSON.parse(contents))
|
||||
.sort((a, b) => a[0] > b[0] ? 1 : -1) // lcg sorted by property keys
|
||||
.reduce((s, [key, value]) => s + getItemXML(key, value), "")
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
@@ -204,4 +180,4 @@ function main() {
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
await main();
|
||||
|
||||
Reference in New Issue
Block a user