diff --git a/Gulpfile.ts b/Gulpfile.ts index 24ff1f3f3c9fe..200692b6ca42f 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -180,6 +180,23 @@ const libraryTargets = librarySourceMap.map(function(f) { return path.join(builtLocalDirectory, f.target); }); +/** + * .lcg file is what localization team uses to know what messages to localize. + * The file is always generated in 'enu\diagnosticMessages.generated.json.lcg' + */ +const generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); + +/** + * The localization target produces the two following transformations: + * 1. 'src\loc\lcl\\diagnosticMessages.generated.json.lcl' => 'built\local\\diagnosticMessages.generated.json' + * convert localized resources into a .json file the compiler can understand + * 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg' + * generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json + */ +const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"].map(function (f) { + return path.join(builtLocalDirectory, f, "diagnosticMessages.generated.json"); +}).concat(generatedLCGFile); + for (const i in libraryTargets) { const entry = librarySourceMap[i]; const target = libraryTargets[i]; @@ -398,7 +415,6 @@ gulp.task(generateLocalizedDiagnosticMessagesJs, /*help*/ false, [], () => { }); // Localize diagnostics -const generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); gulp.task(generatedLCGFile, [generateLocalizedDiagnosticMessagesJs, diagnosticInfoMapTs], (done) => { if (fs.existsSync(builtLocalDirectory) && needsUpdate(generatedDiagnosticMessagesJSON, generatedLCGFile)) { exec(host, [generateLocalizedDiagnosticMessagesJs, lclDirectory, builtLocalDirectory, generatedDiagnosticMessagesJSON], done, done); @@ -576,8 +592,7 @@ gulp.task("dontUseDebugMode", /*help*/ false, [], (done) => { useDebugMode = fal gulp.task("VerifyLKG", /*help*/ false, [], () => { const expectedFiles = [builtLocalCompiler, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, typingsInstallerJs, cancellationTokenJs].concat(libraryTargets); const missingFiles = expectedFiles. - concat(fs.readdirSync(lclDirectory).map(function (d) { return path.join(builtLocalDirectory, d, "diagnosticMessages.generated.json"); })). - concat(generatedLCGFile). + concat(localizationTargets). filter(f => !fs.existsSync(f)); if (missingFiles.length > 0) { throw new Error("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory + diff --git a/Jakefile.js b/Jakefile.js index ba6943d30153d..06f13262a2841 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -239,6 +239,23 @@ var libraryTargets = librarySourceMap.map(function (f) { return path.join(builtLocalDirectory, f.target); }); +/** + * .lcg file is what localization team uses to know what messages to localize. + * The file is always generated in 'enu\diagnosticMessages.generated.json.lcg' + */ +var generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); + +/** + * The localization target produces the two following transformations: + * 1. 'src\loc\lcl\\diagnosticMessages.generated.json.lcl' => 'built\local\\diagnosticMessages.generated.json' + * convert localized resources into a .json file the compiler can understand + * 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg' + * generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json + */ +var localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"].map(function (f) { + return path.join(builtLocalDirectory, f); +}).concat(path.dirname(generatedLCGFile)); + // Prepends the contents of prefixFile to destinationFile function prependFile(prefixFile, destinationFile) { if (!fs.existsSync(prefixFile)) { @@ -444,7 +461,6 @@ compileFile(generateLocalizedDiagnosticMessagesJs, /*useBuiltCompiler*/ false, { noOutFile: true, types: ["node", "xml2js"] }); // Localize diagnostics -var generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); file(generatedLCGFile, [generateLocalizedDiagnosticMessagesJs, diagnosticInfoMapTs, generatedDiagnosticMessagesJSON], function () { var cmd = host + " " + generateLocalizedDiagnosticMessagesJs + " " + lclDirectory + " " + builtLocalDirectory + " " + generatedDiagnosticMessagesJSON; console.log(cmd); @@ -736,8 +752,7 @@ desc("Makes a new LKG out of the built js files"); task("LKG", ["clean", "release", "local"].concat(libraryTargets), function () { var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts, watchGuardFile]. concat(libraryTargets). - concat(fs.readdirSync(lclDirectory).map(function (d) { return path.join(builtLocalDirectory, d) })). - concat(path.dirname(generatedLCGFile)); + concat(localizationTargets); var missingFiles = expectedFiles.filter(function (f) { return !fs.existsSync(f); }); diff --git a/scripts/generateLocalizedDiagnosticMessages.ts b/scripts/generateLocalizedDiagnosticMessages.ts index edfe957515516..d7d5f5c0e7969 100644 --- a/scripts/generateLocalizedDiagnosticMessages.ts +++ b/scripts/generateLocalizedDiagnosticMessages.ts @@ -27,16 +27,54 @@ function main(): void { function visitDirectory(name: string) { const inputFilePath = path.join(inputPath, name, "diagnosticMessages", "diagnosticMessages.generated.json.lcl"); - const outputFilePath = path.join(outputPath, name, "diagnosticMessages.generated.json"); + fs.readFile(inputFilePath, (err, data) => { handleError(err); xml2js.parseString(data.toString(), (err, result) => { handleError(err); - writeFile(outputFilePath, xmlObjectToString(result)); + 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 = getPreferedLocaleName(result.LCX.$.TgtCul); + 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)); }); }); } + /** + * 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 - 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 . If it is a neutral locale for which the script is significant, the + * pattern is -