react-native-i18n: Android app is not updated when changing the language till you refresh the bundle

So here is what happens with Android:

  • You change the language on your phone settings
  • You go back to the app and you see still the old language (this is not the default case on Android)

On iOS works by the well.

I saw there are some libraries out there to listen for locale changes, restart the app, etc. I think we could include a solution directly here so we have everything in one dependency.

I also tried react-native-restart and it is not actually working for me so I am working in a solution right now. It restarts the app but not the bundle. I think maybe we won’t need to refresh the bundle if we can export some method to the update locale for this library?

Would you accept a PR which such functionality here?

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 18

Most upvoted comments

if you want to follow @ferrannp tutorial you may missed some import So full MainActivity.java will be look like this

import com.facebook.react.ReactActivity;
import android.content.res.Configuration;
import com.facebook.react.ReactInstanceManager;
import android.os.Bundle;

public class MainActivity extends ReactActivity {


 static String currentLocale;

/**
 * Returns the name of the main component registered from JavaScript.
 * This is used to schedule rendering of the component.
 */
@Override
protected String getMainComponentName() {
    return "ServiceNode";
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MainActivity.currentLocale = getResources().getConfiguration().locale.toString();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    String locale = newConfig.locale.toString();
    if (!MainActivity.currentLocale.equals(locale)) {
        MainActivity.currentLocale = locale;
        final ReactInstanceManager instanceManager = getReactInstanceManager();
        instanceManager.recreateReactContextInBackground();
    }
}

}

@milon87 Or just:

yarn add react-native-languages i18n-js
react-native link react-native-languages
import Languages from 'react-native-languages'
import I18n from 'i18n-js'

import en from '../locales/en'
import fr from '../locales/fr'

I18n.locale = Languages.language
I18n.fallbacks = true
I18n.translations = { en, fr }

Languages.addEventListener('change', ({ language }) => {
  I18n.locale = language
})

export default I18n

100% compatible API 😄

EDIT: If you want to memoize the results:

import Languages from 'react-native-languages'
import I18n from 'i18n-js'
import memoize from 'lodash.memoize'

import en from '../locales/en'
import fr from '../locales/fr'

// use JS Map as memoization cache
ld.memoize.Cache = Map

I18n.locale = Languages.language
I18n.fallbacks = true
I18n.translations = { en, fr }

export const t = memoize(I18n.t)
export const l = memoize(I18n.l)
export const p = memoize(I18n.p)

Languages.addEventListener('change', ({ language }) => {
  t.cache.clear()
  l.cache.clear()
  p.cache.clear()

  I18n.locale = language
})

export default { t, l, p }

Hey !

Thanks for your answer, I did not know about that package. So I actually wrote about this https://blog.callstack.io/react-native-handling-language-changes-on-android-the-right-way-c883056a8f5c

And I just fixed my case in the native side. Basically:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    String locale = newConfig.locale.toString();

    if (!MainActivity.currentLocale.equals(locale)) {
        MainActivity.currentLocale = locale;
        final ReactInstanceManager instanceManager = getReactInstanceManager();
        instanceManager.recreateReactContextInBackground();
    }
}

Works well for me 😃. Not sure if we could add this to your package as optional…? Or maybe in the README?

How about changing the language in in-app settings? Should I re-render the whole app? Cause when I navigate back, the language isn’t changed because the scene doesn’t re-render!!

@melaku468 reload your top level component (a state update is enough)

I still didn’t get the exact solution. But, i used react-native-restart to restart the whole app.