I want to support language change (manually by user). I'm using react-native-i18n for that. I found how to change the displayed language at run time but I didn't find how to update the current view.
Environment:
When I use I18n.locale ='en';
not in function.. just as it is, the text will be in English and when I use I18n.locale ='he';
the text will be in Hebrew.
However I need to change the language at run time. So I want that when I click each button the language will change and will be displayed.
Nothing happened.. I assume I need to reload / re-render / update the view but I didn't find how to.
You can try something like this
<View style={styles.container}>
<Button onPress={this.setLocale()} title={strings('test.b1')}>
</View>
public setLocale() {
this.setState({stateOfLocale: 'en'});
I18n.locale = stateOfLocale;
}
On the page where I have the button or Select to change the language, nothing will happen unless the texts are dependant on the language.
On every string I can pass the locale as an optional parameter like this {I18n.t("email", { locale: language })}
and this will cause a rerender immediately if it changes.
No restart or refresh needed.
In the example below, I am using a select to modify the language in the state. The text field is dependant on it because of the optional locale parameter and will immediately re-render.
To persist the changes, I've implemented a Save button that will save the locale to AsyncStorage and call a changeLanguage function defined in a separate i18n.js file
import React, { useState } from "react";
import { View, Text, Button } from "react-native";
import I18n, { changeLanguage } from "../i18n/i18n";
import RNPickerSelect as Select from 'react-native-picker-select';
import AsyncStorage from '@react-native-async-storage/async-storage';
function ProfileScreen() {
const locale = I18n.currentLocale();
const [language, setLanguage] = useState(locale);
const saveProfile = async () => {
if (locale !== language) {
AsyncStorage.setItem("language", language);
changeLanguage(language);
}
}
return (
<View>
<Text>{I18n.t("email", { locale: language })}</Text>
<Select
value={language}
onValueChange={(value) => setLanguage(value)}
placeholder={I18n.t("selectAppLanguage")}
items={[
{ label: I18n.t("English", { locale: language }), value: "en" },
{ label: I18n.t("Finnish", { locale: language }), value: "fi" },
{ label: I18n.t("Swedish", { locale: language }), value: "se" },
]}
/>
<Button
title={I18n.t("save", { locale: language })}
onPress={saveProfile}
/>
</View>
);
}
export default ProfileScreen;
here is my i18n.js file.
I am using react-native-localize as react-native-i18n is not maintained anymore and creates problems on Android once released.
Changing the language is as simple as I18n.locale = lang
//i18n/i18n.js
import I18n from "i18n-js";
import * as RNLocalize from "react-native-localize";
import en from './languages/en';
import fi from './languages/fi';
import se from './languages/se';
const locales = RNLocalize.getLocales();
if (Array.isArray(locales)) {
I18n.locale = locales[0].languageCode;
}
export const changeLanguage = lang => {
if (lang) {
I18n.locale = lang;
} else if (Array.isArray(locales)) {
I18n.locale = locales[0].languageCode;
}
}
I18n.fallbacks = true;
I18n.translations = {
en,
fi,
se,
};
export default I18n;
One last thing, in App.js, at app start, I am retrieving the language from local storage inside useEffect and overriding the device's language. So language is persisted.
//App.js
import React, { useEffect } from "react";
import I18n, { changeLanguage } from "./src/i18n/i18n";
import AsyncStorage from '@react-native-async-storage/async-storage';
function App() {
useEffect(() => {
const setLanguage = async () => {
const language = await AsyncStorage.getItem("language");
changeLanguage(language)
}
setLanguage()
}, [])
return ( // ...navigation, etc.
);
}
export default <App />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With