change language programmatically in android

Change Language Programmatically in Android

While developing your awesome application, sometimes you are required to add a feature to change the language of your app on the fly. However, Android OS does not directly support this behaviour. And therefore, you need to solve this situation in some other ways.

Android by default uses the locale of the device to select the appropriate language dependent resources. And most of the time this behaviour is enough for common applications.

However, sometimes there is some business requirements that you need to implement. To do that I will outline the details of changing the language of your application programmatically on the fly.

Here is the appropriate way of changing the locale of the application:

There are some difficulties which you have to overcome to change the language programmatically.

  1. Your application will not remember your language change after it is closed or recreated during the configuration change.
  2. You should update currently visible UI properly according to the selected language.

Solution

“LocaleHelper” is the solution all you need. You just have to initialize locale on your application’s main class. After that all your language changes will persist.

After the recent changes in Android API Version 24(Nougat) we need to override attachBaseContext to reflect changes.

LocaleHelper.javA

if you call onAttach(Context context) constructor it will just set default locale of your device as the default locale of your application.

if you call onAttach(Context context, String defaultLanguage) constructor it will set the given language as the default language of your application for the first time that your application opens. After that you can change your locale by using the buttons or any other method that you provide to your users through your layout.

MainApplication.java

You need to override attachBaseContext and call LocaleHelper.onAttach() to initialize the locale settings in your application.

MAINACTIVITY.java

Here you can find an example activity which has two buttons and three textviews on it to change the locale of the textviews on the fly.

In your activity override attachBaseContext and call LocaleHelper.onAttach(). After that you just need to take care of the activity or fragment which includes the language change buttons. Other activities will not require any modifications at all.

You have two options to update currently visible layout:

  • First, you can just update the text or any other language dependent resources one by one.
  • Second, you can call activity.recreate() to restart currently loaded activity. Then the activity will reload the resources with the correct locale. However, if you select this option your users will notice the affect because it will close your application and you get black screen for a very small amount of time and then recreate your activity again in meanwhile.

Sample Project

For your reference, I added a sample project on github which can be found here. The sample project is targeting Nougat API 25(7.1). You can easily change the target for your needs.

If you have any question regarding to change locale of your android application, feel free to ask.

  • Best solution

    • Safy

      The current solution does not work for Android Nougat

      • Hello Safy, what is not working exactly for your case? I’m adding a sample project targeting Nougat API 25 (7.1) for your information.

        • Andraž Pajtler

          He probably means that context.getResources().updateConfiguration() has been deprecated in Android API 25.

          • @andrapajtler:disqus Thank you for pointing out. I updated the code and sample project to reflect recent changes in Android API.

  • Er B S Choudhary

    thanks for giving post …..it’s only change the textview something …I wan to change keyboard input language …….

    • It is not possible to do that because the virtual keyboard itself is another system application. You can redirect your user to the settings page to let him/her to change the keyboard language by themselves.

  • Kunal Parte

    i m not able to change my application into Hindi and Urdu.
    Please help me with it –Kunal

    • Hello Kunal,

      Please check that your device is supported Hindu language by going “Settings -> Language & Input”.
      If it is not the problem then you need to create a folder called “values-hi” in your “res” folder.

      Then you have to add strings.xml into values-hi folder.

      And then you can apply the codes that i shared here without any problem.

  • Dmitry Suzdalev

    Note that using “Configuration configuration = resources.getConfiguration(); configuration.locale = locale” is wrong, because according to documentation “the returned Configuration object should be treated as read-only”. So you should do “Configuration configuration = new Configuration(resources.getConfiguration());”, i.e. copy it instead.

  • Hello Günhan, I am using your code to change the language setting in my app but somehow the NavigationView does not get rewritten. Do you have any idea why?
    Thanks 🙂

    • I see your problem, it is because you couldn’t update the navigation view itself.

      As i mentioned you can force the activity to recreate itself by using the correct locale however it has a very poor user experience and maybe thats why you didn’t implement that way.

      What you have to do is, you need to find the menu items in your navigationview manually by using the ids that you provided in your menu.xml
      And then you have to reassign textview texts.

      Also another option is, remove the navigationview from the drawer, and then create a new one assign it to the drawer again.

      Or another option is, it is a little bit tricky solution but, just dont use navigationview’s menu, just set your custom headerview, and in that view you manually manage your list of items. And to do that you have to create a recyclerview in which you can easily update the list of items or any other view very easily.

      Thus, i mentioned also in the post the problem is you have to manually update the current view because activity cannot update itself.

      • Thank you, Günhan. We just dropped this feature and let the system decide the best fit for the language 🙂

        • Sumeet

          I also got the same issue.
          As I was changing language from some other activity.
          So on the onResume() method I wrote this code :

          homeActivityBinding.navView.getMenu().clear();
          homeActivityBinding.navView.inflateMenu(R.menu.activity_home_drawer);

          And it worked out.
          I just cleared and inflated menu again.

          Its working really nice.

  • Luthfi

    Hi, I used you LocaleHelper and it works only when we manually update each views’ text after changing language. But it doesn’t work when I used activity.recreate. Locale.getDefault is still correct though, but the string that was received from getResource is wrong.

    Any help?
    Thanks

    • I’ll recreate your situation and check the problem.

    • I tried like this in my activity.

      private void updateViews() {
      recreate();
      }

      and it works. It correctly changes the locale and updates every view on that activity.

      Maybe you somehow disabled/override the “configuration change” on your AndroidManifest or in your activity’s onCreate method.

    • Gonzalo

      A bit late maybe, don’t forget to update your Manifest and add the android:name to application tag, with the same name of the class you created.

  • Sami Özakyol

    Dil seçimini ayarlar activity de yapıyorum bir çok activity bulunuyor uygulamamda kullandığım kodda iç içe activity leri yenilemekle uğraşmamak için, dil değişikliğinden sonra uygulamayı yeniden başlatıyorum. Uygulama kill olmadığı için yeniden başladığında mainapplication kısmı tekrardan çalışmıyor ve dil değişikliği gerçekleşmiyor. Uygulamayı kill ettiğimde bir sonraki açılışta problem kalmıyor. Sorunun çözümü olarak yeniden başlatmadan evvel system.exit(0) komutunu kullandığımda uygulama sonlandığı için sorun oluşmuyor. Sizin tavsiye edebileceğiniz çözüm nedir? teşekkürler.

    • Merhaba Sami,

      Backstack’de bulunan activity’ler resourcelarını önceden yüklediği için bu sorunla karşılaşmanız normal.

      İlk ve en temiz önerim eğer yapabiliyorsanız dil değişim özelliğini uygulamanızın açılış activity’si üzerinde yapmanız. Böylece bir sonra açılacak activity hali hazırda bu değişimden yararlanacaktır.

      İkinci önerim ayarlar activity’niz kapatılırken setResul() ile dil değişliği yapıldığını simgeleyecek bir resultCode set edebilirsiniz. Ve akabinde backstack2den gelecek activitylerin onActivityResult() methodu içerisinde gelen resultCode’u değerlendirip eğer dil değişimi yapmanız gerekiyorsa yine activity.recreate() yapabilirsiniz veya updateViews ile ekran üzerinde çok view bulunmuyorsa bu işlemi manuel gerçekleştirebilirsiniz.

      Uygulama çalışıyorken dil değişikliği yapılması aslında önerilen bir özellik değil ve bir çok uygulamada bu özellik bulunmuyor. Bu sebeple kullanıcı dili değiştirdiğinde uygulamayı kill etmeniz önermeyeceğim bir çözüm olsa da kullanıcıların anlayışla karşılayacağını düşünüyorum.

  • Gonzalo

    You forget to say that “MainApplication” corresponds to the “android:name” property of the tag in Manifest.

  • Sourabh

    Is this a Java project or Android project? I’m trying to change locale on a real-time device using Java. Any suggestions you can provide?

    • This is for Android projects.

  • Simon Hrovatin

    After i call method LocalHelper.setLocal() in my application the activity title (on top of the screen) doesn’t change. Other content is changed OK. If i completly close the apllication and then open it again the title is set correctly. Can you help me fix this problem so that the title will get changed on the fly?

    • Ankush Chugh

      Call recreate() in current older stacked activities also updated in my case.

  • Ankush Chugh

    When Phone rotates the language shifts back to default one, As we know when phone rotates, onConfigurationChanged is called.

    Hence best thing to do is:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    LocaleHelper.onAttach(getBaseContext());
    //update locale and resources, configuration on each config change
    }

    Also you don’t need to override this in each activity just do it in Application class and all done.

  • Muhammad Ahmed AbuTalib

    Hello .

    I downloaded your code and created another activity. When i land on the next activity the language doesn’t change.

    Does that mean i have to put an attachbasecontext on all activities?

    • Hi @muhammadahmedabutalib:disqus,

      Yes, you have to do it for all your activities.
      It is better for you to have a BaseActivity class that you can extend your other activities. And you can do that implementation on your BaseActivity.

      • Muhammad Ahmed AbuTalib

        Gunhan thanks for your reply. I read this late. What i ended up doing was removing the nougat specific code and just using the legacy version.

        When I did that I found out that i needn’t do it in all activities. Its working fine just putting it in the homeactivity.

        Now i am sitting here scared shittless of what might happen and the sideeffects. Do you have any idea how come its working fine?

  • Tarun

    Hey..Just implemented Your class. Its really cool and working fine ’till marshmallow.

    But it is not working NOUGAT!!

    Can you do something for that??

    • Hi @Tarun,

      Have you tried the sample project which is targeted to API 25 (Nougat)?

      • Tarun

        Hey i found the issue. Actually i had to call LocaleHelper.onAttach() in all of my activities inside attachBaseContext method.

        thanks a lot..it’s working fine now.

        One thing that i’m confused about is Location Helper is a static class. Then why do i need to call onAttach again in all of my Activities. I’m sorta confused here. It will be great if you could explain what’s happening here exactly and why do i need to call onAttach in all of my Activities???

        • LocaleHelper is kind of a factory. It returns a new Context based on your locale changes previously. Therefore, without using the newly created (localized) Context. It won’t work. So you need to attach those new context to your activities. It wasn’t like that in the previous version of Android though.

          • Tarun Chauhan

            Thanks a lot for the description. I wonder if we can directly set the locale for whole application instead of calling it every time in all activities. Maybe we could use applicationContext instead of baseContext… :/

          • You should avoid using application context inside your activities because it would have cost you potential memory leaks.

            Just create a BaseActivity and extend your activities from that BaseActivity. And implement this logic on it.

            Take advantage of inheritance right?

          • Tarun Chauhan

            Yeah….exactly….i totally forgot this…this will make it much more easier.. thanks pal ^_^

  • Ashish Tiwari

    I have multiple activities and I am setting data statically and dynamically (from API). I used your code it works good, but sometimes it doesn’t work. It does not change the selected languge. I am restarting only one activity where I am clicking to change the language. Rest activities are setting resources automatically. I only have override attacheBaseContext

    @Override
    protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(LocaleHelper.onAttach(newBase));
    }

    Also implemented Application class code that you specified.

    Please suggest what should I do.

    I am cheking in Android 7.0

  • Maninder Singh

    It is not changing the layout direction according to locale. If I change the language from English to Urdu then the direction does not change to RTL

    • Hi @disqus_YnYOiZn2ls:disqus,

      I updated the the code like you mentioned added support for LayoutDirection.

      By your description and my understanding is that the problem seems you need to reload your current activity layout to be refreshed.

      As I mentioned in the article you could potentially use “activity.recreate()” method. Beware that it will flicker the screen for a second.

  • Joao Neto

    Hi Gunhan, I’m sorry to add another voice to the chorus but I can’t get your solution to work either on Nougat 7.1. I’ve done everything like you posted but instead o changing the labels I do a recreate of my activity. When reloading the activity goes through the attachBaseContext method with the super.attachBaseContext(LocaleHelper.onAttach(base)); but it keeps showing the default labels. Have you tested your solution with the recreate?

    I had tried a similar solution previously but with no success also. I even opened a question on Stackoverflow: https://stackoverflow.com/questions/44554626/android-n-change-locale-in-runtime

    Thanks very much for your help.

    Edit: I actually found the problem. I was using full locale codes like “en_US”. It only works with the two char codes “en”,”fr”, etc

    • Hi @disqus_3S4KUhcukU:disqus

      Just to let you know that this solution is working fine. It’s been used in production apps without any problem. I can assure you.

      I’ve also tried with recreate() of course, and you can check out the example project and see the actual results.

      Documentation says that you should use language parameter as “An ISO 639 alpha-2 or alpha-3 language code”

      • Joao Neto

        Thanks Gunhan. It was after all a bad case of RTFM!

  • Phearun

    Hello Gunhan, is that possible to change the number to its languages? Like 1234567890 to ១២៣៤៥៦៧៨៩០ something like that !
    Best regard.

    • @Phearun Hi,
      The locale changes are done manually, so you can define a string in strings.xml and your language strings.xml then you can achieve it that way.

      values/strings.xml
      12345678
      values-xx/strings.xml
      ១២៣៤៥៦៧៨៩០

      So in your layout or activity you can use it through R.string.telephone_number.

      I might be understood your question wrong but I don’t think any other possible question that you might have asked.

      By the way which language is this?

      • Phearun

        Thank for quick reply.
        In this case, I want to change calendar number language to khmer language as I do SimpleDateFormat (“dd/MMM/yyyy HH:mm:ss a”).
        Ex: 21/Jun/2017 4:05 PM to khmer ២១/មិថុនា/២០១៧ ៤:០៥​ ព្រឹក. Hope you understand my purpose. thanks

        • Hi, SimpleDateFormat takes Locale as argument like so:

          Locale current = new Locale(LocaleHelper.getLanguage(this));
          SimpleDateFormat dateFormat = new SimpleDateFormat(“dd/MMM/yyyy HH:mm:ss a”, current);

          String dateTimeString = dateFormat.format(new Date());

          mAboutTextView.setText(dateTimeString);

          This way you can achieve your goal.

          • Phearun

            Hi Gunhan, i’ve tried your solution and the result is
            21/មិថុនា/2017 21:21:03 ល្ងាច. is it possible to change even number language too?