簡體   English   中英

React Native & i18n 在路由到另一個屏幕后返回默認語言

[英]React Native & i18n returns to default language after routing to another screen

我正在將 React Native 與 i18n 語言管理器一起使用,並且我正在嘗試在首次應用啟動時創建語言選擇。

首屏啟動

語言選擇屏幕確實有效,在選擇語言后組件重新渲染並執行正確的語言。 (假設我選擇了英文,按鈕字符串是英文的)

重新渲染

但是登錄到應用程序后,語言發生了變化,我真的不明白為什么。 (這里假設是英文,而是顯示希伯來語字符串)

在此處輸入圖像描述

這是 App.js 文件,我使用Async Storage檢查該應用程序之前是否已啟動(如果沒有顯示語言選擇,是否使用了保存的語言選擇)。

import React, {useEffect, useState} from "react";
import Login from "./login.js";
import Register from "./register.js";
import Dashboard from "./dashboard.js";
import i18n from "./translation.js";
import { NavigationContainer, useNavigation } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { Text, View, Button, I18nManager } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";



const Stack = createStackNavigator();
const HAS_LAUNCHED = "hasLaunched";
const ENGLISH = "en";
const HEBREW = "he";


//Save the language as AsyncStorage for other times the user will open the app
async function setAppLaunched(en) {
  AsyncStorage.setItem(HAS_LAUNCHED, "true");
  AsyncStorage.setItem(en ? ENGLISH : HEBREW, "true");
  if(await AsyncStorage.getItem(HEBREW)){
    i18n.locale = "he";
    I18nManager.forceRTL(true);
  }
  else{
    i18n.locale = "en";
    I18nManager.forceRTL(false);
  }
}


//If first launch show this screen
function CheckIfFirstLaunch({ onSelect }) {
  const navigation = useNavigation();

  const selectLaunched = (value) => {
    if(value){
      i18n.locale = "en";
      I18nManager.forceRTL(false);
    }
    else{
      i18n.locale = "he";
      I18nManager.forceRTL(true);
    }
    setAppLaunched(value);
    onSelect();
    navigation.navigate('Login');
  };


  return (
    <View>
        <Text>Choose Language</Text>
        <Button onPress={() => selectLaunched(false)} title="Hebrew"/>
        <Button onPress={() => selectLaunched(true)} title="English"/>
    </View>
  );
}

export default function App() {
  const [selected, setSelected] = useState(false);
  const verifyHasLaunched = async () => {
    try {
      const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
      console.log(await AsyncStorage.getItem(HAS_LAUNCHED));
      if(hasLaunched){
        setSelected(true);
      }
      else{
        setSelected(false);
      }
    } catch (err) {
      setSelected(false);
    }
  };

  useEffect(() => verifyHasLaunched, []);


  if(selected){
    const verifyLang = async () => {
      const lang = await AsyncStorage.getItem('he');
      if(lang != null){
        i18n.locale = "he";
        I18nManager.forceRTL(true);
      }
      else{
        i18n.locale = "en";
        I18nManager.forceRTL(false);
      }
   };
   () => verifyLang;
  }

  return (
    <NavigationContainer>
      <Stack.Navigator screenOptions={{headerShown: false}} initialRouteName={selected ? "Login" : "Language"}>
        <Stack.Screen name="Language" >
          {props => (<CheckIfFirstLaunch {...props} onSelect={() => setSelected(true)} />)}
        </Stack.Screen>
        <Stack.Screen name="Login" component={Login} />
        <Stack.Screen name="Register" component={Register} />
        <Stack.Screen name="Dashboard" component={Dashboard} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

翻譯.js

import i18n from 'i18n-js';
import en from './locale/en.json';
import he from './locale/he.json';

i18n.defaultLocale = 'en';
i18n.fallbacks = true;
i18n.translations = { en, he };


export default i18n;

我已經調試了AsyncStorage中的值並收到了正確的值。

看起來, Async Storage保存了重新渲染App.js文件的語言數據,但 I18n 在屏幕路由后重置了他的設置。 這是為什么?

如何在第一次使用 React Native 啟動應用程序時為整個應用程序設置語言?

代碼沙盒

我已經分叉了你的沙箱https://codesandbox.io/s/xenodochial-mclean-ctk5p?file=/src/App.js

有幾個變化。

問題來自這樣一個事實,即每次您選擇一種語言時,您都將其設置為存儲中的鍵。

一旦您選擇了英語,重新加載並選擇了希伯來語,您就可以像這樣在存儲中獲得兩個鍵

{'he': true, 'en': true}

在這一點上,這部分總是將 lang 設置為希伯來語,因為確實有這樣的鍵(“他”是真的)。

 const verifyLang = async () => {
      const lang = await AsyncStorage.getItem('he');
      if(lang != null){
        i18n.locale = "he";
        I18nManager.forceRTL(true);
       }

我改變的是我們不再將每種語言都設置為鍵。 相反,我們通過selectLaunched傳遞語言本身。 然后我們將它保存在存儲中的lang鍵中。 這樣, lang鍵始終存儲正確的語言 - 'he' 或 'en'。

verifyLang可以刪除,因為它不再需要。 希望這能解決您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM