Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Локализация продукции очень важна для международных компаний, осваивающих новые для себя страны и регионы. Аналогично локализация нужна и мобильным приложениям. Если разработчик начинает международную экспансию, важно дать пользователям из другой страны возможность работать с интерфейсом на родном языке. В этой статье мы создадим приложение 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 рекомендует:
- Двухлетний практический курс «Я — веб-разработчик PRO».
- Онлайн-курс «С#-разработчик с нуля».
- Практический годовой курс «PHP-разработчик с 0 до PRO».