如何新增語言支援
本指南說明如何為應用程式新增多語言支援。
前置條件
已了解 國際化 的基本概念。
新增語言
步驟 1:建立語言檔案
// src/nls/term/en.ts
export default {
'Customer': 'Customer',
'Order': 'Order',
'Product': 'Product',
'Save': 'Save',
'Delete': 'Delete',
'Cancel': 'Cancel',
'Confirm': 'Confirm',
'Search': 'Search',
'Loading': 'Loading',
'No data': 'No data',
};
// src/nls/message/en.ts
export default {
'Order ${orderNumber} created successfully!': 'Order ${orderNumber} created successfully!',
'${field} is required': '${field} is required',
'Are you sure you want to delete this item?': 'Are you sure you want to delete this item?',
'Changes saved successfully': 'Changes saved successfully',
'Failed to save changes': 'Failed to save changes',
};
步驟 2:註冊語言
// src/nls/index.ts
import { i18n } from '@appfuse/appfuse-web/utils';
// 繁體中文
import termZhTW from './term/zh-TW';
import messageZhTW from './message/zh-TW';
// 英文
import termEn from './term/en';
import messageEn from './message/en';
// 註冊翻譯
i18n.addTranslation('zh-TW', { ...termZhTW, ...messageZhTW });
i18n.addTranslation('en', { ...termEn, ...messageEn });
// 設定預設語言
i18n.language = 'zh-TW';
i18n.fallback = 'en';
步驟 3:在 App 入口載入
// src/main.tsx
import './nls'; // 載入語言設定
createRoot(document.getElementById('root')!).render(<App />);
新增語言切換器
步驟 1:建立切換元件
// src/components/LanguageSwitcher.tsx
import { i18n, useTranslation } from '@appfuse/appfuse-web/utils';
const languages = [
{ code: 'zh-TW', label: '繁體中文' },
{ code: 'en', label: 'English' },
];
export function LanguageSwitcher() {
const { language } = useTranslation();
const handleChange = (code: string) => {
i18n.language = code;
// 可選:儲存到 localStorage
localStorage.setItem('language', code);
};
return (
<select value={language} onChange={(e) => handleChange(e.target.value)}>
{languages.map((lang) => (
<option key={lang.code} value={lang.code}>
{lang.label}
</option>
))}
</select>
);
}
步驟 2:從 localStorage 恢復語言
// src/nls/index.ts
const savedLanguage = localStorage.getItem('language');
const browserLanguage = navigator.language; // e.g., 'zh-TW', 'en-US'
i18n.language = savedLanguage || browserLanguage || 'zh-TW';
翻譯最佳實踐
使用完整句子作為 Key
// ✅ 好
t('Order created successfully')
t('Are you sure you want to delete this item?')
// ❌ 避免
t('success')
t('confirm_delete')
參數化動態內容
// ✅ 好
t('Order ${orderNumber} created', { orderNumber: '12345' })
// ❌ 避免
t('Order ') + orderNumber + t(' created')
分類管理
src/nls/
├── term/ # 單字、術語
│ ├── zh-TW.ts
│ └── en.ts
├── message/ # 訊息、句子
│ ├── zh-TW.ts
│ └── en.ts
└── validation/ # 驗證訊息
├── zh-TW.ts
└── en.ts
處理日期和數字
日期格式
import { formatDate } from '@appfuse/appfuse-web/utils';
// 自動根據語言格式化
formatDate(new Date(), 'PPP'); // 2024年1月15日 / January 15, 2024
數字格式
// 使用 Intl.NumberFormat
const formatCurrency = (value: number, language: string) => {
const locale = language === 'zh-TW' ? 'zh-TW' : 'en-US';
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: language === 'zh-TW' ? 'TWD' : 'USD',
}).format(value);
};