i18n & Hooks
Internationalization and 43+ custom hooks.
Supported Languages
| Code | Language | Native Name |
|---|
en | English (default) | English |
zh-TW | Chinese Traditional | 中文 |
ja | Japanese | 日本語 |
ko | Korean | 한국어 |
fr | French | Français |
de | German | Deutsch |
es | Spanish | Español |
pt | Portuguese | Português |
it | Italian | Italiano |
ru | Russian | Русский |
i18n Configuration
The i18n system is configured in src/lib/i18n.ts and src/lib/languageConfig.ts:
- Library: i18next with react-i18next bindings
- Detection: Custom locale resolution via
resolveInitialLanguage() (uses navigator.languages with fuzzy locale matching) - Storage: Language preference saved to localStorage (
ryos:language, ryos:language-initialized) with legacy key migration from ryos_language - Fallback: English (
en) as default fallback language - Runtime switching:
applyLanguage() ensures resources are loaded before i18n.changeLanguage()
Locale Bundle Loading
- Eager default locale: English (
en) translation bundle is imported at startup
- Lazy non-default locales: Other locale JSON files are dynamically imported on demand (
localeLoaders) - Deduplicated loading: Concurrent requests for the same locale share a single promise (
loadingLanguages) - Bootstrap flow:
initializeI18n() initializes i18n, resolves initial language, lazy-loads if needed, then applies language
Translation File Structure
Translations are stored in src/lib/locales/{lang}/translation.json:
src/lib/locales/
├── en/translation.json
├── zh-TW/translation.json
├── ja/translation.json
├── ko/translation.json
├── fr/translation.json
├── de/translation.json
├── es/translation.json
├── pt/translation.json
├── it/translation.json
└── ru/translation.json
Translation Key Patterns
| Pattern | Description | Example |
|---|
common. | Shared UI elements (menus, dialogs, buttons) | common.menu.file |
apps.{appId}. | App-specific translations | apps.finder.name |
apps.{appId}.menu. | App menu items | apps.ipod.menu.addSong |
apps.{appId}.help. | App help content | apps.chats.help.chatWithRyo |
apps.{appId}.dialogs. | App dialog text | apps.videos.dialogs.clearPlaylistTitle |
apps.{appId}.widgets. | Widget translations (Dashboard) | apps.dashboard.widgets.clock |
apps.calendar. | Calendar views, events, sidebar | apps.calendar.views.month |
apps.contacts. | Address book, groups, fields | apps.contacts.groups.all |
apps.dashboard. | Dashboard widgets, dictionary, stocks | apps.dashboard.stocks.loading |
settings. | Settings panel translations | settings.language.title |
components. | Shared component translations | components.linkPreview.openIpod |
spotlight. | Spotlight Search UI and sections | spotlight.placeholder, spotlight.sections.apps |
Key Hooks
Window & App Management:
| Hook | Purpose |
|---|
useLaunchApp | Launch apps with multi-window support |
useWindowManager | Drag, resize, snap-to-edge |
useWindowInsets | Theme-dependent constraints |
Audio System:
| Hook | Purpose |
|---|
useSound | Web Audio API playback |
useChatSynth | Chat typing sounds |
useTerminalSounds | Terminal feedback |
useTtsQueue | Text-to-speech queue |
useAudioRecorder | Audio recording |
Device Detection:
| Hook | Purpose |
|---|
useIsMobile | Mobile detection (<768px) |
useIsPhone | Phone detection (<640px) |
useMediaQuery | CSS media query hook |
Using i18n
import { useTranslation } from "react-i18next";
const { t } = useTranslation();
// Simple key lookup
t("common.menu.file") // "File"
t("apps.finder.name") // "Finder"
// With interpolation
t("common.dialog.aboutApp", { appName: "Finder" }) // "About Finder"
t("apps.ipod.dialogs.addedSongsToTop", { count: 5, plural: "s" })
// Pluralization
t("apps.admin.statusBar.usersCount", { count: 1 }) // "1 user"
t("apps.admin.statusBar.usersCount_plural", { count: 5 }) // "5 users"
Helper Functions (src/utils/i18n.ts)
| Function | Purpose |
|---|
getTranslatedAppName(appId) | Get localized app name (theme-aware) |
getTranslatedAppDescription(appId) | Get localized app description |
getTranslatedFolderName(path) | Get localized folder name from path |
getTranslatedHelpItems(appId) | Get localized help items for an app |