5.5 KiB
5.5 KiB
CONTRIBUTING — i18n
Thank you for considering contributing to our localization work — your help is appreciated.
Quick workflow
- Start small: fix typos, improve phrasing, or refine tone and consistency.
- 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/andsrc-tauri/fort("...")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
# 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 --applypnpm node scripts/cleanup-unused-i18n.mjs -- --help— view all flags (--baseline,--src,--keep-extra,--no-backup,--report,--apply,--align).
Recommended steps before submitting translations
- Run the script in dry-run mode to review unused/missing key output.
- Apply removals/alignment locally if your changes introduce new keys or delete UI.
- Inspect
.bakbackups (created by default) when applying changes to confirm nothing important disappeared. - 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.
- Run
pnpm format:i18nto 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 script expects simple top-level JSON key/value maps in each locale file.
.baksnapshots are created automatically when applying fixes; remove them once you confirm the changes.- Alignment keeps key order stable across locales, which makes reviews easier.
Locale Key Structure Guidelines
The locale files now follow a two-namespace layout designed to mirror the React/Rust feature tree:
shared.*— cross-cutting vocabulary (buttons, statuses, validation hints, window chrome, etc.).- Buckets to prefer:
actions,labels,statuses,messages,placeholders,units,validation,window,editorModes.
- Buckets to prefer:
- Add to
sharedonly when the copy is used (or is expected to be reused) by two or more features. Otherwise keep it in the owning feature namespace. <feature>.*— route-level or domain-level strings scoped to a single feature.- Top-level keys mirror folders under
src/pages,src/components, or service domains (settings,proxies,profiles,home,unlock,layout, …). - Within a feature namespace, prefer consistent buckets like
page,sections,forms,fields,actions,tooltips,notifications,errors,dialogs,tables,components. Choose the minimum depth needed to describe the UI.
- Top-level keys mirror folders under
Authoring guidelines
- Follow the shared/feature split — before inventing a new key, check whether an equivalent exists under
shared.*. - Use camelCase leaf keys — keep names semantic (
systemProxy,updateInterval) and avoid positional names (item1,btn_ok). - Group by UI responsibility — for example:
settings.dns.fields.listensettings.dns.dialog.titlesettings.dns.sections.general
- Component-specific copy — nest under
components.<ComponentName>ordialogs.<DialogName>to keep implementation-specific strings organized but still discoverable. - Dynamic placeholders — continue using
{{placeholder}}syntax and document required params in code when possible.
Minimal example
{
"shared": {
"actions": {
"save": "Save",
"cancel": "Cancel"
}
},
"profiles": {
"page": {
"title": "Profiles",
"actions": {
"import": "Import",
"updateAll": "Update All Profiles"
},
"notifications": {
"importSuccess": "Profile imported successfully"
}
},
"components": {
"batchDialog": {
"title": "Batch Operations",
"items": "items"
}
}
}
}
Whenever you need a common verb or label, reference shared.* directly in the code (shared.actions.save, shared.labels.name, …) instead of duplicating the copy in a feature namespace.
Feedback & Contributions
- 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.