Internationalization (i18n)
Overview
Section titled “Overview”ElyOS uses a database-backed i18n system. Translations are stored in the database (not static JSON files) and loaded at runtime. This allows translations to be edited through an admin interface without restarting.
Default languages: hu (Hungarian) and en (English).
Translation Structure
Section titled “Translation Structure”Translations are organized into namespaces. Each namespace corresponds to a functional area:
platform:common # Common texts (save, cancel, etc.)platform:auth # Authenticationplatform:settings # Settings applicationplatform:users # Users applicationplatform:chat # Chat application...Using the T Component
Section titled “Using the T Component”The simplest way to display translations is the T component:
<script lang="ts"> import T from '$lib/components/i18n/T.svelte';</script>
<!-- Simple translation --><T key="platform:common.save" />
<!-- With parameters --><T key="platform:common.welcome" params={{ name: 'User' }} />
<!-- Fallback text --><T key="platform:common.unknown_key" fallback="Unknown" />Using i18n Service in TypeScript
Section titled “Using i18n Service in TypeScript”import { getI18nService } from '$lib/i18n';
const i18n = getI18nService();
// Get translationconst text = i18n.t('platform:common.save');
// With parametersconst welcome = i18n.t('platform:common.welcome', { name: 'User' });
// Current localeconst locale = i18n.locale; // 'hu' | 'en'Switching Locale
Section titled “Switching Locale”import { setLocale } from '$lib/i18n/preference.client';
// Switch locale (saves to cookie, refreshes page)await setLocale('en');The LocaleSwitcher component handles this automatically:
<script lang="ts"> import LocaleSwitcher from '$lib/components/i18n/LocaleSwitcher.svelte';</script>
<LocaleSwitcher />Accessing Current Locale
Section titled “Accessing Current Locale”On the server, locals.locale contains the current language:
export const myAction = command(schema, async () => { const { locals } = getRequestEvent(); const locale = locals.locale; // 'hu' | 'en' // ...});On the client, from the i18n store:
<script lang="ts"> import { getI18nStore } from '$lib/i18n/store.svelte';
const i18nStore = getI18nStore(); const locale = $derived(i18nStore.locale);</script>Adding a New Translation to Core
Section titled “Adding a New Translation to Core”If you’re developing a new feature in the core system, new translations should be placed in seed files so they persist across database reinitialization.
1. Choose the Appropriate Seed File
Section titled “1. Choose the Appropriate Seed File”Translations are organized by functional area:
| Seed File | Purpose |
|---|---|
translations_common.sql | Common texts (buttons, statuses, error messages) |
translations_settings.sql | Settings application translations |
translations_user.sql | Users application translations |
translations_log.sql | Log application translations |
translations_desktop.sql | Desktop environment (Window, Taskbar, StartMenu) |
translations_auth.sql | Auth pages (login, registration) |
translations_notifications.sql | Notification system translations |
translations_plugin_manager.sql | Plugin Manager translations |
2. Add Translations to the Seed File
Section titled “2. Add Translations to the Seed File”Open the appropriate file in packages/database/src/seeds/sql/platform/:
-- translations_myapp.sql
-- =============================================================================-- MYAPP NAMESPACE - My Application Translations-- =============================================================================
-- Hungarian (hu) translationsINSERT INTO platform.translations (locale, namespace, key, value) VALUES('hu', 'myapp', 'title', 'Az én alkalmazásom'),('hu', 'myapp', 'description', 'Ez az alkalmazás leírása'),('hu', 'myapp', 'buttons.create', 'Új létrehozása'),('hu', 'myapp', 'list.empty', 'Nincs megjeleníthető elem')ON CONFLICT (locale, namespace, key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();
-- English (en) translationsINSERT INTO platform.translations (locale, namespace, key, value) VALUES('en', 'myapp', 'title', 'My Application'),('en', 'myapp', 'description', 'This is the application description'),('en', 'myapp', 'buttons.create', 'Create New'),('en', 'myapp', 'list.empty', 'No items to display')ON CONFLICT (locale, namespace, key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();3. Register the Seed (if New File)
Section titled “3. Register the Seed (if New File)”If you created a new seed file, register it in packages/database/src/seeds/config.ts:
export const seedConfig: Record<string, SeedDefinition> = { // ... existing seeds
translations_myapp: { file: 'platform/translations_myapp.sql', dependsOn: ['locales'], description: 'My App translations' }};4. Run the Seed
Section titled “4. Run the Seed”# Updates only new translations (idempotent)bun db:seed
# Or just your seedbun db:seed --no-truncate --only=translations_myapp5. Use the Translations
Section titled “5. Use the Translations”<script lang="ts"> import T from '$lib/components/i18n/T.svelte';</script>
<h1><T key="myapp.title" /></h1><p><T key="myapp.description" /></p>
<button> <T key="myapp.buttons.create" /></button>Translation Key Conventions
Section titled “Translation Key Conventions”- Namespace:
platform:[app-name]orplatform:common - Key:
snake_caseorcamelCase, dot-separated hierarchy - Examples:
platform:common.save→ “Save”platform:common.cancel→ “Cancel”platform:settings.appearance.title→ “Appearance”platform:users.list.empty→ “No users”
I18nProvider
Section titled “I18nProvider”The I18nProvider component initializes the i18n context in the layout. Usually included in the root layout — no need to add manually to applications.
Environment Variables
Section titled “Environment Variables”| Variable | Default | Description |
|---|---|---|
SUPPORTED_LOCALES | hu,en | Comma-separated supported languages |
DEFAULT_LOCALE | hu | Default language |