Add a locale end to end
With a Comvi project wired through cdnLoader() as on Connect to Comvi,
and access to Languages and Settings on the platform, add a language and ship it to
users through the CDN. Your build changes only when the URL rules enumerate locales.
Add the language on the platform
Section titled “Add the language on the platform”Open Languages and click Add Language. Codes are canonical BCP-47, such as pt-BR
or zh-Hant-TW, and the code the platform stores is the code your app configures, uppercase
region included. Machine translation fills the column, translation memory fills what the
organization has already translated from the same source, and a reviewer moves rows from
Needs Review to Translated. See Languages and
Machine Translation.
Publish it
Section titled “Publish it”Open Settings → Content Deploy and check that the new language is ticked in the saved selection. The dashboard starts with every locale ticked, so a new one is included unless you narrowed the list before. The next auto-deploy publishes it, or Deploy Now pushes it at once.
curl https://cdn.comvi.io/<project-token>/pt-BR.jsonThe request returns the catalog once the deploy has landed. A 404 means the language is not in the selection or the deploy is still in flight. A partly translated language ships as it is: the CDN publishes exactly the locales you tick. See CDN Deployment.
Tell the app the locale exists
Section titled “Tell the app the locale exists”import { defineRouting } from '@comvi/next/routing';
export const routing = defineRouting({ locales: ['en', 'de', 'pt-BR'], defaultLocale: 'en', localePrefix: 'as-needed',});import { defineNuxtConfig } from 'nuxt/config';
export default defineNuxtConfig({ modules: ['@comvi/nuxt'], comvi: { defaultLocale: 'en', locales: [ { code: 'en', name: 'English', iso: 'en-US' }, { code: 'pt-BR', name: 'Português (Brasil)', iso: 'pt-BR' }, ], },});An i18n instance that fetches locale + '.json' for whatever locale is set needs nothing.
React, Vue, Svelte, Solid and vanilla apps add the code wherever their own switcher lists
options. An app that composes localeDetector() also adds the code to its supportedLocales:
without that option the detector truncates every detected and cached tag to its lowercased base
language, so a visitor who picked pt-BR comes back as pt, and pt.json does not exist. Next.js and Nuxt are different: both match the first
path segment against their locales list verbatim, so the new code goes into defineRouting
(and into createNextI18n, which spreads the same object) or into comvi.locales. Matching is
case-sensitive. With pt-BR in the list, /pt-br/… is a different route. On Nuxt the module
reads only iso and dir; name is yours, through
useRuntimeConfig().public.comvi.localeObjects.
What needs a redeploy
Section titled “What needs a redeploy”| Change | Ships via | Needs a redeploy |
|---|---|---|
| a translation’s wording | CDN | no |
| a new key | CDN | no |
| a new language already in the routing list | CDN | no |
| a new language that must appear in URLs | CDN, plus source | yes |
| the default locale, or the prefix strategy | source | yes |
A right-to-left language such as ar or he publishes its catalog but does not set dir on
your document. Read the direction from the i18n instance and apply it; on Nuxt the module writes
<html lang dir> itself. See Switch the locale.
How it works
Section titled “How it works”Content Deploy is a saved selection of locales plus a pipeline that writes one JSON object per locale and namespace to the CDN. Adding a language on Languages adds it to the project; it reaches the CDN only when it is in the selection and a deploy runs. A selection somebody narrowed earlier does not grow on its own: the new language stays unticked until a person ticks it, and the CDN keeps answering 404 for it however complete the translations are. An automatic deploy runs about 5 seconds after the last edit, and at most 1 minute into a continuous stream of edits; Deploy Now skips the wait.
On the app side, cdnLoader() never holds a list of locales. When the i18n instance is set to
pt-BR, the loader asks for {cdnUrl}/pt-BR.json for the default namespace and
{cdnUrl}/{namespace}/pt-BR.json for every other one, and whatever comes back is the catalog.
That is why a plain React or Vue app learns about a new language without a build: the only
place the code lists locales is the switcher, and that list is yours. The two frameworks with
locale-prefixed URLs are the exception, because their middleware decides from locales
whether /pt-BR/about is a locale route or a 404, and nothing at runtime can grow that list.
A deploy publishes the values that pass the Filter by Status setting at that moment. With
Translated ticked, a pt-BR key still in review is left out of the file and the i18n
instance walks fallbackLocale for it at render time, as it does for a key whose value is
empty; with the default empty filter every
status ships, drafts included. Finishing the translations later changes the file on the CDN,
and the app picks it up on its next load, still with no redeploy.
Read next
Section titled “Read next”- Switch the locale:
setLocale, persistence and direction. - CDN Deployment: the selection, the deploy pipeline and cache invalidation.
- Going from 2 to 20 languages: decisions that get harder to reverse.