Summary
I'd like to contribute a complete French translation of the documentation (docs/*.md), together with the i18n infrastructure needed for the Fumadocs website to serve both languages. I'm opening this issue first to check that you'd welcome such a contribution before I start translating ~25 files, and to agree on the approach.
Motivation
OpenSpec's docs are substantial (~250 KB across 25 pages). A French version would make the project more accessible to the French-speaking dev community. I'm a native French speaker, I use OpenSpec, and I'm willing to do the work and maintain the translation over time.
Proposed approach
Keeping docs/*.md as the single source of truth, mirrored per locale:
- Translated sources in
docs/fr/ , one file per manifest entry (docs/fr/installation.md mirrors docs/installation.md, etc.). Code blocks, CLI/slash-command names, and product terms stay in English.
- Sync pipeline extension ,
website/scripts/sync-docs.mjs additionally looks for docs/fr/<source> and emits content/docs/<slug>.fr.md (Fumadocs locale-suffix convention), with English fallback when a French file is missing, so translation can land progressively without ever breaking the build. githubSource points at the docs/fr/ file so "edit this page" opens the right source.
- Website i18n (Fumadocs) ,
defineI18n({ defaultLanguage: 'en', languages: ['en', 'fr'] }), routes moved under app/[lang]/ with generateStaticParams (compatible with the current output: 'export' static deploy to Cloudflare Pages , no middleware needed), hideLocale: 'default-locale' so all existing English URLs stay unchanged, French UI translations + language switcher, and a per-locale static search index.
Reviewable PR split
- PR 1: website i18n infrastructure + sync-script changes (no translated content yet; English fallback everywhere). Small, mechanical, easy to verify.
- PR 2..n: translations, one PR per sidebar section (Start here → Understand it → Guides → Reference → Help), so each PR is a reviewable size.
Open question: keeping the translation fresh
Translations rot when the English source moves. I'd propose stamping each docs/fr/*.md with the source commit (or content hash) it was translated from, plus a small CI check (or report) that flags French pages whose English source has changed since. Happy to implement whatever mechanism you prefer or none, if you'd rather keep it lightweight.
Questions for maintainers
- Are you open to carrying a French translation in-repo at all?
- Any preference on the URL scheme (
/fr/docs/...) or the docs/fr/ layout?
- Any preference on the staleness-tracking mechanism?
If you'd rather not take on translation maintenance, no hard feelings ; I can keep it on my fork instead.
Summary
I'd like to contribute a complete French translation of the documentation (
docs/*.md), together with the i18n infrastructure needed for the Fumadocs website to serve both languages. I'm opening this issue first to check that you'd welcome such a contribution before I start translating ~25 files, and to agree on the approach.Motivation
OpenSpec's docs are substantial (~250 KB across 25 pages). A French version would make the project more accessible to the French-speaking dev community. I'm a native French speaker, I use OpenSpec, and I'm willing to do the work and maintain the translation over time.
Proposed approach
Keeping
docs/*.mdas the single source of truth, mirrored per locale:docs/fr/, one file per manifest entry (docs/fr/installation.mdmirrorsdocs/installation.md, etc.). Code blocks, CLI/slash-command names, and product terms stay in English.website/scripts/sync-docs.mjsadditionally looks fordocs/fr/<source>and emitscontent/docs/<slug>.fr.md(Fumadocs locale-suffix convention), with English fallback when a French file is missing, so translation can land progressively without ever breaking the build.githubSourcepoints at thedocs/fr/file so "edit this page" opens the right source.defineI18n({ defaultLanguage: 'en', languages: ['en', 'fr'] }), routes moved underapp/[lang]/withgenerateStaticParams(compatible with the currentoutput: 'export'static deploy to Cloudflare Pages , no middleware needed),hideLocale: 'default-locale'so all existing English URLs stay unchanged, French UI translations + language switcher, and a per-locale static search index.Reviewable PR split
Open question: keeping the translation fresh
Translations rot when the English source moves. I'd propose stamping each
docs/fr/*.mdwith the source commit (or content hash) it was translated from, plus a small CI check (or report) that flags French pages whose English source has changed since. Happy to implement whatever mechanism you prefer or none, if you'd rather keep it lightweight.Questions for maintainers
/fr/docs/...) or thedocs/fr/layout?If you'd rather not take on translation maintenance, no hard feelings ; I can keep it on my fork instead.