乐闻世界logo
搜索文章和话题

How to implement internationalization (i18n) in Expo apps? What are recommended libraries?

2月21日 15:58

Internationalization (i18n) of Expo apps is an important feature for serving global users. Expo supports multiple internationalization solutions, enabling developers to easily implement multi-language support.

Internationalization Library Selection:

  1. i18next

The most popular internationalization library, powerful and easy to use.

Installation:

bash
npm install i18next react-i18next expo-localization

Configure i18next:

typescript
// i18n.ts import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import { getLocales } from 'expo-localization'; const resources = { en: { translation: { welcome: 'Welcome', login: 'Login', logout: 'Logout', 'hello.name': 'Hello, {{name}}!', }, }, zh: { translation: { welcome: '欢迎', login: '登录', logout: '退出', 'hello.name': '你好,{{name}}!', }, }, }; i18n .use(initReactI18next) .init({ resources, lng: getLocales()[0]?.languageCode || 'en', fallbackLng: 'en', interpolation: { escapeValue: false, }, }); export default i18n;

Use i18next:

typescript
import { useTranslation } from 'react-i18next'; function WelcomeScreen() { const { t, i18n } = useTranslation(); const changeLanguage = (lang: string) => { i18n.changeLanguage(lang); }; return ( <View> <Text>{t('welcome')}</Text> <Text>{t('hello.name', { name: 'John' })}</Text> <Button title="English" onPress={() => changeLanguage('en')} /> <Button title="中文" onPress={() => changeLanguage('zh')} /> </View> ); }
  1. expo-localization

Expo's official localization library for getting device language settings.

Use expo-localization:

typescript
import * as Localization from 'expo-localization'; function getDeviceLanguage() { const locale = Localization.locale; const languageCode = Localization.locale.split('-')[0]; console.log('Locale:', locale); console.log('Language:', languageCode); return languageCode; }

Get Localization Info:

typescript
function getLocalizationInfo() { const locale = Localization.locale; const timezone = Localization.timezone; const isoCurrencyCodes = Localization.isoCurrencyCodes; return { locale, timezone, currency: isoCurrencyCodes[0], }; }
  1. React Native Localization

Lightweight internationalization solution.

Installation:

bash
npm install react-native-localize

Configuration:

typescript
import * as RNLocalize from 'react-native-localize'; const translations = { en: require('./en.json'), zh: require('./zh.json'), }; const fallback = { languageTag: 'en', isRTL: false }; const { languageTag } = RNLocalize.findBestAvailableLanguage(Object.keys(translations)) || fallback; i18n.init({ resources: { [languageTag]: translations[languageTag], }, lng: languageTag, fallbackLng: 'en', });

Multi-language Resource Management:

  1. JSON File Structure
json
// locales/en.json { "common": { "ok": "OK", "cancel": "Cancel", "save": "Save" }, "auth": { "login": "Login", "logout": "Logout", "register": "Register", "forgotPassword": "Forgot Password?" }, "home": { "title": "Home", "welcome": "Welcome back!", "recentActivity": "Recent Activity" } }
json
// locales/zh.json { "common": { "ok": "确定", "cancel": "取消", "save": "保存" }, "auth": { "login": "登录", "logout": "退出", "register": "注册", "forgotPassword": "忘记密码?" }, "home": { "title": "首页", "welcome": "欢迎回来!", "recentActivity": "最近活动" } }
  1. Namespace Organization
typescript
// Use namespaces i18n.init({ resources: { en: { common: require('./locales/en/common.json'), auth: require('./locales/en/auth.json'), home: require('./locales/en/home.json'), }, zh: { common: require('./locales/zh/common.json'), auth: require('./locales/zh/auth.json'), home: require('./locales/zh/home.json'), }, }, }); // Use namespace const { t } = useTranslation('common'); <Text>{t('ok')}</Text> // Cross namespace <Text>{t('auth:login')}</Text>

Date and Time Localization:

typescript
import { format } from 'date-fns'; import { zhCN, enUS } from 'date-fns/locale'; function formatDate(date: Date, locale: string) { const localeMap = { en: enUS, zh: zhCN, }; return format(date, 'PPP', { locale: localeMap[locale] || enUS, }); } function formatDateTime(date: Date, locale: string) { return format(date, 'PPPppp', { locale: locale === 'zh' ? zhCN : enUS, }); }

Number and Currency Localization:

typescript
function formatCurrency(amount: number, locale: string) { return new Intl.NumberFormat(locale, { style: 'currency', currency: locale === 'zh' ? 'CNY' : 'USD', }).format(amount); } function formatNumber(number: number, locale: string) { return new Intl.NumberFormat(locale).format(number); } function formatPercent(value: number, locale: string) { return new Intl.NumberFormat(locale, { style: 'percent', minimumFractionDigits: 2, }).format(value); }

RTL (Right-to-Left) Support:

typescript
import { I18nManager } from 'react-native'; function setupRTL(locale: string) { const isRTL = locale === 'ar' || locale === 'he'; if (I18nManager.isRTL !== isRTL) { I18nManager.allowRTL(isRTL); I18nManager.forceRTL(isRTL); // Need to restart app Updates.reloadAsync(); } }

Dynamic Language Switching:

typescript
function LanguageSwitcher() { const { i18n } = useTranslation(); const [currentLang, setCurrentLang] = useState(i18n.language); const changeLanguage = async (lang: string) => { await i18n.changeLanguage(lang); setCurrentLang(lang); // Save user preference await AsyncStorage.setItem('userLanguage', lang); // If RTL support needed setupRTL(lang); }; const languages = [ { code: 'en', name: 'English' }, { code: 'zh', name: '中文' }, { code: 'es', name: 'Español' }, ]; return ( <View> {languages.map((lang) => ( <Button key={lang.code} title={lang.name} onPress={() => changeLanguage(lang.code)} disabled={currentLang === lang.code} /> ))} </View> ); }

Best Practices:

  1. Resource File Organization

    • Organize translation files by feature modules
    • Use namespaces to avoid conflicts
    • Keep translation file structure consistent
  2. Translation Quality

    • Use professional translation tools
    • Consider cultural differences and habits
    • Regularly review and update translations
  3. Performance Optimization

    • Load language packages on demand
    • Cache translation results
    • Avoid frequent language switching
  4. User Experience

    • Auto-detect device language
    • Provide language switching options
    • Save user language preferences
  5. Test Coverage

    • Test display in all languages
    • Check for text overflow issues
    • Verify RTL layouts

Common Issues:

  1. Missing Translations

    • Set fallback language
    • Use translation management tools
    • Regularly check translation completeness
  2. Text Overflow

    • Use flex layout
    • Provide text truncation options
    • Adjust layout for different languages
  3. Dynamic Loading

    • Use code splitting
    • Lazy load language packages
    • Preload common languages

Through comprehensive internationalization implementation, Expo apps can better serve global users and improve user experience and market competitiveness.

标签:Expo