Skip to content
Orbix Nuxt · Tailwind CSS v1.0.3

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.

Language menu

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 the useI18n() 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>
  • lang is a computed ref with the active language (en, es, pt, fr or ar). The vue-i18n instance is also installed in the Nuxt app (src/plugins/i18n.ts), and i18n.global.locale holds the same value.
  • The data-i18n and data-i18n-attr attributes 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> and dir follow the language (kept in the Nuxt head with useHead, 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

  1. Copy src/locales/en to src/locales/de and translate the values (keep the keys).
  2. Add it to LANGUAGES in src/core/i18n.ts: ['en', 'es', 'pt', 'fr', 'ar', 'de'].
  3. Add it to the language menus in src/components/shell/Topbar.vue and src/components/auth/AuthControls.vue (copy one of the existing entries and change data-fd-lang, lang, the aria-checked binding and the label).
  4. Add the code to the language pattern of src/boot/orbix-boot.js (/^(en|es|pt|fr|ar|de)$/).
  5. 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.