/
githubmirror
/
TypeScript
Обзор
Документация
Войти
/
githubmirror
/
TypeScript
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
scripts/generateLocalizedDiagnosticMessages.mjs
182 строки
6 KB
Jake Bailey
Add regex eslint plugin, fix lints (#59371)
14 авг 2024, 00:16
Не верифицирован
14 авг 2024, 00:16
195203e
Код
Авторство
О чём код?
import { XMLParser } from "fast-xml-parser"; import fs from "fs"; import path from "path"; /** @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:"); console.log("\tnode generateLocalizedDiagnosticMessages.js <lcl source directory> <output directory> <generated diagnostics map file>"); return; } const inputPath = args[0]; const outputPath = args[1]; const diagnosticsMapFilePath = args[2]; // generate the lcg file for enu await generateLCGFile(); // generate other langs const files = await fs.promises.readdir(inputPath); await Promise.all(files.map(visitDirectory)); return; /** * @param {string} name */ async function visitDirectory(name) { const inputFilePath = path.join(inputPath, name, "diagnosticMessages", "diagnosticMessages.generated.json.lcl"); const contents = await fs.promises.readFile(inputFilePath); /** @type {ParsedLCL} */ 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)); } /** * A locale name is based on the language tagging conventions of RFC 4646 (Windows Vista * and later), and is represented by LOCALE_SNAME. * Generally, the pattern <language>-<REGION> is used. Here, language is a lowercase ISO 639 * language code. The codes from ISO 639-1 are used when available. Otherwise, codes from * ISO 639-2/T are used. REGION specifies an uppercase ISO 3166-1 country/region identifier. * For example, the locale name for English (United States) is "en-US" and the locale name * for Divehi (Maldives) is "dv-MV". * * If the locale is a neutral locale (no region), the LOCALE_SNAME value follows the * pattern <language>. If it is a neutral locale for which the script is significant, the * pattern is <language>-<Script>. * * More at https://msdn.microsoft.com/en-us/library/windows/desktop/dd373814(v=vs.85).aspx * * Most of the languages we support are neutral locales, so we want to use the language name. * There are three exceptions, zh-CN, zh-TW and pt-BR. * * @param {string} localeName */ function getPreferredLocaleName(localeName) { switch (localeName) { case "zh-CN": case "zh-TW": case "pt-BR": return localeName; default: return localeName.split("-")[0]; } } /** * @param {ParsedLCL} o */ function xmlObjectToString(o) { /** @type {any} */ const out = {}; 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"); process.exit(1); } if (ItemId.charAt(0) === ";") { ItemId = ItemId.slice(1); // remove leading semicolon } val = val.replace(/\]5D;/, "]"); // unescape `]` out[ItemId] = val; } return JSON.stringify(out, undefined, 2); } /** * @param {string} fileName * @param {string} contents */ async function writeFile(fileName, contents) { await fs.promises.mkdir(path.dirname(fileName), { recursive: true }); await fs.promises.writeFile(fileName, contents); } 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 * @param {string} value */ function getItemXML(key, value) { // escape entrt value value = value.replace(/\]/g, "]5D;"); return ` <Item ItemId=";${key}" ItemType="0" PsrId="306" Leaf="true"> <Str Cat="Text"> <Val><![CDATA[${value}]]></Val> </Str> <Disp Icon="Str" /> </Item>`; } /** * @param {string} items */ function getLCGFileXML(items) { return `<?xml version="1.0" encoding="utf-8"?> <LCX SchemaVersion="6.0" Name="diagnosticMessages.generated.json" PsrId="306" FileType="1" SrcCul="en-US" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx"> <OwnedComments> <Cmt Name="Dev" /> <Cmt Name="LcxAdmin" /> <Cmt Name="Rccx" /> </OwnedComments> <Item ItemId=";String Table" ItemType="0" PsrId="306" Leaf="false"> <Disp Icon="Expand" Expand="true" Disp="true" LocTbl="false" /> <Item ItemId=";Strings" ItemType="0" PsrId="306" Leaf="false"> <Disp Icon="Str" Disp="true" LocTbl="false" />${items} </Item> </Item> </LCX>`; } } } await main();