Melokalkan aplikasi di React Native

Selama pengembangan salah satu aplikasi kami, kami perlu membuat dukungan multibahasa. Tugasnya adalah memberi pengguna kemampuan untuk mengubah bahasa (Rusia dan Inggris) dari antarmuka aplikasi. Pada saat yang sama, teks dan konten harus diterjemahkan dengan cepat.



Untuk melakukan ini, kami harus menyelesaikan 2 masalah:



  1. Tentukan bahasa aplikasi saat ini.
  2. Menggunakan status global untuk terjemahan sambil jalan.


Pada artikel ini saya akan mencoba menjelaskan secara rinci bagaimana kami menyelesaikan masalah ini. Dan jadi kami pergi.



Tentukan bahasa perangkat saat ini



Untuk menentukan bahasa saat ini, Anda tentu saja dapat menggunakan pustaka react-native-i18n, tetapi kami memutuskan untuk melakukannya tanpanya, karena Anda dapat melakukannya tanpa pustaka pihak ketiga. Untuk melakukan ini, tulis yang berikut ini:



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


Untuk iOS, kami mengambil bahasa aplikasi melalui SettingsManager, dan untuk android melalui native I18nManager.



Sekarang setelah kami menerima bahasa perangkat saat ini, kami dapat menyimpannya ke AsyncStorage dan melanjutkan ke tugas kedua.



Kami menerjemahkan "dengan cepat"



Kami menggunakan MobX untuk mengelola status global, tetapi Anda dapat menggunakan solusi yang berbeda.



Jadi kita harus membuat kelas (saya suka menyebutnya "model") yang akan bertanggung jawab atas keadaan global lokalisasi saat ini. Kami menciptakan:



//   ,      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();


Saat kita menginisialisasi model kita, kita memanggil metode init, yang mengambil lokal baik dari AsyncStorage, jika ada, atau kita mengekstrak bahasa perangkat saat ini dan meletakkannya di AsyncStorage.



Selanjutnya, kita perlu menulis metode (tindakan) yang akan mengubah bahasa:



  @action
  changeLang(lang: string) {
    this.lang = lang;
    AsyncStorage.setItem(STORE, lang);
  }


Saya pikir semuanya jelas di sini.



Sekarang tiba bagian menyenangkan. Kami memutuskan untuk menyimpan terjemahannya sendiri dalam kamus sederhana. Untuk melakukan ini, buat file js di sebelah LangModel kami, di mana kami akan meletakkan terjemahan kami:



// translations.js
// ,     . 
export default const translations = {
  ", !": {en: "Hello, World!"},
}


Selanjutnya, kami akan menerapkan satu metode lagi di LangModel, yang akan menerima teks sebagai masukan dan mengembalikan teks dari lokalisasi saat ini:



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];
  }


Itu saja, LangModel kita sudah siap.



Lengkapi Kode LangModel
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();




Sekarang kita dapat menggunakan metode rk untuk melokalkan teks:



<Text>{LangModel.rk(", !")}</Text>


Anda dapat melihat cara kerjanya di aplikasi kami di AppStore dan Google Play (Klik pada ikon (!) Di kanan atas, gulir ke bawah)



Bonus



Tentu saja, menulis LangModel.rk setiap saat tidaklah keren. Oleh karena itu, kita dapat membuat komponen Teks kita sendiri dan sudah menggunakan LangModel.rk di dalamnya



//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>
));


Kami mungkin juga perlu, misalnya, untuk mengubah logo aplikasi tergantung pada lokalisasi saat ini. Untuk melakukan ini, Anda cukup mengubah konten tergantung pada LangModel.lang (jangan lupa untuk membungkus komponen Anda di pengamat (MobX))



PS: Mungkin pendekatan ini akan tampak bukan standar, tetapi kami menyukainya lebih dari yang ditawarkan oleh react-native-i18n



On itu saja untuk saya. Terimakasih untuk semua!)



All Articles