Languages
Every project has one source language, the one your developers write in, and any number of target languages you translate into. Translators see the source value next to the target field.
Add a language
Section titled “Add a language”-
Open the project and go to Languages in the sidebar.
-
Click Add Language. The dialog opens on a shortlist of popular languages; the search box covers the whole catalog of 619 locales.
-
Search by English name, native name or code (“French”, “Français” or “fr”) and select the language.
-
Confirm. The language appears in the list immediately.
Add languages at any time; no plan limits how many a project has. Existing translations are untouched; every key shows an empty value for the new language, unless the language was removed earlier, in which case its old values come back.
The source language is chosen at project creation and cannot be changed afterwards. Settings → General shows it with a lock icon and “Cannot be changed after creation”.
Locale codes
Section titled “Locale codes”| Code | Language |
|---|---|
en |
English |
en-US |
English (United States) |
pt-BR |
Portuguese (Brazil) |
zh-Hans |
Chinese (Simplified) |
zh-Hant-TW |
Chinese (Traditional, Taiwan) |
sr-Latn |
Serbian (Latin script) |
Codes are canonical BCP-47: subtags separated by a hyphen, the language lowercase, a script subtag Titlecase, a region subtag UPPERCASE. The same code appears in the dashboard, the API, the CLI, import/export and CDN URLs.
Which spelling your app needs
Section titled “Which spelling your app needs”The one Comvi stores. Every code in the built-in catalog is canonical, and a custom code is
canonicalized on the way in, so a project holds pt-BR however you spelled it when adding
it. Legacy spellings are accepted as input everywhere: the dashboard, the REST API, the
CLI and import/export resolve pt_BR, pt-br and PT-BR onto the stored pt-BR, and all
of them return the canonical form. Old CDN file names keep working for a deprecation window.
A canonical code is valid BCP-47 by construction. The Comvi i18n library’s plurals and
formatters go through Intl, which throws on an underscored code, so use the project’s
codes verbatim in app config and URLs.
Add a locale end to end walks the path from adding the
language to reading it in an app.
Custom locales
Section titled “Custom locales”Choose Create custom language… at the bottom of the Add Language dialog when no
built-in code fits: an internal pseudo-locale, a formality variant, a non-standard regional
split. Give it a code, a name, a native name and a flag emoji. The dialog suggests codes in
the shape de-formal or en-simple.
A custom code is canonicalized like any other, including uppercasing a region subtag:
en_uk_legal is stored as en-UK-legal. Separator and case do not make a code distinct,
so pt_br and PT-BR both resolve to the built-in pt-BR and are rejected as duplicates.
A custom code cannot shadow a built-in one: creating fr as a custom locale returns
LOCALE_ALREADY_EXISTS. Custom locales are scoped to their project, so two projects can
each define their own de-formal.
Progress
Section titled “Progress”The Languages page shows a three-part bar per language, and the table sorts by name or by progress:
| Segment | Meaning |
|---|---|
| Translated | Values that have been reviewed and approved |
| Needs Review | Values that exist but have not been approved |
| Not Translated | Keys with no value for this language |
Each language row also carries the locale code, the English display name, the native name,
a flag derived from the code (or the emoji you gave a custom locale), and an optional
AI translation context sent to LLM machine-translation providers on top of the
project-level context. Plural rules come from the locale: English has one and other,
Arabic has six forms. ICU MessageFormat applies them at runtime in the consuming app.
Right-to-left languages
Section titled “Right-to-left languages”The editor flips text direction for the language subtags ar, he, fa, ur, yi, ps
and sd. Direction is decided by the language subtag, so regional codes such as ar-EG
and he-IL are laid out right-to-left too. On the SDK side every i18n instance exposes a
reactive dir getter that returns 'rtl' or 'ltr' for the active locale; bind it to
your <html> or root layout element. See
Text direction.
Remove a language
Section titled “Remove a language”Open the actions menu on the language row and choose Remove Language. The dialog tells you how many translations are affected. Removal archives rather than erases: the values are kept, and adding the same language back restores them. The source language has no Remove action.