Languages and locales
What this is
How ComStack handles languages and locales. Pages are authored in one locale and auto-translated at publish time. URL routing, RTL support, and locale-specific features are driven by BCP-47 locale codes.
How it works
Language support
The platform supports 102 unique languages (112 locale entries including regional variants like en-GB, es-MX, zh-CN).
| Capability | Count |
|---|---|
| Total locale entries | 112 |
| Unique base languages | 102 |
| Voice support | 97 languages (107 entries) |
| RTL script support | 10 |
Default locale vs additional locales
Every project has one default locale (e.g. en). Pages are authored in the default locale and automatically translated into every additional locale at publish time.
- Default locale → root URL:
https://example.com/guides/intro - Additional locale → prefixed URL:
https://example.com/es/guias/intro
You author once; the publishing pipeline handles translation fan-out. See Translations concept.
URL routing
Locales use short codes as URL prefixes:
| Locale | URL prefix |
|---|---|
Default (e.g. en) | None — root path |
Spanish (es or es-MX) | /es/ |
Norwegian Bokmål (nb) | /nb/ |
Chinese Simplified (zh-CN) | /zh/ |
British English (en-GB) | Uses default root (if en is default) |
Locale codes are normalized to their short form for URLs (zh-CN → zh, es-MX → es).
Two variants of the same base language cannot coexist in one project. es-ES and es-MX both map to /es/ — this creates a URL collision. Project settings enforce this by rejecting a locale add that would collide with an existing short code.
BCP-47 field naming
The language field stored on each page (e.g. es-MX) is the full BCP-47 tag. It drives:
- The HTML
langattribute - RTL layout direction
- The translation prompt locale
- Voice agent language selection
The URL prefix uses only the short code. They’re independent: changing a project’s locale from es to es-MX improves translation quality without changing URLs.
Adding a locale
Add an additional locale via the project’s module settings (PUT /api/projects/:id/modules/knowledge_base). When a locale is added, the server runs an automatic translation fan-out that creates draft variants of every live source-locale page in the new language. These drafts are not live until the next publish.
Preview the fan-out without writing: POST .../modules/knowledge_base/locales/preview.
RTL languages
These 10 languages use right-to-left script — the platform applies RTL layout automatically:
ar (Arabic), dv (Divehi), fa (Persian), he (Hebrew), ku (Kurdish), ps (Pashto), sd (Sindhi), ug (Uyghur), ur (Urdu), yi (Yiddish)
When to use it
- Set the default locale at project creation — it determines the root URL path and the source language for all translations
- Add additional locales when you need translated versions of your content
- Use the full BCP-47 tag when setting
languageon a page via the API — it controls translation quality and regional voice behavior - Use the short code when constructing or referencing URLs
Common errors
| Error | Cause | Fix |
|---|---|---|
400 violations: locale would create URL collision | Adding es-MX when es-ES already exists (both resolve to /es/) | Remove the conflicting locale before adding the new one |
| Translated page shows source-locale content | Translation drafts haven’t been published yet | The fan-out creates drafts; publish to deploy them |
| RTL layout not applied | Locale code missing from the RTL registry | Confirm the BCP-47 code is in the RTL list above |
| Wrong locale prefix in URL | Page’s language field doesn’t match a configured project locale | Ensure the page language is one of project.locales |
Related
- Translations concept — how translations are generated at publish time
- AI discovery — hreflang and multilingual indexing
- Solution: International buyers can’t use my website