Languages and RTL
Orbix ships in English, Spanish, Portuguese, French and Arabic. Arabic switches the whole layout to
right-to-left. Numbers, currencies and dates are formatted for the active language with the browser Intl API.

How it works
- Translations live in
src/locales/<locale>/<area>.json(common.json,nav.json,dashboards.json...). A key is the file name plus the path inside it:common.actions.save. - The dictionaries are loaded into vue-i18n (
src/core/i18n.ts): English is bundled, because the server renders every page in English; the active language is loaded on demand in the browser. Components read them with theuseI18n()composable, so the language menu re-renders the page instantly, without a reload:
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n';
const { t, fmt, lang } = useI18n();
</script>
<template>
<button type="button" class="fd-btn fd-btn--primary">
<span class="fd-btn__label" data-i18n="common.actions.save">{{ t('common.actions.save') }}</span>
</button>
<input class="fd-input" type="search" :placeholder="t('common.actions.search')" data-i18n-attr="placeholder:common.actions.search" />
<span>{{ fmt('currency', 48290.5) }}</span> <!-- $48,290.50 · 48.290,50 US$ · ٤٨٬٢٩٠٫٥٠ US$ -->
</template>langis a computed ref with the active language (en,es,pt,frorar). The vue-i18n instance is also installed in the Nuxt app (src/plugins/i18n.ts), andi18n.global.localeholds the same value.- The
data-i18nanddata-i18n-attrattributes are optional in your own components; the template keeps them so that markup created at runtime (data grids, page scripts, foundry-ui behaviors) is translated too. - The choice is saved in the browser (
fd:lang), and demo links accept?lang=es. Without a saved choice the template starts in English.<html lang>anddirfollow the language (kept in the Nuxt head withuseHead,src/composables/useDocumentHead.ts).
Server rendering and languages
URLs have no language prefix: each page is generated once, in English, and the browser applies the saved
language (or ?lang=) right after loading, under the preloader, before the page is shown. This keeps the static
site simple (one HTML file per page) and the server HTML always matches what the browser hydrates.
If you prefer one URL per language (/es/dashboards/crm) with every language rendered on the server, the
@nuxtjs/i18n module can do it with the same JSON files (strategy: 'prefix_except_default', the dictionaries
as lazy locale files); the static build then contains one copy of every page per language. Orbix does not need
it, so it is not included.
Placeholders and plurals
The dictionaries keep one format in every Orbix edition, compiled by src/core/i18n.ts for vue-i18n.
Placeholders use double braces: "greeting": "Welcome back, {{name}}" and
t('greeting', { name: user.name }).
Plurals use _one / _other keys (Arabic also _zero, _two, _few, _many, the plural categories of the
language) and a count:
{ "count_one": "{{count}} task", "count_other": "{{count}} tasks" }{{ t('tasks.count', { count: tasks.length }) }}Formats: fmt(type, value, options) with the types number, decimal, compact, currency,
currency-compact, percent, date, date-long, date-short, datetime, time, month, weekday,
relative and duration-min; options { digits, currency }.
Add a language
- Copy
src/locales/entosrc/locales/deand translate the values (keep the keys). - Add it to
LANGUAGESinsrc/core/i18n.ts:['en', 'es', 'pt', 'fr', 'ar', 'de']. - Add it to the language menus in
src/components/shell/Topbar.vueandsrc/components/auth/AuthControls.vue(copy one of the existing entries and changedata-fd-lang,lang, thearia-checkedbinding and the label). - Add the code to the language pattern of
src/boot/orbix-boot.js(/^(en|es|pt|fr|ar|de)$/). - Run
npm test– the translation tests check that every language has every key with the same placeholders.
For a right-to-left language (Hebrew, Persian, Urdu) nothing else is needed: the direction is derived from the language code.
Remove a language
Remove it from LANGUAGES, the two language menus and the boot pattern, then delete src/locales/<locale>/.
Translating your own texts
Never write visible text directly in a template: always use a key, so every language stays complete. The test
tests/hardcoded-text.test.ts renders every page and fails when a visible text or label is not translated (demo
content inside data-demo elements is allowed). Keep your keys in their own file per area (reports.json) to
find them easily.