diff --git a/docs/CONTRIBUTING_i18n.md b/docs/CONTRIBUTING_i18n.md index 6e97e463..bab73096 100644 --- a/docs/CONTRIBUTING_i18n.md +++ b/docs/CONTRIBUTING_i18n.md @@ -2,80 +2,113 @@ Thank you for considering contributing to our localization work — your help is appreciated. -Quick overview - -- cvr-i18 is a CLI that helps manage simple top-level JSON locale files: - - Detect duplicated top-level keys - - Find keys missing versus a base file (default: en.json) - - Export missing entries for translators - - Reorder keys to match the base file for predictable diffs - - Operate on a directory or a single file - -Get the CLI (No binary provided yet) - -```bash -git clone https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli -cd clash-verge-rev-i18n-cli -cargo install --path . -# or -cargo install --git https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli -``` - -Common commands - -- Show help: `cvr-i18` -- Directory (auto-detects `./locales` or `./src/locales`): `cvr-i18 -d /path/to/locales` -- Check duplicates: `cvr-i18 -k` -- Check missing keys: `cvr-i18 -m` -- Export missing keys: `cvr-i18 -m -e ./exports` -- Sort keys to base file: `cvr-i18 -s` -- Use a base file: `cvr-i18 -b base.json` -- Single file: `cvr-i18 -f locales/zh.json` - -Options (short) - -- `-d, --directory ` -- `-f, --file ` -- `-k, --duplicated-key` -- `-m, --missing-key` -- `-e, --export ` -- `-s, --sort` -- `-b, --base ` - -Exit codes - -- `0` — success (no issues) -- `1` — issues found (duplicates/missing) -- `2` — error (IO/parse/runtime) - -How to contribute (recommended steps) +## Quick workflow - Start small: fix typos, improve phrasing, or refine tone and consistency. -- Run the CLI against your locale files to detect duplicates or missing keys. -- Export starter JSONs for translators with `-m -e `. +- Use `scripts/cleanup-unused-i18n.mjs` (see below) to keep locale files aligned and free of dead keys. - Prefer incremental PRs or draft PRs; leave a comment on the issue if you want guidance. - Open an issue to report missing strings, UI context, or localization bugs. - Add or improve docs and tests to make future contributions easier. +## Locale maintenance script + +The repository ships with `scripts/cleanup-unused-i18n.mjs`, a TypeScript-aware analyzer that: + +- Scans `src/` and `src-tauri/` for `t("...")` usages (including dynamic prefixes) to identify which locale keys are referenced. +- Reports unused keys per locale and optionally removes them. +- Compares every locale against the baseline (default: `en.json`) to produce missing/extra key lists. +- Aligns locale structure/order with the baseline so diffs stay predictable. +- Emits optional JSON reports for CI or manual review. + +### Typical commands + +```bash +# Dry-run audit (recommended before opening a PR) +pnpm node scripts/cleanup-unused-i18n.mjs + +# Apply removals and align to the baseline structure (same as pnpm format:i18n) +pnpm node scripts/cleanup-unused-i18n.mjs --apply --align + +# Generate a machine-readable report +pnpm node scripts/cleanup-unused-i18n.mjs --report ./i18n-report.json +``` + +Shorthand task runner aliases: + +- `pnpm format:i18n` → `node scripts/cleanup-unused-i18n.mjs --align --apply` +- `pnpm node scripts/cleanup-unused-i18n.mjs -- --help` — view all flags (`--baseline`, `--src`, `--keep-extra`, `--no-backup`, `--report`, `--apply`, `--align`). + +### Recommended steps before submitting translations + +1. Run the script in dry-run mode to review unused/missing key output. +2. Apply removals/alignment locally if your changes introduce new keys or delete UI. +3. Inspect `.bak` backups (created by default) when applying changes to confirm nothing important disappeared. +4. For dynamic key patterns, add explicit references or update the whitelist if the script misidentifies usage. + PR checklist - Keep JSON files UTF-8 encoded. - Follow the repo’s locale file structure and naming conventions. -- Reorder keys to match the base file (`-s`) for minimal diffs. +- Run `pnpm format:i18n` to align with the baseline file for minimal diffs. - Test translations in a local dev build before opening a PR. - Reference related issues and explain any context for translations or changes. Notes -- The tool expects simple top-level JSON key/value maps. -- Exported JSONs are starter files for translators (fill in values, keep keys). -- Sorting keeps diffs consistent and reviewable. +- The script expects simple top-level JSON key/value maps in each locale file. +- `.bak` snapshots are created automatically when applying fixes; remove them once you confirm the changes. +- Alignment keeps key order stable across locales, which makes reviews easier. -Repository -https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli +## Locale Key Structure Guidelines + +- **Top-level scope** — Map each locale namespace to a route-level feature or domain module, mirroring folder names in `src/pages`/`src/services`. Prefer plural nouns for resource pages (`profiles`, `connections`) and reuse existing slugs where possible (`home`, `settings`). +- **Common strings** — Put reusable actions, statuses, and units in `common.*`. Before adding a new key elsewhere, check whether an equivalent entry already lives under `common`. +- **Feature layout** — Inside a namespace, group strings by their UI role using consistent buckets such as `page`, `actions`, `labels`, `tooltips`, `notifications`, `errors`, and `placeholders`. Avoid duplicating the same bucket at multiple levels. +- **Components and dialogs** — When a feature needs component-specific copy, nest it under `components.` or `dialogs.` instead of leaking implementation names like `proxyTunCard`. +- **Naming style** — Use lower camelCase for keys, align with the feature’s UI wording, and keep names semantic (`systemProxy` rather than `switch1`). Reserve template placeholders for dynamic values (e.g., `{{name}}`). +- **Example** + +```json +{ + "profiles": { + "page": { + "title": "Profiles", + "description": "Manage subscription sources" + }, + "actions": { + "new": "@:common.actions.new", + "import": "Import" + }, + "notifications": { + "importSuccess": "Profile imported successfully" + }, + "components": { + "batchDialog": { + "title": "Batch Operations" + } + } + } +} +``` + +Referencing `@:common.actions.new` helps reuse shared strings through the i18n loader. + +### Pending Cleanup — Reuse `common.actions` + +- `profile.viewer.buttons.save` → `@:common.actions.save` +- `profile.viewer.buttons.cancel` → `@:common.actions.cancel` +- `profile.menu.delete` → `@:common.actions.delete` +- `profiles.page.actions.new` → `@:common.actions.new` +- `test.page.actions.new` → `@:common.actions.new` +- `home.ipInfo.labels.retry` → `@:common.actions.retry` +- `settings.backup.actions.refresh` → `@:common.actions.refresh` +- `settings.backup.actions.save` → `@:common.actions.save` +- `settings.backup.actions.delete` → `@:common.actions.delete` +- `home.systemInfo.labels.enabled` → `@:common.status.enabled` +- `home.systemInfo.labels.disabled` → `@:common.status.disabled` ## Feedback & Contributions -- For tool usage issues or feedback: please open an Issue in the [repository](https://github.com/clash-verge-rev/clash-verge-rev-i18n-cli) so it can be tracked and addressed. +- For tool usage issues or feedback: please open an Issue in this repository so it can be tracked and addressed. - For localization contributions (translations, fixes, context notes, etc.): submit a PR or Issue in this repository and include examples, context, and testing instructions when possible. - If you need help or a review, leave a comment on your submission requesting assistance.