The console writes its strings inline, t('key', 'English'), which reads well in code but left src/i18n/en.json with only 353 of them. A translation starts from one file, so this makes en.json the whole English catalog and keeps it complete.
tools/i18n-extract.mjs (npm run i18n) uses the TypeScript parser, already a dev dependency, to find every t() with English, and adds what en.json lacks.
It understands t(key, 'text'), t(key, 'text', {…}), t(key, {defaultValue}) and plurals (defaultValue_one/_other become key_one/key_other).
It never changes a string en.json already has, since that's the one people see. New keys go at the end of their group, so the existing file isn't reordered.
Keys built at run time are skipped.
npm run i18n:check is in CI, after lint. A new string without an entry fails the build with its file and line, and says to run npm run i18n.
1,124 strings added, for 1,477 in all.
Nothing visible changes. I checked that no new key has different English at different call sites; if one did, the catalog would have made them read the same.
Four keys renamed on the audit log's change table: audit.change.field/before/after/secret become audit.changes.*. audit.change is also a string of its own, and a nested catalog can't hold both. The text is unchanged.
Checked: 518 tests pass, and lint, typecheck and build are clean. i18n:check passes.
Merge order: after admin #59 (the Security page), rerun npm run i18n so its ~70 strings are in too, or CI will say which are missing. I'll do that rebase.
The console writes its strings inline, `t('key', 'English')`, which reads well in code but left `src/i18n/en.json` with only 353 of them. A translation starts from one file, so this makes `en.json` the whole English catalog and keeps it complete.
- **`tools/i18n-extract.mjs`** (`npm run i18n`) uses the TypeScript parser, already a dev dependency, to find every `t()` with English, and adds what `en.json` lacks.
- It understands `t(key, 'text')`, `t(key, 'text', {…})`, `t(key, {defaultValue})` and plurals (`defaultValue_one`/`_other` become `key_one`/`key_other`).
- It never changes a string `en.json` already has, since that's the one people see. New keys go at the end of their group, so the existing file isn't reordered.
- Keys built at run time are skipped.
- **`npm run i18n:check`** is in CI, after lint. A new string without an entry fails the build with its file and line, and says to run `npm run i18n`.
- **1,124 strings added**, for 1,477 in all.
- **Nothing visible changes.** I checked that no new key has different English at different call sites; if one did, the catalog would have made them read the same.
- **Four keys renamed** on the audit log's change table: `audit.change.field/before/after/secret` become `audit.changes.*`. `audit.change` is also a string of its own, and a nested catalog can't hold both. The text is unchanged.
**Checked:** 518 tests pass, and lint, typecheck and build are clean. `i18n:check` passes.
**Merge order:** after admin #59 (the Security page), rerun `npm run i18n` so its ~70 strings are in too, or CI will say which are missing. I'll do that rebase.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The console writes its strings inline,
t('key', 'English'), which reads well in code but leftsrc/i18n/en.jsonwith only 353 of them. A translation starts from one file, so this makesen.jsonthe whole English catalog and keeps it complete.tools/i18n-extract.mjs(npm run i18n) uses the TypeScript parser, already a dev dependency, to find everyt()with English, and adds whaten.jsonlacks.t(key, 'text'),t(key, 'text', {…}),t(key, {defaultValue})and plurals (defaultValue_one/_otherbecomekey_one/key_other).en.jsonalready has, since that's the one people see. New keys go at the end of their group, so the existing file isn't reordered.npm run i18n:checkis in CI, after lint. A new string without an entry fails the build with its file and line, and says to runnpm run i18n.audit.change.field/before/after/secretbecomeaudit.changes.*.audit.changeis also a string of its own, and a nested catalog can't hold both. The text is unchanged.Checked: 518 tests pass, and lint, typecheck and build are clean.
i18n:checkpasses.Merge order: after admin #59 (the Security page), rerun
npm run i18nso its ~70 strings are in too, or CI will say which are missing. I'll do that rebase.a1f7f05a96to77c6712085