AlexanderZaytsev / react-native-i18n

React Native + i18n.js
MIT License
2.18k stars 493 forks source link

Updating I18n language config on first launch #278

Open yotamdahan opened 3 years ago

yotamdahan commented 3 years ago

I'm trying to set the app language by user choice on first app launch.

I have this stack overflow question, but no luck there.

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.clear()
  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 selectLaunched = (value) => {
    setAppLaunched(value);
    onSelect();
  };

  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);
      setSelected(hasLaunched != null);
    } catch (err) {
      setSelected(false);
    }
  };

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

  if (!selected){
    return <CheckIfFirstLaunch onSelect={() => setSelected(true)} />;
  }
  else{
    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="Login">
        <Stack.Screen name="Login" component={Login} />
        <Stack.Screen name="Register" component={Register} />
        <Stack.Screen name="Dashboard" component={Dashboard} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

So far I have managed to display the first launch screen with 2 language options (Hebrew, English). After I choose language the app re-renders and the language remains as default. Only after I proceed to another screen/refresh the screen I can see the language change.

But the component has already re-rendered, so what can cause that?

FayyazAliKhan1 commented 2 years ago

Same issue is appear to me as well, In my case I18n.locale get successfully updated but when I logged out & send user to Sign In screen at first render it is the new language but on second render it changes to default, don't know what's causing this behaviour

atdhetwig commented 2 years ago

Same issue for me too, do you have any solution>??