Skip to content
Add a locale

Add a locale

Add one ICU catalogue, register it in your edition, then test its formatting and direction. The four framework editions ship en, es, pt-BR, and ar; the plain HTML edition ships English text and a direction control, not a language switcher. Email templates use a separate catalogue.

Add the catalogue

In a full repository, create a JSON file named for the new locale code inside shared/locales/, using shared/locales/en.json as the key list. Keep the keys flat (for example, enum.orderStatus.packing is one key), and keep ICU placeholders and plural/select arguments compatible with the English message.

For a standalone edition, create the file under its own mirror: react/src/shared/locales/, nextjs/src/shared/locales/, vue/src/shared/locales/, or nuxt/app/shared/locales/. These are repo-relative descriptions of the delivered folders; there is no root sync tool in a standalone copy. A standalone starter has a reduced catalogue: for example, use starters/react/src/shared/locales/en.json as the key list for the React starter rather than the full-edition catalogue. See generated folders for the other starter mirror paths.

Register it in React

Add the locale code and its display name to react/src/app/preferences.ts. Import its catalogue and add it to resources in react/src/app/i18n.ts and CATALOGUES in react/src/app/format.ts, so interface messages and numbers/dates use the same locale. In a standalone React folder, edit the same files inside your folder (the react/ prefix in these paths is the full-repository location) and its own mirrored catalogue.

Register it in Vue

Add the code and display name to vue/src/app/preferences.ts, and its catalogue to messages in vue/src/app/i18n.ts and CATALOGUES in vue/src/app/format.ts. In a standalone Vue folder, edit the same files inside your folder and its own vue/src/shared/locales/ mirror. Vue's vue-i18n uses the shared ICU compiler; do not rewrite the catalogue in Vue's different message syntax.

Register it in Next.js

Add the code to nextjs/src/i18n/routing.ts and its catalogue import to nextjs/src/i18n/request.ts. Register the formatter's catalogue in nextjs/src/server/format.ts as well. In a standalone Next.js folder, edit the same files inside your folder and its own nextjs/src/shared/locales/ mirror. The locale is a URL segment, so test a page at the new prefixed path as well as the language switcher.

Register it in Nuxt

Add the code, language, name, and direction to the locale list in nuxt/nuxt.config.ts; import the catalogue and add it to messages in nuxt/i18n/i18n.config.ts. Also register the catalogue for numbers and dates in nuxt/app/composables/useFormat.ts. For a new RTL language, update the natural-direction choice in nuxt/app/stores/preferences.ts, which currently checks Arabic explicitly. In a standalone Nuxt folder, edit the same files inside your folder and its own nuxt/app/shared/locales/ mirror. Its locale is a URL prefix: test a direct visit and reload, not only a client-side switch.

Dates and times are written in UTC

Every date and time the formatter writes is in UTC, whatever the locale: calendar days, the calendar's clock, and timestamps such as when an order was placed. The locale decides how a date is spelled, never which zone it is in. Next.js and Nuxt render a page on the server and hydrate it in the browser, and the two are rarely in the same zone; a timestamp written in each one's own zone reads differently twice and hydration fails. To show a reader their local time, render that value in the browser only.

Check direction and coverage

shared/ui/preferences.mjs uses RTL_LOCALES (ar, fa, he, ur) through directionFor in React, Vue, and Next.js. If the new language is RTL and not represented there, update that list in the full repository or in the corresponding standalone mirror; for Nuxt update its natural-direction choice as described above. The direction control remains available for a manual override. For HTML, html/assets/js/i18n.js consumes the English catalogue and html/assets/js/preferences.js provides direction; adding JSON alone will not add a language switcher. See RTL for layout and mixed-script checks.

The UI catalogue does not translate product data. If you also add translated product names or descriptions, supply those values in your data and review the editor fields in react/src/pages/ProductEdit.tsx, vue/src/pages/ProductEdit.vue, nextjs/src/products/form.tsx, or nuxt/app/pages/products/[id].vue: their field direction currently special-cases Arabic. This applies equally to a standalone edition, using its copy of that file.

In the full repository, validate catalogue keys and ICU messages before syncing. A standalone folder does not include these root tools/ checks; validate its catalogue and exercise its locale route or switcher within that edition.

Full repository only
node tools/i18n-check/check.mjs
node tools/sync-shared.mjs

Email messages are separate from the app catalogues: consult tools/emails/locales/ and the email guide when translating an email.