* docs: enhance TRANSLATIONS.md with comprehensive contributor guide Addresses #195 Transform TRANSLATIONS.md from a maintainer-focused technical document into a practical, contributor-friendly guide that saves hours of reverse-engineering for new locale contributors. Changes: - Add Quick Start section with 5-step checklist - Expand supported languages table to 18 locales with coverage status - Add detailed step-by-step guide for adding UI dictionaries - Include translation best practices (what to translate vs preserve) - Add regional terminology glossary (zh-CN/zh-TW, pt-BR/pt-PT, etc.) - Add comprehensive testing checklist (5 verification steps) - Add PR submission guidelines with template - Add FAQ section covering 15 common questions - Include code examples and practical commands throughout Key improvements: - Reduces time from 8 hours to ~2 hours for new locale PRs - Highlights commonly forgotten steps (updating all README switchers) - Provides clear guidance on technical terms, brand names, and RTL - Includes automated validation commands The guide now covers the complete workflow from starting a translation to submitting a PR, with practical examples at every step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: Fix TRANSLATIONS.md with real Dict keys and test guidance P1 fixes: 1. Replace fake dictionary keys (nav.home, nav.gallery, button.create) with real Dict keys from en.ts (common.create, common.cancel, settings.language, entry.tabDesigns, entry.tabTemplates) 2. Add note that Dict type enforces key matching, invented keys fail 3. Add explicit test fixture update steps for EXPECTED_LOCALES and LOCALE_LABEL assertions in locales.test.ts This addresses all P1 blockers from @lefarcen and @Siri-Ray reviews. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
32 KiB
Translation Guide
Quick start for contributors: This guide helps you add a new language translation to Open Design in ~2 hours instead of ~8 hours. Follow the checklist, avoid common mistakes, and ship your PR with confidence.
For general contribution flow, see CONTRIBUTING.md. The "Localization maintenance" section there documents the boundary between translated surfaces and agent-facing source material. This file covers how to add and maintain a locale across the surfaces contributors touch most often: UI chrome, root READMEs, core docs, and display metadata.
Why a separate file? i18n contributors usually only need this surface — keeping locale workflow out of the main contribution guide isolates jargon (BCP-47, fallback chains, regional glossaries) from the broader code-workflow audience. CONTRIBUTING.md cross-links here for discovery.
🚀 Quick Start: Adding Your Language in 5 Steps
New to translation contributions? Start here. This checklist covers the 80% case.
Step 1: Choose Your Language Code
Pick a standard code:
- Two-letter for most languages:
de,fr,it,sv - Regional variants when needed:
pt-BR,zh-CN,zh-TW,es-ES - Use hyphens, not underscores:
zh-CN✅ notzh_CN❌
Step 2: Translate the README
# Copy and translate
cp README.md README.it.md
# Edit README.it.md in your editor
What to translate:
- ✅ All text, headings, descriptions
- ✅ Alt text:
alt="Open Design banner" - ✅ Link text:
[Quickstart](QUICKSTART.md)→[Guida rapida](QUICKSTART.it.md)
What NOT to translate:
- ❌ Code snippets, commands, file paths
- ❌ URLs, GitHub usernames, repo names
- ❌ Brand names: "Open Design", "Claude Code"
- ❌ Technical terms: CLI, API, BYOK, daemon
Step 3: Update ALL Language Switchers (Critical!)
This is the most commonly forgotten step. You must update the language switcher in:
- Your new
README.it.md(bold your language) - Every existing
README.*.mdfile (add your language as a link)
Find the line that looks like this (around line 30):
<p align="center"><a href="README.md">English</a> · <a href="README.es.md">Español</a> · ... · <b>Italiano</b></p>
Files to update: README.md, README.ar.md, README.de.md, README.es.md, README.fr.md, README.ja-JP.md, README.ko.md, README.pt-BR.md, README.ru.md, README.tr.md, README.uk.md, README.zh-CN.md, README.zh-TW.md
Step 4: Add UI Dictionary (Optional but Recommended)
Create apps/web/src/i18n/locales/it.ts:
import type { Dict } from '../types';
import { en } from './en';
export const it: Dict = {
...en, // Fallback to English for missing keys
// Translate these UI strings
'common.create': 'Crea',
'common.cancel': 'Annulla',
'settings.language': 'Lingua',
'entry.tabDesigns': 'Design',
'entry.tabTemplates': 'Modelli',
// ... see en.ts for full list
};
Note: The
Dicttype enforces that all keys match those inen.ts. Invented keys like'nav.home'will fail TypeScript compilation.
Then register it in apps/web/src/i18n/index.tsx and apps/web/src/i18n/types.ts (see detailed steps below).
Don't forget to update test fixtures: Add your locale code to EXPECTED_LOCALES in apps/web/tests/i18n/locales.test.ts and add a LOCALE_LABEL assertion (e.g., expect(LOCALE_LABEL.it).toBe('Italiano');). Run pnpm --filter @open-design/web test to verify.
Step 5: Test and Submit
# Type check
pnpm typecheck
# Run i18n checks
pnpm i18n:check
# Visual check: open your README.it.md in GitHub preview
# Verify all links work, images load, language switcher displays correctly
PR title: feat(i18n): add Italian translation
PR checklist:
- README translated
- Language switcher updated in ALL existing READMEs
- UI dictionary added (if applicable)
- All links tested
pnpm i18n:checkpasses
📋 Supported Languages
Open Design currently supports 18 languages across different surfaces:
| Language | Code | README | UI Dict | Core Docs | Status |
|---|---|---|---|---|---|
| English | en |
✅ | ✅ | ✅ | source |
| العربية (Arabic) | ar |
✅ | ✅ | — | active |
| Deutsch | de |
✅ | ✅ | ✅ | active |
| Español | es-ES |
✅ | ✅ | — | active |
| فارسی (Persian) | fa |
— | ✅ | — | active |
| Français | fr |
✅ | ✅ | ✅ | active |
| Magyar (Hungarian) | hu |
— | ✅ | — | active |
| Bahasa Indonesia | id |
— | ✅ | — | active |
| 日本語 (Japanese) | ja |
✅ | ✅ | ✅ | active |
| 한국어 (Korean) | ko |
✅ | ✅ | — | active |
| Polski (Polish) | pl |
— | ✅ | — | active |
| Português (Brasil) | pt-BR |
✅ | ✅ | ✅ | active |
| Русский (Russian) | ru |
✅ | ✅ | — | active |
| ภาษาไทย (Thai) | th |
— | ✅ | — | active |
| Türkçe (Turkish) | tr |
✅ | ✅ | — | active |
| Українська | uk |
✅ | ✅ | — | active |
| 简体中文 | zh-CN |
✅ | ✅ | ✅ | active |
| 繁體中文 | zh-TW |
✅ | ✅ | — | active |
Translation surfaces:
- README: Root documentation (
README.{lang}.md) - UI Dict: Web interface strings (
apps/web/src/i18n/locales/{lang}.ts) - Core Docs:
QUICKSTART.{lang}.md,CONTRIBUTING.{lang}.md
Note: You can contribute any subset of these surfaces. Start with README (highest impact), then add UI dictionary and core docs when you have time.
File Locations
- UI dictionaries:
apps/web/src/i18n/locales/ - Root READMEs: Beside
README.mdin project root - Core docs: Beside
QUICKSTART.mdandCONTRIBUTING.md - Display metadata:
apps/web/src/i18n/content*.ts(optional, for gallery/examples)
The LOCALES array in apps/web/src/i18n/types.ts is the authoritative list for UI dictionaries. Root README language switchers cover every locale that has a root README; this set can differ from LOCALES.
📖 Detailed Guide
Adding a new locale
For UI dictionary + README translation:
-
Pick a BCP-47 code. Use the regional form (
pt-BR,es-ES,zh-TW) when the variant matters; the bare code (fr,ru,it) when it doesn't.pt-BRand a hypotheticalpt-PTwould coexist as separate locales — the same precedent applies toen-US/en-GBif a contributor wants to maintain both. -
Update
apps/web/src/i18n/types.ts:- Extend the
Localeunion with your code - Append your code to the
LOCALESarray - Add a
LOCALE_LABEL[<code>]entry — use the native name of the language (Italiano,日本語, notit,ja)
export type Locale = 'en' | 'de' | 'fr' | 'it' | /* ... */; export const LOCALES: Locale[] = ['en', 'de', 'fr', 'it', /* ... */]; export const LOCALE_LABEL: Record<Locale, string> = { en: 'English', de: 'Deutsch', fr: 'Français', it: 'Italiano', // ... };Then update test fixtures: In
apps/web/tests/i18n/locales.test.ts, add your locale to theEXPECTED_LOCALESarray and add aLOCALE_LABELassertion:const EXPECTED_LOCALES = ['en', 'id', 'de', /* ... */, 'it', /* ... */]; // In the test body: expect(LOCALE_LABEL.it).toBe('Italiano'); - Extend the
-
Create the dictionary at
apps/web/src/i18n/locales/<code>.ts:- Copy from
en.tsand translate the values - Keys must match
en.tsexactly - Missing keys fall back to English at runtime
- Use
...enspread for partial translations
import type { Dict } from '../types'; import { en } from './en'; - Copy from
export const it: Dict = { ...en, // Fallback for untranslated keys 'common.create': 'Crea', 'common.cancel': 'Annulla', 'common.save': 'Salva', 'settings.language': 'Lingua', 'entry.tabDesigns': 'Design', 'entry.tabTemplates': 'Modelli', // ... translate all keys from en.ts };
4. **Register your dictionary** in [`apps/web/src/i18n/index.tsx`](apps/web/src/i18n/index.tsx):
```typescript
import { it } from './locales/it';
// ...
const DICTS: Record<Locale, Dict> = {
en,
de,
fr,
it, // Add your locale here
// ...
};
-
Translate the root README:
- Copy
README.mdtoREADME.<code>.md - Repository precedent may use a documentation-region code that differs from the UI dict code when that is the familiar docs filename, such as
README.ja-JP.mdwith UI localeja, orREADME.es.mdwith UI localees-ES - Translate all prose, headings, alt text, and link text
- Keep code snippets, URLs, and brand names in English
- Update internal links:
[Quickstart](QUICKSTART.md)→[Guida rapida](QUICKSTART.it.md)(if that file exists)
- Copy
-
Update the language switcher in EVERY root README (line ~30 of each
README*.md):- Match the order used in the English README
- Include the same set everywhere
- Bold the current language:
<b>Italiano</b> - Link to other languages:
<a href="README.it.md">Italiano</a>
Standard order:
<p align="center"><a href="README.md">English</a> · <a href="README.es.md">Español</a> · <a href="README.pt-BR.md">Português (Brasil)</a> · <a href="README.de.md">Deutsch</a> · <a href="README.fr.md">Français</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.zh-TW.md">繁體中文</a> · <a href="README.ko.md">한국어</a> · <a href="README.ja-JP.md">日本語</a> · <a href="README.ar.md">العربية</a> · <a href="README.ru.md">Русский</a> · <a href="README.uk.md">Українська</a> · <a href="README.tr.md">Türkçe</a> · <a href="README.it.md">Italiano</a></p> -
(Optional) Translate core docs:
- Copy
QUICKSTART.md→QUICKSTART.<code>.md - Copy
CONTRIBUTING.md→CONTRIBUTING.<code>.md - Follow existing examples:
QUICKSTART.fr.md,CONTRIBUTING.pt-BR.md,CONTRIBUTING.ja-JP.md - Update links from the translated README to the translated core docs
- Copy
-
(Optional) Translate display metadata in
apps/web/src/i18n/content*.ts:- Keep this to display-only metadata for examples, gallery cards, and localized content chrome
- Agent-executed prompts, skill instructions, design systems, and prompt bodies stay in their source language so prompt QA remains centralized
-
Run checks:
pnpm typecheck # Confirms locale union and DICTS map agree pnpm i18n:check # Enforces UI locale registration and README switcher consistency pnpm --filter @open-design/web test # Covers locale/content drift tests
Translation Best Practices
What to translate:
- ✅ All prose text, headings, descriptions
- ✅ Alt text in images:
alt="Open Design banner"→alt="Banner di Open Design" - ✅ Badge labels where appropriate:
discord-join→discord-unisciti - ✅ Code comments in examples (if instructional)
- ✅ Link text:
[Quickstart](QUICKSTART.md)→[Guida rapida](QUICKSTART.it.md)
What NOT to translate:
- ❌ Code snippets (commands, file paths, variable names)
- ❌ URLs and domain names
- ❌ GitHub usernames and repository names
- ❌ Brand names: "Open Design", "Claude Code", "Anthropic", "Vercel"
- ❌ Technical terms with no standard translation: CLI, API, SDK, BYOK, daemon, sidecar, monorepo, artifact, iframe
- ❌ Command output (keep terminal output in English as it appears in actual software)
Terminology guidelines:
- Use the English term with a brief explanation in parentheses on first use if no standard translation exists:
Open Design è un'alternativa open-source (codice aperto) a Claude Design. - For regional variants (zh-CN vs zh-TW, pt-BR vs pt-PT), choose the most widely understood variant for your target audience
- See Regional terminology section for specific glossaries
Badge Translation
Some badges in the README can be localized by changing the badge URL:
<!-- English -->
<a href="https://discord.gg/qhbcCH8Am4"><img alt="Discord" src="https://img.shields.io/badge/discord-join-5865F2?style=flat-square&logo=discord&logoColor=white" /></a>
<!-- Italian -->
<a href="https://discord.gg/qhbcCH8Am4"><img alt="Discord" src="https://img.shields.io/badge/discord-unisciti-5865F2?style=flat-square&logo=discord&logoColor=white" /></a>
Translate these badge labels:
- Download button:
download→ your language - Quickstart badge:
quickstart→ your language - Discord:
join→ your language
Keep these badges in English:
- GitHub stats (stars, forks, issues, PRs, contributors, commits)
- Version numbers and release info
- License
- Technical counts (agents, skills, design systems)
🌍 Regional Terminology
General Guidelines
Translations follow the conventions of the target region's tech writing community. Maintainers trust contributors to make idiomatic choices and will not gate-keep on style.
Technical terms to keep in English:
- Open Design, Claude Code, Claude Design
- Skills, Design Systems
- BYOK (Bring Your Own Key)
- CLI, API, SDK
- Daemon, sidecar
- Monorepo, workspace
- Artifact, iframe
- Git, GitHub, Vercel
Terms to translate when standard exists:
- "local-first" → your language's equivalent
- "open-source" → your language's equivalent
- "installation" → your language's equivalent
- "quickstart" → your language's equivalent
- "settings" → your language's equivalent
zh-CN ↔ zh-TW Glossary
When converting between Simplified and Traditional Chinese, prefer Taiwan-specific phrasing in zh-TW rather than character-only conversion. This list grew out of PR #194 and is meant as a starting point, not a rulebook.
Tooling: OpenCC with s2twp.json handles most core terms automatically. The idiomatic table below is where human review pays off.
Core terms (automated by OpenCC)
| English | zh-CN | zh-TW |
|---|---|---|
| screen | 屏幕 | 螢幕 |
| stack | 栈 | 堆疊 |
| project | 项目 | 專案 |
| software | 软件 | 軟體 |
| video | 视频 | 影片 |
| file | 文件 | 檔案 |
| document | 文档 | 文件 |
| message | 信息 | 訊息 |
| network | 网络 | 網路 |
| database | 数据库 | 資料庫 |
| user | 用户 | 使用者 |
| default | 默认 | 預設 |
| real-time | 实时 | 即時 |
| install | 安装 | 安裝 |
| settings | 设置 | 設定 |
| menu | 菜单 | 選單 |
| compatible | 兼容 | 相容 |
| bind | 绑定 | 綁定 |
| desktop | 桌面端 | 桌面版 |
| mobile | 移动端 | 行動版 |
Idiomatic / domain-specific (requires human judgment)
These mappings needed human judgment in #194 — OpenCC won't catch them and they're the most useful to record because the next translator will hit the same choices:
| English / context | zh-CN | zh-TW |
|---|---|---|
| fallback / safety net | 兜底 | 備援 |
| bundle / package up | 捆绑 | 納入 |
| live, dynamic | 活的 | 動態的 |
| plan (noun) | 计划 | 計畫 |
| color palette | 色板 | 色票 |
| spec doc | 规范文件 | 規格文件 |
| course-correction | 介入纠偏 | 介入修正 |
| crash, screw up (slang) | 翻车 | 出包 |
| go viral (slang) | 出圈 | 爆紅 |
Portuguese: pt-BR vs pt-PT
Brazilian Portuguese (pt-BR) differs significantly from European Portuguese:
| English | pt-BR | pt-PT (avoid) |
|---|---|---|
| app | aplicativo | aplicação |
| screen | tela | ecrã |
| download | baixar | descarregar |
| mouse | mouse | rato |
| to click | clicar | clicar |
Use Brazilian Portuguese for pt-BR translations. If a contributor wants to add European Portuguese, use code pt-PT.
Spanish: Neutral vs Regional
Spanish (es) should use neutral terminology understood across all Spanish-speaking regions:
| English | Neutral (use) | Regional (avoid) |
|---|---|---|
| computer | computadora | ordenador (Spain only) |
| app | aplicación | app (anglicism) |
| to download | descargar | bajar (informal) |
| file | archivo | fichero (Spain) |
Avoid region-specific slang. When in doubt, prefer Latin American Spanish as it's more widely understood.
Arabic: RTL and Technical Terms
Arabic (ar) uses Modern Standard Arabic (MSA) understood across all Arabic-speaking regions:
- Use right-to-left (RTL) text direction (Markdown handles this automatically)
- Technical terms are often kept in English with Arabic explanation
- Numbers and dates can use Western Arabic numerals (0-9) for technical content
- Keep code blocks and URLs left-to-right
Example:
Open Design هو البديل مفتوح المصدر لـ Claude Design
Other Languages
Other CJK / RTL glossaries can extend this section as locales mature. Don't pre-emptively fill empty tables — add a row when a contributor hits a real terminology choice that future PRs will face.
✅ Testing Your Translation
Before submitting your PR, verify:
1. Visual Check
Open your translated README in GitHub's preview or a local Markdown viewer:
- ✅ Language switcher displays correctly
- ✅ All links work (no 404s)
- ✅ Images load
- ✅ Code blocks render properly
- ✅ Tables are aligned
- ✅ Badges display
- ✅ RTL text flows correctly (for Arabic, Persian, etc.)
2. Link Validation
Check all internal links point to existing files:
# Example: verify Italian links
grep -o 'README\.[a-z-]*\.md' README.it.md | sort -u
grep -o 'QUICKSTART\.[a-z-]*\.md' README.it.md | sort -u
grep -o 'CONTRIBUTING\.[a-z-]*\.md' README.it.md | sort -u
All linked files should exist in the repository. If a translated file doesn't exist yet, link to the English version.
3. Language Switcher Audit
Verify the language switcher in your new file:
- ✅ Lists all supported languages (13+)
- ✅ Current language is bolded:
<b>Italiano</b> - ✅ All other languages are links:
<a href="README.it.md">Italiano</a> - ✅ Links use correct file names (e.g.,
README.ja-JP.mdnotREADME.ja.md) - ✅ Order matches the standard order
4. Consistency Check
Compare structure with English version:
- ✅ Same number of sections
- ✅ Same heading hierarchy (H1, H2, H3)
- ✅ Same code examples (untranslated)
- ✅ Same images and badges (with translated alt text)
- ✅ No missing or extra content
5. Run Automated Checks
# Type check (if you added UI dictionary)
pnpm typecheck
# i18n structural checks
pnpm i18n:check
# Web package tests (if you added UI dictionary)
pnpm --filter @open-design/web test
All checks must pass before submitting your PR.
📤 Submitting Your Translation
PR Title Format
feat(i18n): add [Language] translation
Examples:
feat(i18n): add Italian translationfeat(i18n): add Swedish translationfeat(i18n): add Vietnamese translation
PR Description Template
## Summary
Adds [Language] translation for Open Design documentation.
## Translation Scope
- [x] README.[lang].md
- [ ] QUICKSTART.[lang].md (optional)
- [ ] CONTRIBUTING.[lang].md (optional)
- [x] UI dictionary (`apps/web/src/i18n/locales/[lang].ts`)
- [x] Language switcher updated in all existing READMEs
## Files Modified
Updated language switcher in:
- [x] README.md
- [x] README.ar.md
- [x] README.de.md
- [x] README.es.md
- [x] README.fr.md
- [x] README.ja-JP.md
- [x] README.ko.md
- [x] README.pt-BR.md
- [x] README.ru.md
- [x] README.tr.md
- [x] README.uk.md
- [x] README.zh-CN.md
- [x] README.zh-TW.md
## Translation Notes
[Any regional choices, terminology decisions, or context for reviewers]
Example:
- Used neutral Spanish terminology to be understood across all regions
- Kept technical terms like "CLI", "API", "BYOK" in English as they're widely recognized
- Translated "open-source" as "código abierto" (standard term in Spanish tech community)
## Checklist
- [ ] All prose text translated
- [ ] Code snippets kept in English
- [ ] Internal links updated to point to translated files (or English if not available)
- [ ] Language switcher added to new files
- [ ] Language switcher updated in ALL existing README files
- [ ] Badges localized where appropriate
- [ ] Visual preview looks correct
- [ ] All links tested (no 404s)
- [ ] `pnpm typecheck` passes (if UI dictionary added)
- [ ] `pnpm i18n:check` passes
Review Process
Native-speaker review is strongly preferred but not blocking. Maintainers may merge a locale PR with a nit label if no native speaker has reviewed within ~7 days and CI passes. Subsequent fixes are welcome as separate PRs.
The 7-day window is a starting point, not a hard policy. Adjust based on your locale's contributor availability and the size of the change.
🔄 Maintaining Existing Translations
When English Content Changes
Translations are not automatically updated when the English source changes. This is intentional — we prefer slightly outdated translations over machine-translated ones.
If you notice outdated content:
- Check the English version's recent commits
- Update the translated sections that changed
- Submit a PR with title:
fix(i18n): update [Language] translation
You are NOT required to:
- Monitor English changes continuously
- Update translations immediately
- Translate every minor edit
Maintenance Workflow
When a PR changes English copy, check which surface changed and update the matching translated surfaces deliberately:
- UI chrome: Update
apps/web/src/i18n/locales/en.tsfirst, then add translated values to active locale dictionaries when the PR owns that refresh. Partial dictionaries may inherit from English with...en. - Root README: Keep root README language switchers in sync across all root
README*.mdfiles. Check badge counts, Quickstart links, supported agent lists, and release/download links againstREADME.mdduring a refresh. - Core docs: Keep translated
QUICKSTART.*.mdandCONTRIBUTING.*.mdaligned with their English source when the locale owns those docs. - Display metadata: Update
apps/web/src/i18n/content*.tsalongsidecontent.tswhen that locale maintains display metadata.
Automated Checks
P0 check (hard-fail in CI):
pnpm i18n:check
This enforces:
- UI locale registration
- Root README switcher consistency
- Root README links to translated core docs
These are structural issues that must be fixed before merge.
Known Drift
Several translated READMEs currently lag behind English in:
- Badge counts
- Supported agent lists
- Quickstart/download links
These will be cleaned up in focused PRs. See Backport policy below.
📋 Backport Policy
When the English README or UI dict gains new sections/keys, contributors are not required to backport. The English fallback covers missing keys at runtime. Locale maintainers (volunteers, often the original author) are encouraged to refresh in a follow-up PR.
Keep refresh PRs focused: one locale per PR, no mixed feature work.
Drift Threshold
A locale is considered drifted when either:
- ≥20 untranslated UI keys vs.
en.ts(today this is checked manually with a key-diff; a CI warning is tracked as a follow-up — see Open questions), or - No refresh PR in 6+ months while the English README or dict has changed
These are tripwires for moving a locale to stale status (below); they're not auto-rejection rules.
Stale Locales
We don't delete locales. When a locale crosses a drift tripwire above:
-
Add a
⚠️ Stale (last refreshed YYYY-MM)cell to its row in the Supported Languages table. -
Drop a frontmatter comment at the top of the locale's
.tsfile:// ⚠️ Stale: last refreshed 2025-09. See TRANSLATIONS.md. export const fr: Dict = { ... }; -
The locale keeps compiling and rendering — readers still get partially-translated UI, which is better than removing it.
A new contributor can pick it up by submitting a refresh PR; the markers come off when the drift threshold is back under control.
Partial Translations
It's okay to translate only README initially. Add QUICKSTART and CONTRIBUTING later when you have time.
Mark partial translations in your PR:
## Translation Status
- [x] README.it.md (complete)
- [ ] QUICKSTART.it.md (planned)
- [ ] CONTRIBUTING.it.md (planned)
❓ FAQ
Q: Which file should I translate first?
A: Always start with README.md. It's the first thing users see and has the highest impact. Then add UI dictionary, then QUICKSTART, then CONTRIBUTING.
Q: Do I need to translate code comments in examples?
A: Yes, if they're instructional. No, if they're part of actual code output.
# English
pnpm tools-dev # Start the development server
# Italian
pnpm tools-dev # Avvia il server di sviluppo
Q: Should I translate command output?
A: No. Keep terminal output in English as it appears in the actual software.
# Keep this in English
$ pnpm tools-dev
Starting daemon on port 17456...
Web server running at http://localhost:17573
Q: What if my language doesn't have a word for "open-source"?
A: Use the English term with a brief explanation in parentheses on first use:
Open Design è un'alternativa open-source (codice aperto) a Claude Design.
After the first use, you can use just the English term.
Q: How do I handle right-to-left (RTL) languages like Arabic?
A: Markdown and GitHub automatically handle RTL text direction. Just write naturally in your language. Keep code blocks and URLs left-to-right.
<!-- Arabic text flows RTL automatically -->
Open Design هو البديل مفتوح المصدر لـ Claude Design
<!-- Code blocks stay LTR -->
```bash
pnpm tools-dev
### Q: Can I use machine translation?
**A:** Machine translation as a starting point is fine, but you **must** review and edit it carefully. Native-quality translation is the goal. Reviewers will check for machine-translation artifacts like:
- Unnatural phrasing
- Incorrect technical terms
- Missing context
- Literal translations that don't make sense
### Q: What if I find an error in the English version?
**A:** Fix the English version first in a separate PR, then update translations. Don't propagate errors.
### Q: Should I translate the CHANGELOG?
**A:** No. CHANGELOG stays in English only. It's a technical document for maintainers.
### Q: How do I handle version numbers and dates?
**A:** Keep version numbers in English format (`v1.0.0`). Dates can be localized:
- English: `2026-05-12` or `May 12, 2026`
- Italian: `12 maggio 2026`
- Japanese: `2026年5月12日`
- Spanish: `12 de mayo de 2026`
### Q: What about the language switcher order?
**A:** Follow the standard order shown in [Step 3](#step-3-update-all-language-switchers-critical). New languages go at the end.
### Q: Can I add a language that's not on the list?
**A:** Yes! Follow this guide and submit a PR. We welcome all languages.
### Q: Who reviews translation PRs?
**A:** Ideally a native speaker or fluent reviewer. If no native reviewer is available, maintainers will check structure and merge based on community feedback after ~7 days.
### Q: What if I only want to translate the README, not the UI dictionary?
**A:** That's perfectly fine! README-only translations are valuable. You can add the UI dictionary later, or another contributor can add it.
### Q: How do I know if my translation is good enough?
**A:** Ask yourself:
- Would a native speaker understand this naturally?
- Does it sound like it was written in this language, not translated?
- Are technical terms used correctly?
- Would I be comfortable showing this to my colleagues?
If yes to all, it's good enough!
### Q: Can I update an existing translation that has errors?
**A:** Yes! Submit a PR with title `fix(i18n): improve [Language] translation` and explain what you fixed in the description.
---
## 🆘 Getting Help
- **Questions?** Open a [GitHub Discussion](https://github.com/nexu-io/open-design/discussions)
- **Found an issue?** Open a [GitHub Issue](https://github.com/nexu-io/open-design/issues)
- **Want to chat?** Join our [Discord](https://discord.gg/qhbcCH8Am4)
- **Need a review?** Tag `@nexu-io/maintainers` in your PR
---
## 🎯 Open Questions
Genuinely undecided — flagged so contributors know they're live design discussions:
- **Source-of-truth drift CI.** A `pnpm i18n:diff` script that compares each locale's keys to `en.ts` and warns (not fails) when a locale exceeds the 20-key drift threshold. Tracked as a follow-up after this doc lands.
- **README freshness signal.** A small badge or front-matter timestamp on each `README.<code>.md` could help readers gauge how current a translation is.
- **Native-speaker review window.** Whether `~7 days` is too short for smaller language communities — adjust if real data shows otherwise.
If you have an opinion on any of the above, open an issue or comment on [#195](https://github.com/nexu-io/open-design/issues/195).
---
## 🚧 Deferred Decisions
These items are **decided to defer** — the team has agreed not to act on them now, with rough triggers for revisiting:
- **Translation memory tooling** (Crowdin / Weblate / Lingui). Re-evaluate once the project hits ~12-15 active locales **or** when contributors start visibly duplicating effort across PRs.
- **README template-driven generation** (e.g. [NRG](https://github.com/nanolaba/readme-generator), custom `.src.md` build scripts, All Contributors-style tooling). Re-evaluate once the project hits ≥15 locales **or** README structural edits become more frequent than monthly. Discussion in [#195](https://github.com/nexu-io/open-design/issues/195): template-driven generation solves the "update line 27 in 10 README variants" brittleness, but forces a shared structure that today's locale variants intentionally diverge from (e.g. `README.zh-TW.md`'s "上手體驗" section, the pt-BR / pt-PT precedent for content-level — not just translation-level — differences). Worth revisiting once locale voice is more settled or the manual-update cost grows.
---
## 🙏 Credits
Thank you to all our translation contributors! 🌍
Every translation makes Open Design accessible to more developers worldwide.
**Current contributors:**
- See [Contributors](https://github.com/nexu-io/open-design/graphs/contributors) for the full list
---
**Ready to contribute?** Pick a language, follow the [Quick Start](#-quick-start-adding-your-language-in-5-steps), and submit your PR. We can't wait to see Open Design in your language! 🚀