Core Feature: Multilingual Support
Relevant source files
The following files were used as context for generating this wiki page:The application provides full multilingual support for its user interface, with English and Chinese (中文) being the currently implemented languages. This system is designed to be straightforward, relying on a centralized translation file and React's state management to dynamically render UI text in the selected language. The user's language preference is persisted across sessions using the browser's localStorage.
The core of the internationalization (i18n) system is built around a simple key-value structure, making it easy to add new languages or modify existing strings. The language is initialized based on the user's saved preference or browser settings, and can be changed at any time through the application's settings menu.
Sources: README.md:14, App.tsx:43-49, translations.ts:3-5
Architecture
The multilingual support feature is implemented through the interaction of three main parts: a central translation definition file, the main application component for state management, and a settings modal for user interaction.
translations.ts: This file is the single source of truth for all localizable strings. It exports thetranslationsobject, which contains the text for all supported languages.App.tsx: The root component that initializes and manages the current language state (lang). It detects the user's preferred language, loads the corresponding strings, and passes them down to child components.SettingsModal.tsx: A UI component that allows the user to select their preferred language. It communicates the user's choice back to theAppcomponent to update the application's state.localStorage: The browser's local storage is used to persist the user's language choice, ensuring it is remembered between visits.
The following diagram illustrates the relationship between these components.
Translation Data Structure
All UI text is defined in a single file, translations.ts. This file exports a Language type and a translations object.
Language Type
The Language type explicitly defines the supported language codes.
export type Language = 'en' | 'zh';
Sources: translations.ts:3
Translations Object
The translations object is a nested structure. The top-level keys are the language codes defined in the Language type. Each language key maps to an object containing key-value pairs, where the key is a semantic identifier for a string (e.g., appTitle) and the value is the translated text.
export const translations = {
en: {
appTitle: "AI Image Gen",
prompt: "Prompt",
generate: "Free Generate",
// ... more keys
},
zh: {
appTitle: "AI 绘图",
prompt: "提示词",
generate: "免费生成图片",
// ... more keys
}
};
Sources: translations.ts:5-92
Example Translation Keys
| Key | English Value | Chinese Value |
|---|---|---|
appTitle | AI Image Gen | AI 绘图 |
prompt | Prompt | 提示词 |
generate | Free Generate | 免费生成图片 |
settings | Settings | 设置 |
language | Language | 语言 |
ar_square | Default 1:1 | 默认 1:1 |
Sources: translations.ts:7, 8, 18, 28, 35, 39, translations.ts:47, 48, 58, 68, 75, 79
State Management and Initialization
The application's language state is managed within the main App.tsx component.
Initialization Flow
On application load, the lang state is initialized by a function that determines the best language to use based on a clear priority order:
- It first checks
localStoragefor a previously saved language preference under the keyapp_language. - If no preference is found, it falls back to the user's browser language settings via
navigator.language. It checks if the browser language starts withzh. - If neither of the above conditions is met, it defaults to
'en'.
This logic ensures a consistent experience for returning users while providing a sensible default for new users.
The initialization flow is visualized below:
Sources: App.tsx:43-49
State Persistence
To persist the language choice, a useEffect hook in App.tsx listens for changes to the lang state. Whenever the lang state is updated (e.g., by the user in the settings modal), this hook writes the new language code to localStorage.
// in App.tsx
useEffect(() => {
localStorage.setItem('app_language', lang);
}, [lang]);
Sources: App.tsx:126-128
Language Switching
Users can change the application language via the SettingsModal component.
UI and Interaction
The SettingsModal component is opened from the main app header. Inside the modal, it displays buttons for each supported language ("English" and "中文").
The App component passes its lang state and the setLang state updater function as props to SettingsModal. When a user clicks a language button, the corresponding onClick handler calls setLang with the new language code ('en' or 'zh').
// in components/SettingsModal.tsx
<button
onClick={() => setLang('en')}
// ...
>
English
</button>
<button
onClick={() => setLang('zh')}
// ...
>
中文
</button>
Sources: components/SettingsModal.tsx:47-55, components/SettingsModal.tsx:56-64
Language Change Sequence
The following diagram shows the sequence of events when a user changes the language.
Consuming Translations
Once the lang state is set in App.tsx, the corresponding translation object is selected and used throughout the component tree.
A t constant is created to hold the translations for the currently active language:
// in App.tsx
const t = translations[lang];
Sources: App.tsx:51
This t object is then used to access strings in the JSX. For example:
// in App.tsx
<h1 className="text-white text-xl font-bold ...">{t.appTitle}</h1>
<p className="text-white text-lg font-medium ...">{t.prompt}</p>
<button
onClick={handleGenerate}
// ...
>
{isLoading ? (
// ...
) : (
<span className="truncate">{t.generate}</span>
)}
</button>
Sources: App.tsx:458, App.tsx:483, App.tsx:598
Translations are also used to dynamically generate data for other components. For instance, the labels for the aspectRatioOptions array are populated from the t object, ensuring that dropdown menus are also translated.
// in App.tsx
const aspectRatioOptions = [
{ value: '1:1', label: t.ar_square },
{ value: '9:16', label: t.ar_photo_9_16 },
// ...
];
Sources: App.tsx:54-64