[Разработка мобильных приложений, Локализация продуктов] Локализуем приложение на React Native
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В ходе разработки одного из наших приложений нам понадобилось сделать поддержку мультиязычности. Задача была дать пользователю возможность менять язык(русский и английский) интерфейса приложения. При этом текста и контент должны переводиться «на лету».
Для этого нам нужно было решить 2 задачи:
1. Определить текущий язык приложения.
2. Использование глобального состояния для перевода «на лету».
В этой статья попробую подробно расписать как мы решили данные задачи. И так поехали.
Определяем текущий язык устройства
Для определения текущего языка можно, конечно, воспользоваться библиотекой react-native-i18n, но мы решили обойтись без него, так как для решения этой задачи можно и без сторонних библиотек. Для этого пишем следующее:
import {NativeModules, Platform} from 'react-native';
let deviceLanguage = (Platform.OS === 'ios'
? NativeModules.SettingsManager.settings.AppleLocale ||
NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13
: NativeModules.I18nManager.localeIdentifier
Для ios мы извлекаем язык приложения через SettingsManager, а для android через нативный I18nManager.
Теперь когда мы получили текущий язык устройства, мы можем сохранить его в AsyncStorage и приступить ко второй задаче.
Переводим «на лету»
Для управления глобальным состоянием мы используем MobX, но вы можете использовать другое решение.
И так мы должны создать класс(мне нравится называть «модель»), который будет отвечать за глобальное состояния текущей локализации. Создаем:
// ключ локального хранилища, в котором будем записывать текущий lang
const STORE = '@lang-store';
// список русскоязычных стран
const RU_LANGS = [
'ru',
'az',
'am',
'by',
'ge',
'kz',
'kg',
'md',
'tj',
'tm',
'uz',
'ua',
];
class LangModel {
@observable
lang = 'ru'; // по умолчанию
constructor() {
this.init();
}
@action
async init() {
const lang = await AsyncStorage.getItem(STORE);
if (lang) {
this.lang = lang;
} else {
let deviceLanguage: string = (Platform.OS === 'ios'
? NativeModules.SettingsManager.settings.AppleLocale ||
NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13
: NativeModules.I18nManager.localeIdentifier
).toLowerCase();
if (
RU_LANGS.findIndex((rulang) => deviceLanguage.includes(rulang)) === -1
) {
this.lang = 'en';
}
AsyncStorage.setItem(STORE, this.lang);
}
}
export default new LangModel();
При инициализации нашей модели мы вызываем метод init, который берет локаль либо из AsyncStorage, если там есть, либо извлекаем текущий язык устройства и кладет в AsyncStorage.
Далее нам нужно написать метод(action), который будет менять язык:
@action
changeLang(lang: string) {
this.lang = lang;
AsyncStorage.setItem(STORE, lang);
}
Думаю, что тут все понятно.
Теперь самое интересное. Сами переводы мы решили хранить простым словарем. Для этого создадим js файл рядом с нашей LangModel, в котором мы поместим наши переводы:
// translations.js
// Да, за основу мы взяли русский.
export default const translations = {
"Привет, Мир!": {en: "Hello, World!"},
}
Далее реализуем еще один метод в LangModel, который будет принимать на вход текст и возвращать текст текущей локализации:
import translations from './translations';
...
rk(text) {
if (!text) {
return text;
}
// если локаль ru, то переводить не нужно
if (this.lang === 'ru') {
return text;
}
// если перевода нет, кинем предупреждение
if (translations[text] === undefined || translations[text][this.lang] === undefined) {
console.warn(text);
return text;
}
return translations[text][this.lang];
}
Все, наш LangModel готов.
Полный код LangModel
SPL
import {NativeModules, Platform} from 'react-native';
import {observable, action} from 'mobx';
import AsyncStorage from '@react-native-community/async-storage';
import translations from './translations';
const STORE = '@lang-store';
// список ru локали
const RU_LANGS = [
'ru',
'az',
'am',
'by',
'ge',
'kz',
'kg',
'md',
'tj',
'tm',
'uz',
'ua',
];
class LangModel {
@observable
lang = 'en';
constructor() {
this.init();
}
@action
async init() {
// Берем текущую локаль из AsyncStorage
const lang = await AsyncStorage.getItem(STORE);
if (lang) {
this.lang = lang;
} else {
let deviceLanguage: string = (Platform.OS === 'ios'
? NativeModules.SettingsManager.settings.AppleLocale ||
NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13
: NativeModules.I18nManager.localeIdentifier
).toLowerCase();
if (
RU_LANGS.findIndex((rulang) => deviceLanguage.includes(rulang)) > -1
) {
this.lang = 'ru';
}
AsyncStorage.setItem(STORE, this.lang);
}
@action
changeLang(lang: string) {
this.lang = lang;
AsyncStorage.setItem(STORE, lang);
}
rk(text) {
if (!text) {
return text;
}
// если локаль ru, то переводить не нужно
if (this.lang === 'ru') {
return text;
}
// если перевода нет, кинем предупреждение
if (translations[text] === undefined || translations[text][this.lang] === undefined) {
console.warn(text);
return text;
}
return translations[text][this.lang];
}
}
export default new LangModel();
Теперь мы можем использовать метод rk для локализация текста:
<Text>{LangModel.rk("Привет, Мир!")}</Text>
Посмотреть как это работает можно в нашем приложении в AppStore и Google Play (Нажать на иконку (!) справа вверху, пролистать вниз)
Бонус
Конечно, писать каждый раз LangModel.rk это не круто. Поэтому мы можем создать собственный компонент Text и в нем уже использовать LangModel.rk
//components/text.js
import React from 'react';
import {Text} from 'react-native';
import {observer} from 'mobx-react';
import {LangModel} from 'models';
export const MyText = observer((props) => (
<Text {...props}>{props.notTranslate ? props.children : LangModel.rk(props.children)}</Text>
));
Так же нам может понадобиться, например, менять логотип приложения в зависимости от текущей локализации. Для этого можно просто менять контент в зависимости от LangModel.lang (не забудьте обернуть ваш компонент в observer(MobX))
P.S.: Возможно такой подход вам покажется не стандартным, но он нам понравился больше чем то, что предлагает react-native-i18n
На этом у меня все. Всем спасибо!)
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка мобильных приложений, Разработка под Android, Системы обмена сообщениями] Google без предупреждения удалила из магазина приложений почтовый сервис K-9 Mail за разное написание названия
- [Информационная безопасность, Разработка мобильных приложений, Разработка под Android, Софт] В Android 11 появилась встроенная функция записи экрана, а вскоре Google пообещала верифицированные звонки
- [Flutter, Программирование, Разработка мобильных приложений] Flutter.dev: Простое управление состоянием приложения (перевод)
- [Законодательство в IT, Разработка мобильных приложений, Разработка под iOS] В Госдуме пожаловались в ФАС на то, что российские разработчики покупают аккаунты за рубежом для доступа в App Store
- [Разработка мобильных приложений, Разработка для интернета вещей] Fuchsia OS: Возможности и перспективы развития
- [API, Информационная безопасность, Разработка мобильных приложений] Во фреймворке Apple/Google для отслеживания контактов больных коронавирусом нашли уязвимость
- [C++, Open source, Swift, Локализация продуктов, Разработка под iOS] Формулы переводов: хитрая локализация
- [Разработка веб-сайтов, Разработка мобильных приложений, C#, Облачные сервисы] Продвинутое велосипедостроение или клиент-серверное приложение на базе C# .Net framework
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android] «Ну, покати!» или CI/CD мобильных приложений на основе контракта
- [Kotlin, Голосовые интерфейсы, Разработка мобильных приложений, Разработка под Android] Как встроить голосового помощника в любое мобильное приложение. Разбираем на примере Habitica
Теги для поиска: #_razrabotka_mobilnyh_prilozhenij (Разработка мобильных приложений), #_lokalizatsija_produktov (Локализация продуктов), #_react_native, #_reactnative, #_mobile_development, #_razrabotka_mobilnyh_prilozhenij (
Разработка мобильных приложений
), #_lokalizatsija_produktov (
Локализация продуктов
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:29
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В ходе разработки одного из наших приложений нам понадобилось сделать поддержку мультиязычности. Задача была дать пользователю возможность менять язык(русский и английский) интерфейса приложения. При этом текста и контент должны переводиться «на лету». Для этого нам нужно было решить 2 задачи: 1. Определить текущий язык приложения. 2. Использование глобального состояния для перевода «на лету». В этой статья попробую подробно расписать как мы решили данные задачи. И так поехали. Определяем текущий язык устройства Для определения текущего языка можно, конечно, воспользоваться библиотекой react-native-i18n, но мы решили обойтись без него, так как для решения этой задачи можно и без сторонних библиотек. Для этого пишем следующее: import {NativeModules, Platform} from 'react-native';
let deviceLanguage = (Platform.OS === 'ios' ? NativeModules.SettingsManager.settings.AppleLocale || NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13 : NativeModules.I18nManager.localeIdentifier Для ios мы извлекаем язык приложения через SettingsManager, а для android через нативный I18nManager. Теперь когда мы получили текущий язык устройства, мы можем сохранить его в AsyncStorage и приступить ко второй задаче. Переводим «на лету» Для управления глобальным состоянием мы используем MobX, но вы можете использовать другое решение. И так мы должны создать класс(мне нравится называть «модель»), который будет отвечать за глобальное состояния текущей локализации. Создаем: // ключ локального хранилища, в котором будем записывать текущий lang
const STORE = '@lang-store'; // список русскоязычных стран const RU_LANGS = [ 'ru', 'az', 'am', 'by', 'ge', 'kz', 'kg', 'md', 'tj', 'tm', 'uz', 'ua', ]; class LangModel { @observable lang = 'ru'; // по умолчанию constructor() { this.init(); } @action async init() { const lang = await AsyncStorage.getItem(STORE); if (lang) { this.lang = lang; } else { let deviceLanguage: string = (Platform.OS === 'ios' ? NativeModules.SettingsManager.settings.AppleLocale || NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13 : NativeModules.I18nManager.localeIdentifier ).toLowerCase(); if ( RU_LANGS.findIndex((rulang) => deviceLanguage.includes(rulang)) === -1 ) { this.lang = 'en'; } AsyncStorage.setItem(STORE, this.lang); } } export default new LangModel(); При инициализации нашей модели мы вызываем метод init, который берет локаль либо из AsyncStorage, если там есть, либо извлекаем текущий язык устройства и кладет в AsyncStorage. Далее нам нужно написать метод(action), который будет менять язык: @action
changeLang(lang: string) { this.lang = lang; AsyncStorage.setItem(STORE, lang); } Думаю, что тут все понятно. Теперь самое интересное. Сами переводы мы решили хранить простым словарем. Для этого создадим js файл рядом с нашей LangModel, в котором мы поместим наши переводы: // translations.js
// Да, за основу мы взяли русский. export default const translations = { "Привет, Мир!": {en: "Hello, World!"}, } Далее реализуем еще один метод в LangModel, который будет принимать на вход текст и возвращать текст текущей локализации: import translations from './translations';
... rk(text) { if (!text) { return text; } // если локаль ru, то переводить не нужно if (this.lang === 'ru') { return text; } // если перевода нет, кинем предупреждение if (translations[text] === undefined || translations[text][this.lang] === undefined) { console.warn(text); return text; } return translations[text][this.lang]; } Все, наш LangModel готов. Полный код LangModelSPLimport {NativeModules, Platform} from 'react-native';
import {observable, action} from 'mobx'; import AsyncStorage from '@react-native-community/async-storage'; import translations from './translations'; const STORE = '@lang-store'; // список ru локали const RU_LANGS = [ 'ru', 'az', 'am', 'by', 'ge', 'kz', 'kg', 'md', 'tj', 'tm', 'uz', 'ua', ]; class LangModel { @observable lang = 'en'; constructor() { this.init(); } @action async init() { // Берем текущую локаль из AsyncStorage const lang = await AsyncStorage.getItem(STORE); if (lang) { this.lang = lang; } else { let deviceLanguage: string = (Platform.OS === 'ios' ? NativeModules.SettingsManager.settings.AppleLocale || NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13 : NativeModules.I18nManager.localeIdentifier ).toLowerCase(); if ( RU_LANGS.findIndex((rulang) => deviceLanguage.includes(rulang)) > -1 ) { this.lang = 'ru'; } AsyncStorage.setItem(STORE, this.lang); } @action changeLang(lang: string) { this.lang = lang; AsyncStorage.setItem(STORE, lang); } rk(text) { if (!text) { return text; } // если локаль ru, то переводить не нужно if (this.lang === 'ru') { return text; } // если перевода нет, кинем предупреждение if (translations[text] === undefined || translations[text][this.lang] === undefined) { console.warn(text); return text; } return translations[text][this.lang]; } } export default new LangModel(); Теперь мы можем использовать метод rk для локализация текста: <Text>{LangModel.rk("Привет, Мир!")}</Text>
Посмотреть как это работает можно в нашем приложении в AppStore и Google Play (Нажать на иконку (!) справа вверху, пролистать вниз) Бонус Конечно, писать каждый раз LangModel.rk это не круто. Поэтому мы можем создать собственный компонент Text и в нем уже использовать LangModel.rk //components/text.js
import React from 'react'; import {Text} from 'react-native'; import {observer} from 'mobx-react'; import {LangModel} from 'models'; export const MyText = observer((props) => ( <Text {...props}>{props.notTranslate ? props.children : LangModel.rk(props.children)}</Text> )); Так же нам может понадобиться, например, менять логотип приложения в зависимости от текущей локализации. Для этого можно просто менять контент в зависимости от LangModel.lang (не забудьте обернуть ваш компонент в observer(MobX)) P.S.: Возможно такой подход вам покажется не стандартным, но он нам понравился больше чем то, что предлагает react-native-i18n На этом у меня все. Всем спасибо!) =========== Источник: habr.com =========== Похожие новости:
Разработка мобильных приложений ), #_lokalizatsija_produktov ( Локализация продуктов ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:29
Часовой пояс: UTC + 5