【问题标题】:react native async - rerendering after user input on multi-language app [missing translation]反应原生异步 - 在多语言应用程序上用户输入后重新呈现 [缺少翻译]
【发布时间】:2020-09-15 07:33:00
【问题描述】:

我正在尝试从设置屏幕更新应用程序的语言。整个应用程序应该更改语言 onLanguageChange。该应用程序做了一些事情,因为不同的字段显示为[missing '[langCode].[screenName].[fieldName] translation],所以我很接近,但我无法使应用程序正确重新加载,我已经尝试了互联网上可用的所有内容。这基本上是状态更新时更新屏幕的问题,但是应用程序需要一些时间来加载 JSON

有什么想法吗?我在这里:

在我的设置屏幕中

import { AsyncStorage } from 'react-native';
import i18n, {updateLocale, strings} from '../assets/locales/i18n'

export default function SettingsScreen({navigation}) {

  const {signOut} = React.useContext(global.AuthContext)
  
  const currentLanguage = i18n.locale.toString().substr(0,2);
  const [selectedLanguage, setSelectedLanguage] = useState(currentLanguage);
  const [selectedNotifications, setNotificationsOptions] = useState('On');

const onChangeLanguage = (value) => {
        setSelectedLanguage(value)
        updateLocale(value)
  }

  return (

          <Text style={styles.maintext}>{strings('settingsscreen.Language')}</Text>
          <RNPickerSelect
            placeholder={{}}
            value={selectedLanguage}
            style={pickerSelectStyles}
            onValueChange={(value)=>onChangeLanguage(value)}
            items={[
              { label: 'Español', value: 'es' },
              { label: 'Català', value: 'ca' },
              { label: 'English', value: 'en' },
          ]}
            />

        (...)

        <View style={styles.bubble}>
          <Button title={strings('settingsscreen.signout')} onPress={()=>{
              AsyncStorage.setItem('LANGUAGE', selectedLanguage) && signOut()
          }}
           color='white' />  
        </View>

  );
}


还有我的 i18n.js:

import * as Localization from 'expo-localization';
import { AsyncStorage } from 'react-native';
import i18n from 'i18n-js';

// Should the app fallback to English if user locale doesn't exists
i18n.fallbacks = true;
i18n.defaultLocale = 'en';
i18n.locale = 'en';

import en from './en';
import es from './es'; 
import ca from './ca';  

i18n.translations = {
  en,
  es,
  ca,
};

// The method we'll use instead of a regular string
export function strings(name, params = {}) {
  return i18n.t(name, params);
};

// Setting the locale to be used on first render
export const loadLocale = async () => {

  //First we check if there is already a selected variable in AsyncStorage

  asyncSelectedLanguage = await AsyncStorage.getItem('LANGUAGE');
  console.log('async language: ' +asyncSelectedLanguage)

  if (asyncSelectedLanguage!==null) {
    i18n.locale = asyncSelectedLanguage;
  } else {
    i18n.locale = Localization.locale;
  }

  console.log('i18n locale' + i18n.locale)

  
  switch (i18n.locale.toString().substr(0,2)) {
        case 'en': import('./en.json').then(en => {i18n.translations = { en }}); break;
        case 'ca': import('./ca.json').then(ca => {i18n.translations = { ca }}); break;
        case 'es': import('./es.json').then(es => {i18n.translations = { es }}); break;
        default: import('./en.json').then(en => {i18n.translations = { en }}); break;

    }
}

export const updateLocale = async (langcode) => {

  i18n.locale=langcode.toString();
  
  switch (i18n.locale.toString().substr(0,2)) {
        case 'en': import('./en.json').then(en => {i18n.translations = { en }}); break;
        case 'ca': import('./ca.json').then(ca => {i18n.translations = { ca }}); break;
        case 'es': import('./es.json').then(es => {i18n.translations = { es }}); break;
        default: import('./en.json').then(en => {i18n.translations = { en }}); break;

    }
}

export default i18n;

【问题讨论】:

  • 你能分享一个语言json文件的样本吗?

标签: reactjs react-native asynchronous async-await internationalization


【解决方案1】:

为了改变文本,必须重新渲染。如果您需要重新加载整个应用程序,您可以使用react-native-restart。这有点粗糙,但它确保了所有组件的完全重新渲染。否则,您可以使用 useState 和 useEffect 挂钩将字符串设置为状态,以便重新呈现文本。像这样:

const [settingScreen, setSettingScreen] = useState(strings('settingsscreen.Language'));

useEffect(()=>{
    setSettingScreen(strings('settingsscreen.Language'))
},[selectedLanguage]);
...
<Text style={styles.maintext}>{settingScreen}</Text>

你也可以使用备忘录:

const settingScreen = useMemo(() => strings('settingsscreen.Language'),[selectedLanguage]);
...
<Text style={styles.maintext}>{settingScreen}</Text>

【讨论】:

  • 感谢 Parsa 的贡献。我找到了另一个解决方案,我将在下面发布
  • 好的。我会有兴趣阅读它。语言更改后重新渲染已经烦了一段时间了。
【解决方案2】:

我找到了解决方案。只需将 i18n.js 更改为:

import * as Localization from 'expo-localization';
import { AsyncStorage } from 'react-native';
import i18n from 'i18n-js';

// Should the app fallback to English if user locale doesn't exists
i18n.fallbacks = true;
i18n.defaultLocale = 'en';
i18n.locale = 'en';

import en from './en';
import es from './es'; 
import ca from './ca';  

i18n.translations = {
  en,
  es,
  ca,
};

// The method we'll use instead of a regular string
export function strings(name, params = {}) {
  return i18n.t(name, params);
};

// Setting the locale to be used on first render
export const loadLocale = async () => {

  //First we check if there is already a selected variable in AsyncStorage

  asyncSelectedLanguage = await AsyncStorage.getItem('LANGUAGE');
  console.log('async language: ' +asyncSelectedLanguage)

  if (asyncSelectedLanguage!==null) {
    i18n.locale = asyncSelectedLanguage;
  } else {
    i18n.locale = Localization.locale;
  }

  
}

export const updateLocale = async (langcode) => {

  i18n.locale=langcode.toString();
  
  
}

export default i18n;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多