How AionUI's Translation System Supports Multi-Language Localization (en-US, zh-CN, ja-JP)
AionUI uses the i18next ecosystem to share JSON translation bundles between the React renderer and Electron main process, enabling runtime language detection and instant switching for locales including en-US, zh-CN, and ja-JP.
The iOfficeAI/AionUi repository implements a robust internationalization (i18n) architecture that keeps all UI strings in centralized JSON files. This design allows the application to support multiple languages without code duplication, using the same translation keys across both frontend components and backend error dialogs.
Locale Bundle Architecture
AionUI stores all translatable content as static JSON resources, creating a single source of truth for text content.
JSON File Organization
Translation files live in src/renderer/i18n/locales/ and follow the BCP-47 naming convention. Each file exports a flat or nested object where keys represent translation identifiers and values contain the localized text.
The repository includes dedicated bundles for:
en-US.json– English (United States)zh-CN.json– Simplified Chineseja-JP.json– Japanese
Key-Based Design
All UI elements, error messages, and configuration labels use stable dot-notation keys (e.g., settings.platformCustom, codex.network.timeout_title). This structure decouples the code from specific languages, allowing new locales to be added by simply creating a JSON file with identical keys.
Renderer Process Implementation
The React frontend initializes i18next in src/renderer/i18n/index.ts, creating a shared instance that supports automatic language detection and React integration.
i18next Initialization
The configuration imports locale JSON files directly and registers them as translation resources:
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
import enUS from './locales/en-US.json';
import zhCN from './locales/zh-CN.json';
import jaJP from './locales/ja-JP.json';
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
'en-US': { translation: enUS },
'zh-CN': { translation: zhCN },
'ja-JP': { translation: jaJP },
},
fallbackLng: 'en-US',
debug: false,
interpolation: { escapeValue: false },
});
This file is imported early in src/renderer/index.ts via import './i18n';, ensuring the translation system is ready before any components render.
Language Detection and Switching
The i18next-browser-languagedetector plugin automatically inspects navigator.language, localStorage, and query parameters to determine the initial locale. If detection fails or the locale is unsupported, the system falls back to en-US.
Programmatic switching is handled via the changeLanguage method:
i18n.changeLanguage('zh-CN');
This updates the active locale instantly and triggers re-renders in all React components using the useTranslation hook.
Main Process Integration
The Electron main process requires the same translations for native dialogs and background logic. AionUI mirrors the renderer setup in src/process/i18n/index.ts, importing the identical JSON bundles from the renderer directory and exposing a separate i18next instance.
Backend modules like CodexAgentManager.ts consume this instance directly:
import i18n from '@process/i18n';
function showNetworkError() {
const title = i18n.t('codex.network.timeout_title');
const message = i18n.t('codex.network.recovery_suggestions');
dialog.showErrorBox(title, message);
}
This architecture ensures consistent messaging across the UI and system-level error handlers without duplicating translation files.
Consuming Translations in Components
AionUI provides ergonomic access to translations in both React and non-React contexts.
React Hooks
Components use the useTranslation hook from react-i18next to access the t function and i18n instance:
import { useTranslation } from 'react-i18next';
export default function SettingsPanel() {
const { t, i18n } = useTranslation();
return (
<div>
<h1>{t('settings.title')}</h1>
<p>Current locale: {i18n.language}</p>
</div>
);
}
Dynamic UI Elements
Platform configurations in src/renderer/config/modelPlatforms.ts support an optional i18nKey field, allowing dynamic labels to be translated without hard-coding text:
{
id: 'openai',
name: 'OpenAI',
i18nKey: 'platform.openai.name',
// ...
}
Components render these by passing the key to the t function, ensuring dropdowns and tooltips remain localizable.
Adding New Languages
Extending AionUI to support additional languages requires minimal code changes:
-
Create a new JSON file in
src/renderer/i18n/locales/using the BCP-47 identifier (e.g.,ko-KR.jsonfor Korean). -
Copy the keys from an existing locale file and translate the values.
-
Import the new JSON in
src/renderer/i18n/index.tsand add it to theresourcesmap:
import koKR from './locales/ko-KR.json';
// Inside init configuration
resources: {
'ko-KR': { translation: koKR },
// existing locales...
}
- Update any language selector UI to include the new option.
The same JSON file can be imported by src/process/i18n/index.ts to ensure the main process recognizes the new locale immediately.
Summary
- AionUI uses i18next with react-i18next to manage translations across the React renderer and Electron main process.
- Locale data resides in
src/renderer/i18n/locales/as JSON files named with BCP-47 identifiers likeen-US.json,zh-CN.json, andja-JP.json. - The
i18next-browser-languagedetectorplugin automatically detects the user's language, falling back toen-USwhen necessary. - Both renderer and main processes share the same translation keys, ensuring consistent messaging in UI components and native dialogs.
- Adding a new language requires only creating a JSON file and registering it in
src/renderer/i18n/index.ts.
Frequently Asked Questions
What i18n library does AionUI use?
AionUI uses i18next together with react-i18next for the React renderer and i18next-browser-languagedetector for automatic language detection. The Electron main process uses a separate i18next instance initialized in src/process/i18n/index.ts that imports the same JSON locale files.
How does AionUI detect the user's language?
The system relies on the i18next-browser-languagedetector plugin, which checks the browser's navigator.language, localStorage preferences, and URL query parameters. If detection fails or returns an unsupported locale, AionUI falls back to en-US as defined in the fallbackLng configuration option in src/renderer/i18n/index.ts.
Can I add a custom locale without modifying core files?
While you must edit src/renderer/i18n/index.ts to import the new JSON file and add it to the resources map, the process is non-breaking and follows a simple pattern. Create your locale file in src/renderer/i18n/locales/, import it, and register it under the appropriate BCP-47 key. The main process will automatically support the new locale if it imports the same file.
Does the main process share the same translation files as the renderer?
Yes. The main process configuration in src/process/i18n/index.ts imports the JSON files directly from the renderer's src/renderer/i18n/locales/ directory. This ensures that error dialogs and background logic use the exact same keys and translations as the UI, maintaining consistency across the entire application.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →