Пишем мультиязычное приложение на React Native

Локализация продукции очень важна для международных компаний, осваивающих новые для себя страны и регионы. Аналогично локализация нужна и мобильным приложениям. Если разработчик начинает международную экспансию, важно дать пользователям из другой страны возможность работать с интерфейсом на родном языке. В этой статье мы создадим приложение React Native, используя пакет react-native-localize.

Skillbox рекомендует: Образовательный онлайн-курс «Профессия Java-разработчик».
Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».

Инструменты и навыки

Для понимания этой статьи нужны базовые навыки работы с React Native. Для ознакомления с настройками рабочей машины можно воспользоваться официальной инструкцией.

Нам понадобятся вот такие версии программных инструментов:

  • Node v10.15.0
  • npm 6.4.1
  • yarn 1.16.0
  • react-native 0.59.9
  • react-native-localize 1.1.3
  • i18n-js 3.3.0

Начинаем

Мы создадим приложение, которое будет поддерживать английский, французский и арабский языки. Сначала создаем новый проект, используя react-native-cli. Для этого в терминале нужно набрать вот что:

$ react-native init multiLanguage
$ cd multiLanguage

Добавляем необходимые библиотеки

Первым делом нужно установить react-native-localize, набрав следующее:
$ yarn add react-native-localize

Если в процессе установки возникают проблемы, стоит изучить мануал по установке.

Библиотека react-native-localize дает разработчику доступ к мультиязычным функциям. Но ей нужна еще одна библиотека — i18n.

В статье описывается использование I18n.js для того, чтобы обеспечить перевод в JavaScript.

$ yarn add i18n-js

Ну а поскольку i18n-js не предоставляет кэширования или мемоизации, я предлагаю использовать для этого lodash.memoize:

$ yarn add lodash.memoize

Работа с переводами

Для того, чтобы приложение умело работать и с другими языками, сначала нужно создать каталог translations внутри src, потом — три файла JSON, для каждого из языков.

1. en.json для английского;

2. fr.json для французского;

3. ar.json для арабского.

Эти файлы содержат объекты JSON с ключами и значениями. Ключ будет один и тот же для каждого языка. Он используется приложением для отображения текстовой информации.

Значение (value) — это текст, который нужно показывать пользователю.

Английский язык:

{ «hello»: «Hello World!»}

Французский

{ «hello»: «Salut le Monde!»}

Арабский

{ «hello»: «أهلاً بالعالم»}

Аналогичным образом можно добавлять и другие языки.

Основной код

На этом этапе нужно открыть файл App.js и добавить в него импорт:

import React from "react"; import * as RNLocalize from "react-native-localize"; import i18n from "i18n-js"; import memoize from "lodash.memoize"; // Use for caching/memoize for better performance   import {   I18nManager,   SafeAreaView,   ScrollView,   StyleSheet,   Text,   View } from "react-native";

После этого добавляются вспомогательные функции и константы, которые пригодятся впоследствии.

const translationGetters = {   // lazy requires (metro bundler does not support symlinks)   ar: () => require("./src/translations/ar.json"),   en: () => require("./src/translations/en.json"),   fr: () => require("./src/translations/fr.json") };   const translate = memoize(   (key, config) => i18n.t(key, config),   (key, config) => (config ? key + JSON.stringify(config) : key) );   const setI18nConfig = () => {   // fallback if no available language fits   const fallback = { languageTag: "en", isRTL: false };     const { languageTag, isRTL } =     RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||     fallback;     // clear translation cache   translate.cache.clear();   // update layout direction   I18nManager.forceRTL(isRTL);   // set i18n-js config   i18n.translations = { [languageTag]: translationGetters[languageTag]() };   i18n.locale = languageTag; };

Ну а теперь создадим компонент класса App:

export default class App extends React.Component {   constructor(props) {     super(props);     setI18nConfig(); // set initial config   }     componentDidMount() {     RNLocalize.addEventListener("change", this.handleLocalizationChange);   }     componentWillUnmount() {     RNLocalize.removeEventListener("change", this.handleLocalizationChange);   }     handleLocalizationChange = () => {     setI18nConfig();     this.forceUpdate();   };     render() {     return (       <SafeAreaView style={styles.safeArea}>         <Text style={styles.value}>{translate("hello")}</Text>       </SafeAreaView>     );   } }   const styles = StyleSheet.create({   safeArea: {     backgroundColor: "white",     flex: 1,     alignItems: "center",     justifyContent: "center"   },   value: {     fontSize: 18   } });

Первый элемент — setI18nConfig() — устанавливает начальную конфигурацию.

Затем в componentDidMount() нужно добавить прослушивание событий, этот элемент будет отслеживать обновления и вызывать handleLocalizationChange() в том случае, когда они происходят.

Метод handleLocalizationChange() активизирует setI18nConfig() и forceUpdate(). Это необходимо для устройств на Android, так как компонент должен быть отрендерен, чтобы изменения стали заметными.

Затем нужно убрать прослушивание из метода componentWillUnmount().

Наконец, в render() возвращается hello путем использования translate() и добавления в него параметра key. После этих действий приложение сможет «понимать», какой язык нужен, и показывать сообщения именно на нем.

Запуск приложения

Теперь самое время проверить, как работает перевод.

Сначала запускаем приложение в симуляторе или эмуляторе, набирая

$ react-native run-ios
$ react-native run-android

Выглядеть это будет примерно так:

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

С арабским языком проделываем то же самое, разницы нет.

Пока все идет хорошо.

Но что произойдет, если выбрать случайный язык, перевода которого нет в приложении?

Оказывается, задача findBestLanguage — предоставление оптимального из всех доступных перевода. В результате будет отображаться язык, который был установлен по умолчанию.

Речь идет о настройках телефона. Так, например, в эмуляторе iOS можно посмотреть порядок языков.

Если выбранный язык не является предпочитаемым, findBestAvailableLanguage возвращает undefined, так что показывается тот язык, который установлен по умолчанию.

Бонус

У react-native-localize есть API, которое предоставляет доступ к большому количеству языковых элементов. Перед тем, как начать работу, стоит ознакомиться с документацией.

Выводы

Приложение можно сделать мультиязычным без особых проблем. React-native-localize — отличный вариант, который позволяет расширить круг пользователей приложения.

Исходный код проекта находится здесь.

Skillbox рекомендует:


ссылка на оригинал статьи https://habr.com/ru/company/skillbox/blog/459741/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *