104 lines
2.6 KiB
JavaScript
104 lines
2.6 KiB
JavaScript
/**
|
|
* @file Lit Localize build script.
|
|
*
|
|
* @import { Config } from "@lit/localize-tools/lib/types/config.js"
|
|
*/
|
|
import * as fs from "node:fs/promises";
|
|
import * as path from "node:path";
|
|
import process from "node:process";
|
|
import { $ } from "zx";
|
|
|
|
const localizeRules = await import("../lit-localize.json", {
|
|
with: {
|
|
type: "json",
|
|
},
|
|
})
|
|
.then((module) => {
|
|
return /** @type {Config} */ (module.default);
|
|
})
|
|
|
|
.catch((error) => {
|
|
console.error("Failed to load lit-localize.json", error);
|
|
process.exit(1);
|
|
});
|
|
|
|
/**
|
|
* Attempt to stat a file, returning null if it doesn't exist.
|
|
*/
|
|
function tryStat(filePath) {
|
|
return fs.stat(filePath).catch(() => null);
|
|
}
|
|
|
|
/**
|
|
* Check if a generated file is up-to-date with its XLIFF source.
|
|
*
|
|
* @param {string} languageCode The locale to check.
|
|
*/
|
|
async function generatedFileIsUpToDateWithXliffSource(languageCode) {
|
|
const xlfFilePath = path.join("./xliff", `${languageCode}.xlf`);
|
|
const xlfStat = await tryStat(xlfFilePath);
|
|
|
|
if (!xlfStat) {
|
|
console.error(`lit-localize expected '${languageCode}.xlf', but XLF file is not present`);
|
|
|
|
process.exit(1);
|
|
}
|
|
|
|
const generatedTSFilePath = path.join("./src/locales", `${languageCode}.ts`);
|
|
|
|
const generatedTSFilePathStat = await tryStat(generatedTSFilePath);
|
|
|
|
// Does the generated file exist?
|
|
if (!generatedTSFilePathStat) {
|
|
return {
|
|
languageCode,
|
|
exists: false,
|
|
expired: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
languageCode,
|
|
exists: true,
|
|
// Is the generated file older than the XLIFF file?
|
|
expired: generatedTSFilePathStat.mtimeMs < xlfStat.mtimeMs,
|
|
};
|
|
}
|
|
|
|
const results = await Promise.all(
|
|
localizeRules.targetLocales.map(generatedFileIsUpToDateWithXliffSource),
|
|
);
|
|
|
|
const pendingBuild = results.some((result) => !result.exists || result.expired);
|
|
|
|
if (!pendingBuild) {
|
|
console.log("Local is up-to-date!");
|
|
process.exit(0);
|
|
}
|
|
|
|
const status = await $({ stdio: ["ignore", "pipe", "pipe"] })`npx lit-localize build`;
|
|
|
|
/**
|
|
* @type {Map<string, number>}
|
|
*/
|
|
const counts = new Map();
|
|
|
|
// Count all the missing message warnings
|
|
for (const line of status.stderr.split("\n")) {
|
|
const match = /^([\w-]+) message/.exec(line);
|
|
if (!match) continue;
|
|
|
|
const count = counts.get(match[1]) || 0;
|
|
counts.set(match[1], count + 1);
|
|
}
|
|
|
|
const locales = Array.from(counts.keys()).sort();
|
|
|
|
for (const locale of locales) {
|
|
console.log(`Locale '${locale}' has ${counts.get(locale)} missing translations`);
|
|
}
|
|
|
|
await $`npx prettier --write src/locale-codes.ts`;
|
|
|
|
console.log("\nTranslation tables rebuilt.\n");
|