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:

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:

  1. Create a new JSON file in src/renderer/i18n/locales/ using the BCP-47 identifier (e.g., ko-KR.json for Korean).

  2. Copy the keys from an existing locale file and translate the values.

  3. Import the new JSON in src/renderer/i18n/index.ts and add it to the resources map:

import koKR from './locales/ko-KR.json';

// Inside init configuration
resources: {
  'ko-KR': { translation: koKR },
  // existing locales...
}
  1. 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 like en-US.json, zh-CN.json, and ja-JP.json.
  • The i18next-browser-languagedetector plugin automatically detects the user's language, falling back to en-US when 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →