Internationalization (i18n)
Relevant source files
The following files were used as context for generating this wiki page:The Internationalization (i18n) system in Charlotte provides multi-language support for the user interface. It is designed around a key-value system where each supported language has a corresponding translation file. The entire system is driven by a central configuration that sets the site's language, ensuring that all UI text is displayed in the selected locale.
The architecture is straightforward, relying on a TypeScript enum for type-safe translation keys, individual language "packs" as objects, and a core translation function that resolves keys to strings for the currently configured language. This approach makes it easy to add new languages or modify existing translations without altering application logic.
Architecture
The i18n system is composed of several key files that work together to deliver translated content. The default language for the site is determined by the lang property in src/config.ts.
The following diagram illustrates the high-level architecture of the i18n system.
This diagram shows how the main i18n() function uses the site configuration to select a language pack and retrieves a translation string based on a provided key.
Sources: src/i18n/translation.ts, src/config.ts:10, src/i18n/i18nKey.ts, src/utils/content-utils.ts:150
Core Components
| Component | File Path | Description |
|---|---|---|
| Translation Keys | src/i18n/i18nKey.ts | An enum that defines all available keys for translation strings. This ensures type safety when requesting a translation. |
| Translation Logic | src/i18n/translation.ts | Contains the main i18n function, which retrieves the appropriate string from language packs based on the site's configuration. |
| Language Packs | src/i18n/languages/*.ts | A set of files, each exporting a Translation object for a specific language (e.g., en, zh_CN). |
| Site Configuration | src/config.ts | The main configuration file where the site's default language is set via the lang property. |
| Type Definitions | src/types/config.ts | Defines the SiteConfig type, including the allowed values for the lang property. |
Translation Keys (I18nKey)
All user-facing strings that require translation are identified by a key defined in the I18nKey enum. This prevents typos and ensures that all calls to the translation function use a valid key.
Sources: src/i18n/i18nKey.ts
// src/i18n/i18nKey.ts:1-5
enum I18nKey {
home = "home",
about = "about",
archive = "archive",
search = "search",
// ... more keys
Sources: src/i18n/i18nKey.ts:1-5
Some examples of keys include:
| Key | Example Usage |
|---|---|
home | The "Home" navigation link. |
recentPosts | The title for the recent posts section. |
uncategorized | The default category name for posts without one. |
themeColor | The label for the theme color selector. |
wordCount | The unit for word count (singular, e.g., "word"). |
wordsCount | The unit for word count (plural, e.g., "words"). |
pinned | The label for a pinned post. |
Sources: src/i18n/i18nKey.ts:2-52
Language Packs
Translations for each language are stored in separate files within the src/i18n/languages/ directory. Each file exports a Translation object that maps keys from I18nKey to their string values in that language.
Sources: src/i18n/languages/en.ts, src/i18n/languages/zh_CN.ts, src/i18n/languages/ja.ts, src/i18n/languages/zh_TW.ts
Supported Languages
The application currently supports the following languages:
| Language Code | File |
|---|---|
en | src/i18n/languages/en.ts |
zh_CN | src/i18n/languages/zh_CN.ts |
zh_TW | src/i18n/languages/zh_TW.ts |
ja | src/i18n/languages/ja.ts |
Sources: src/types/config.ts:7, src/i18n/translation.ts:5-8
Example Language File (en.ts)
This snippet shows the structure of a language pack, mapping I18nKey members to English strings.
// src/i18n/languages/en.ts:4-12
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const en: Translation = {
[Key.home]: "Home",
[Key.about]: "About",
[Key.archive]: "Archive",
[Key.search]: "Search",
[Key.tags]: "Tags",
[Key.categories]: "Categories",
[Key.recentPosts]: "Recent Posts",
// ... more translations
Sources: src/i18n/languages/en.ts:4-12
Core Translation Logic
The central piece of the i18n system is the i18n function located in src/i18n/translation.ts. This function is responsible for selecting the correct language pack and resolving a translation key.
i18n() Function Flow
The function performs the following steps to retrieve a translation:
- It reads the
langproperty from the globalsiteConfig. - It selects the corresponding language pack object (e.g.,
en,zh_CN). - It looks up the value associated with the provided
I18nKey. - For keys related to counts (e.g.,
wordCount,postCount), it handles pluralization by checking an optionalcountparameter. - It returns the final translated string.
This diagram shows the logical flow within the i18n function, including how it handles pluralization for count-based keys.
Sources: src/i18n/translation.ts:17-45
Pluralization
The system has a simple pluralization mechanism. For certain base keys like wordCount, minuteCount, and postCount, if a count argument is passed to the i18n function and its value is not 1, the function automatically attempts to use the plural version of the key (e.g., wordsCount).
// src/i18n/translation.ts:28-36
const plural =
count !== undefined &&
count > 1 &&
(key === Key.wordCount ||
key === Key.minuteCount ||
key === Key.postCount);
if (plural) {
key = `${key}s` as I18nKey;
}
Sources: src/i18n/translation.ts:28-36
Configuration
The site's language is configured in src/config.ts within the siteConfig object. The lang property must be one of the values defined in the SiteConfig type.
// src/config.ts:9-10
export const siteConfig: SiteConfig = {
// ...
lang: "zh_CN", // 语言代码,例如 'en', 'zh_CN', 'ja' 等
// ...
};
Sources: src/config.ts:9-10
The SiteConfig type definition ensures that only supported language codes can be used.
// src/types/config.ts:6-7
export type SiteConfig = {
// ...
lang: "en" | "zh_CN" | "zh_TW" | "ja";
// ...
};
Sources: src/types/config.ts:6-7
Usage Example
The i18n system is used throughout the application to render text. A clear example is in getCategoryList, where posts without a category are assigned the "Uncategorized" label by fetching the appropriate translation.
// src/utils/content-utils.ts:149-152
if (!post.data.category) {
const ucKey = i18n(I18nKey.uncategorized);
count[ucKey] = count[ucKey] ? count[ucKey] + 1 : 1;
return;
}
This code demonstrates how the i18n function is called with a key to get a localized string, which is then used as a map key for counting posts in the "Uncategorized" category.
Sources: src/utils/content-utils.ts:149-152