Use American English spelling throughout
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* Check a catalogue against the strings the code actually asks for.
|
||||
* Check a catalog against the strings the code actually asks for.
|
||||
*
|
||||
* Two failures, and only one of them is visible without this.
|
||||
*
|
||||
@@ -8,9 +8,9 @@
|
||||
* as an untranslated word on screen, which somebody will eventually notice.
|
||||
*
|
||||
* A *stale* key -- one whose English no longer exists, usually because it was
|
||||
* mistyped when the catalogue was written -- is silent. The translation sits
|
||||
* mistyped when the catalog was written -- is silent. The translation sits
|
||||
* in the file looking correct, is never looked up, and the app renders English
|
||||
* for ever. Nothing warns, because a catalogue is only ever read by key.
|
||||
* for ever. Nothing warns, because a catalog is only ever read by key.
|
||||
*/
|
||||
/*
|
||||
* The parser, not the compiler.
|
||||
@@ -32,13 +32,13 @@ import { readFileSync, globSync } from "node:fs";
|
||||
/*
|
||||
* Two sets, because there are two questions and they need different nets.
|
||||
*
|
||||
* `wanted` is what a catalogue *owes*: the strings that actually reach t(),
|
||||
* `wanted` is what a catalog *owes*: the strings that actually reach t(),
|
||||
* tc() or plural(). Coverage is measured against it, so it has to stay strict
|
||||
* -- widening it would count every CSS class and JMAP method name as an
|
||||
* untranslated string.
|
||||
*
|
||||
* `seen` is every string literal in the source, and answers only "is this
|
||||
* catalogue key still written down anywhere". Stale detection needs the wide
|
||||
* catalog key still written down anywhere". Stale detection needs the wide
|
||||
* net: a key reaches t() as a variable often enough that a strict set reports
|
||||
* mostly false alarms.
|
||||
*/
|
||||
@@ -70,7 +70,7 @@ for (const file of globSync("web/src/**/*.{ts,tsx}").filter((f) => !f.includes("
|
||||
if (ts.isJsxText(n)) { const text = n.text.trim(); if (text) seen.add(text); }
|
||||
/*
|
||||
* A `label:` in a constant is still a string somebody has to translate --
|
||||
* it reaches t() one render later -- so it stays part of what a catalogue
|
||||
* it reaches t() one render later -- so it stays part of what a catalog
|
||||
* owes, and out of coverage it would flatter the number.
|
||||
*/
|
||||
if (ts.isPropertyAssignment(n) && n.name.getText(src) === "label" && ts.isStringLiteral(n.initializer)) wanted.add(n.initializer.text);
|
||||
@@ -81,10 +81,10 @@ for (const file of globSync("web/src/**/*.{ts,tsx}").filter((f) => !f.includes("
|
||||
if (ts.isCallExpression(n) && ts.isIdentifier(n.expression)) {
|
||||
const fn = n.expression.text, a0 = n.arguments[0];
|
||||
if ((fn === "t" || fn === "translate" || fn === "tNode") && a0 && ts.isStringLiteral(a0)) wanted.add(a0.text);
|
||||
// tc(context, source) keys the catalogue on both, joined by the same
|
||||
// tc(context, source) keys the catalog on both, joined by the same
|
||||
// control character tc() uses. Without this the contextual entries all
|
||||
// looked stale, which is the checker's own false alarm rather than a
|
||||
// catalogue problem.
|
||||
// catalog problem.
|
||||
if (fn === "tc" && a0 && ts.isStringLiteral(a0) && n.arguments[1] && ts.isStringLiteral(n.arguments[1])) {
|
||||
// Only the contextual key is required. The plain one is tc()'s
|
||||
// fallback, not a second obligation -- asking for both would report
|
||||
@@ -104,8 +104,8 @@ for (const file of globSync("web/src/**/*.{ts,tsx}").filter((f) => !f.includes("
|
||||
}
|
||||
|
||||
/*
|
||||
* A catalogue and a picker entry are two halves of one thing, and either half
|
||||
* alone is dead weight. A catalogue with no entry in UI_LANGUAGES never
|
||||
* A catalog and a picker entry are two halves of one thing, and either half
|
||||
* alone is dead weight. A catalog with no entry in UI_LANGUAGES never
|
||||
* reaches a reader -- it builds, it passes every test, and the language simply
|
||||
* is not offered. That happened to Dutch: the entry was added by a text
|
||||
* replacement anchored on a line that did not exist on that branch, so it was
|
||||
@@ -113,17 +113,17 @@ for (const file of globSync("web/src/**/*.{ts,tsx}").filter((f) => !f.includes("
|
||||
*/
|
||||
const languagesSrc = readFileSync("web/src/lib/languages.ts", "utf8");
|
||||
const registered = new Set([...languagesSrc.matchAll(/tag:\s*"([\w-]+)"/g)].map((m) => m[1]));
|
||||
const catalogues = new Set(globSync("web/src/locales/*.ts").map((f) => f.split("/").pop().replace(".ts", "")));
|
||||
const catalogs = new Set(globSync("web/src/locales/*.ts").map((f) => f.split("/").pop().replace(".ts", "")));
|
||||
|
||||
let failed = false;
|
||||
for (const tag of catalogues) {
|
||||
for (const tag of catalogs) {
|
||||
if (!registered.has(tag)) {
|
||||
failed = true;
|
||||
console.log(`!! ${tag}.ts exists but is not in UI_LANGUAGES — the language is never offered\n`);
|
||||
}
|
||||
}
|
||||
for (const tag of registered) {
|
||||
if (tag !== "en" && !catalogues.has(tag)) {
|
||||
if (tag !== "en" && !catalogs.has(tag)) {
|
||||
failed = true;
|
||||
console.log(`!! UI_LANGUAGES offers ${tag} but there is no ${tag}.ts — it would fall back to English\n`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user