Введение

Я всегда устанавливаю i18n (интернационализацию) в своих приложениях, даже если, вероятно, будет использоваться только один язык. Боль от адаптации приложения, которое изначально не считалось многоязычным, слишком велика, чтобы откладывать ее. К счастью, теперь у меня есть простая настройка с автодополнением с помощью машинописного текста, автоматическим определением языка пользователя и многим другим.

Настраивать

Чтобы получить пользовательский язык и обрабатывать наши переводы, мы используем 2 библиотеки:

React-native-localization: набор инструментов с простым API для получения локали, единиц измерения и часового пояса пользователя. (примечание: если вы используете expo, expo-localization также является хорошей библиотекой для использования)

react-i18next: мощный и популярный фреймворк для интернационализации в React/React-native.

npm install react-native-localize react-18next i18next

После установки нам нужен только один файл конфигурации и файлы JSON, которые будут содержать наши переводы для каждого языка.

import AsyncStorage from '@react-native-async-storage/async-storage'
import i18n, { LanguageDetectorAsyncModule } from 'i18next'
import { initReactI18next } from 'react-i18next'
import * as RNLocalize from 'react-native-localize'

import fr from './dictionaries/fr.json'

export const locales = {
  fr: {
    translation: fr,
  },
}

export const DEFAULT_LOCALE = 'fr'

export const defaultLanguage =
  RNLocalize.findBestAvailableLanguage(Object.keys(locales))?.languageTag || DEFAULT_LOCALE

export const currentLanguage = i18n.language || defaultLanguage

const useLanguageStorage: LanguageDetectorAsyncModule = {
  type: 'languageDetector',
  async: true,
  detect: async (callback) => {
    AsyncStorage.getItem('language').then((lang) => {
      if (lang) return callback(lang)
    })
  },
  init: () => null,
  cacheUserLanguage: async (language: string) => {
    AsyncStorage.setItem('language', language)
  },
}

i18n
  .use(useLanguageStorage)
  .use(initReactI18next)
  .init({
    fallbackLng: defaultLanguage,
    resources: locales,
    react: {
      useSuspense: false,
    },
  })

export default i18n

Затем вам нужно будет импортировать этот файл в свой App.tsx и все.

Автозаполнение с помощью машинописного текста

Одна раздражающая вещь при использовании ключей перевода — это ввод путей снова и снова. Чтобы улучшить опыт разработчиков, я добавляю небольшое определение, чтобы получить предложения с помощью Typescript, это помогает избежать ошибок и сократить время кодирования.

Создайте файл react-18next.d.ts в корне каталога вашего проекта или в папке types и добавьте этот код:

import 'react-i18next'

import fr from './i18n/dictionaries/fr.json'

declare module 'react-i18next' {
  // and extend them!
  interface Resources {
    translation: typeof fr
  }
}

С этой настройкой у вас должно получиться что-то подобное в VScode

Применение

Наиболее распространенное использование

Почти каждый раз, когда текст используется на экране, вы добавляете этот текст, связанный с ключом в файле JSON, используете хук, предоставленный i18next, который называется useTranslation, и используете ключ в своем тексте.

Доступ вне компонентов

Иногда вам может понадобиться использовать ваши переводы вне ваших компонентов в файлах конфигурации или что-то еще. Для этого вы можете напрямую импортировать файл i18n и получить доступ к методу t.

import i18next from './i18n'

i18next.t('my.key')

Вложенные тексты/несколько стилей

Одной из мощных функций react-i18next является компонент Trans, который может интерпретировать пользовательские теги в ваших переводах, чтобы использовать компонент для части вашего текста.

"myKey":"it is my text <color>colored part</color> end of text"
<Text>
  <Trans
    components={{ color: <Text font="bold"
    color="primary" /> }}
  >
    {t("path.to.my.key"}
  </Trans>
<Text>

Обновите язык

Для обновления языка вы используете тот же хук

const { t, i18n } = useTranslation('');
...
<Button onPress={()=>i18n.changeLanguage("de")>{i18n("switchLanguage")}</Button>Handle dates, currencies, API values

Обрабатывать даты, валюты, значения API

Для обработки дат я использую библиотеку dayjs, потому что это очень популярная библиотека, полная и имеет тот же API, что и Momentjs (которую я использовал в свое время).

import 'dayjs/locale/fr' // load on demand
dayjs.locale('fr') // use French locale globally
dayjs('2018-05-05').locale('fr-FR').format() // use on a specific textja

Для валют у вас есть несколько способов решить эту проблему, теперь я использую Intl.

const { i18n } = useTranslation()
<Text>{Intl.NumberFormat(i18n.language, {
    style: 'currency',
    currency: 'EUR'}).format(45012)}</Text>

В заключение убедитесь, что все ваши формы/динамические значения связаны с слагом или ключом, связанным с вашим API. С такой настройкой добавить еще один язык будет очень быстро, а не утомительной задачей.

😄 Спасибо за прочтение! Если вы нашли эту статью полезной, подписывайтесь на меня в Твиттере, я делюсь советами по разработке, дизайну и делюсь своим путешествием по созданию собственной стартап-студии.

Первоначально опубликовано на antoinemesnil.com