Amazon Gift Cards

Wednesday, January 28, 2009

Force Localize an Application on Android

Localization has always been a problem in tech at large and products from big companies like Google, Apple and Microsoft are not immune to it and so does Android (I know they came from Google). But one thing that was cool about Android is it was built for developers to localized their apps by default but the problem is that the API or documentation is lacking. If your in a journey to further localize your application, i suggest you to read this page on the official google groups for developers.

As the title stated, you can force your application to be localize on an application basis and not system basis. In this article we would use simplied chinese and english. To do this you have to edit something on your oncreate function on your default activity.

Update for Android 2.0
Add android:configChanges="locale" to your activity nodes on the manifest file
<activity android:name=".Main" android:configChanges="locale" android:label="@string/app_name" />

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;

public class Main extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String languageToLoad  = "cn";
    Locale locale = new Locale(languageToLoad); 
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config, 
    getBaseContext().getResources().getDisplayMetrics());
    this.setContentView(R.layout.main);
  }
}


Quick Explanation
String languageToLoad = "cn";
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);

-- Here we create an new Locale in ch (Simplified Chinese) and set our default locale to a specific locale (See this for more information)

Configuration config = new Configuration();
config.locale = locale;

-- This would create a new Configuration which we would use later and then we change the locale of this configuration with our chinese locale.

getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());

-- This is the core part, here we only update the configuration of our basecontext's resources. I might not be right here but according to the description of Context, Interface to global information about an application environment. Getting the baseContext should be application level.

Source Code
Main.java
main layout
strings.xml in values folder
strings.xml in values-cn folder

Update History
   Jan 17, 2012 - Visual Update

36 comments:

Maxim Yudin said...

Thanks a lot for this article

Wes Corp said...

Works like a charm for me !!!

Thank you.

Cheers,
Wes

Anousak said...

How would you add a new locale for a new build? I have successful build Android 1.5 and now would like to work on my own language localization.
Thanks in advance for your kind suggestions.

Anousak

admin said...

While its not good to stay away from the official way of doing the localization, I would suggest that you could create a function on top of activity to change the app language something like setLocalizeLanguage() . The official way is actually okay but the problem you need to dig in order to find out how to do it. Hope this helps

Max said...

Thanks a lot !!!

EBArtSoft said...

This dont work in Android 2.0
When you do updateConfiguration the app resume in loop.

admin said...

Just add android:configChanges="locale" to your node on the manifest file. :)

Christophe said...

Hi,

thanks for your post. It was very helpful!

However, do you know how (if) I can force the existing activity to reload the strings ?
(I got a "change language" menu, and want the changes to be immediatly visible)

I currently recall setContentView(R.layout.mylayout) but this does not apply to the menu (and I found this method a bit aggressive).

admin said...

hi christophe, grad it helped, what im doing is call finish() and startActivity on the same Activity, while this is more agressive i cant find other solutions as well. Kindly post if you happen to find a better solution, thanks :)

Klaus said...

This don't work in Android 2.0 and Motorola Droid. It works with the Android 2.0 and the Eclipse default build in emulator, but not with the Droid device. I believe, something is wrong with "getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());", maybe a security violation. Or with getBaseContext().getResources().getDisplayMetrics(), hmm....

Here is my good collection of emulators: http://teavuihuang.com/android/

Btw, android:configChanges="locale" node was set on the manifest file.

Cheers!

Klaus

Klaus said...

I do have more informations. It works only, if you set the android:minSdkVersion in the manifest to (Android 1.6) or (Android 2.0). If you build an app for Android 1.5 the dimension of the screen is too small - the buttons size is right, but the font is very small. Does anyone has a solution / workaround?

Thanks!

Klaus

admin said...

Klaus, thanks for the information, be default you should always set the minSdkVersion. On the font problem, have you tried using style and do something like <item name="android:textSize">18sp</item>

chrisonline said...

Is there any solution out there about the to small fonts on Motorola Droid?
I have minSDKVersion 1.5 and on the Droid the fonts are very small....

On my Hero (1.5) there is no problem.
On the emulators for 2.0 and 2.0.1 there is also no problem.

It seems only with the motorola droid ?!?

Adrian Vintu said...

I also got the small fonts issue on the Motorola that chrisonline reported.

I wrote an article with the solution here http://adrianvintu.com/blogengine/post/Force-Locale-on-Android.aspx

BR,
Adrian Vintu

chrisonline said...

Thanks i will try it!

chrisonline said...

Answer for the qeustion "However, do you know how (if) I can force the existing activity to reload the strings ?" :

In the preference screen onLanguageChange i call the method
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

This methods changes the screen orientation to landscape and afterward to SENSOR sensitive.
AND it automatically restarts the app on changing orientation, so all is tranlated in the new selected language.

In the main app onActivityResult i do the same. So the main app also gets restarted.
Works perfect for me so give it a try.

MorrisLiang said...

Hi,I got a problem with the languages...Everything works in the emulator(API1.5).But when I try it on my phone,it doesn't work.
The problem is my phone doesn't have CHINESE locale.And I try calling updateConfiguration(xxx) to swtich to CHINESE.After that,I check the locale by calling getResources().getConfiguration().locale,and all I get is null.This snippet works with languages which the phone supports.
Do you know how to deal with that?I know there is solutions,'cause handcent sms can set to CHINESE in my phone.I just can't figure it out..

MorrisLiang said...

I just find that if I set the locale directly with something like "getResources().getConfiguration().locale=Locale.CHINA",and after I slide out my keyboard causing the orientation changed,the app shows CHINESE.So here's another question:If I use this method to change app's language,how do I change it immediately without sliding out my keyboard.Also,I try calling setRequestedOrientation(xxx) 2 times,but it doesn't work well.

admin said...

Have you tried to call finish() and startActivity on the same Activity, might not be the best solution, but im still looking for solutions as well.

MorrisLiang said...

I don't think finish() and startActivity would solve that odd problem.As I try different potential solutions,and here's what I got:

First,I try to force the locale to be Locale.CHINA with Application Class.And every time when the onCreate() method of the activity(preference activity) was called,it shows that the current locale is "zh_CN",this is nice.But,the app itself remains English.I still have to rotate it before it shows Chinese.
Seems like something should be done before onCreate().Maybe I should check out the android source...

Christophe said...

About "However, do you know how (if) I can force the existing activity to reload the strings ?”

At the end, I added a methode loadLng() in my base class, and I call it after the language change. I use it to set (by hand) all the string of the screen. more work/code, but less agressive/cpu consuming.

Anonymous said...

Thank you, good tutorial.

One question:

The code works properly for my Activity, it loads correctly the corresponding strings and I can see it's correctly updated using getBaseContext().getResources().getConfiguration().locale.getLanguage();

But, if I start another Activity and finish it, when I go back to the original one, getBaseContext().getResources().getConfiguration().locale.getLanguage(); returns the default Locale, not the one I wanted to force. I do this test in the onResume method to decide if I should reload the Activity after coming back from a language configuration activity, but if I always get the same, I cannot take the decission this way.

Thank you.

Anonymous said...

manifest







code snippet

Intent intent = new Intent(this.getApplicationContext(),
AppView.class);
intent.setAction(Intent.ACTION_CONFIGURATION_CHANGED);
startActivity(intent);

Anonymous said...

Hi guys!
I need to get application supported languages, i.e. what localized resources are packaged in .apk programmatically, how it can be done? tnx in advns

Almond said...

Please read the documentations or this post in the official google groups http://groups.google.com/group/android-developers/web/localizing-android-apps-draft

Anonymous said...

You may be interested in tool to translate .strings files. If so check this one http://crowdin.net

easy said...

Recommended new tool: Androlate - An Eclipse plugin which translates your string resources using Google Translate. http://www.cicadalane.com/node/394

Anonymous said...

thanks, works for me

dies said...

Thanks for this article. I always wanted to improve my application through translation. Now I believe your guidance will help me.

> You may be interested in tool to translate .strings files. If so check this one http://crowdin.net


That's just great! Exectly what I was looking for

ProjectJourneyman said...

Thanks for the info on this. I just spent a lot longer than I expected adding the ability to switch languages within my app. It works now though!

There are a few quirks, such as the need to re-apply locale within onCreateOptionsMenu, where it magically gets reset.

Chongtin said...

Thanks for the tutorial. But there is a problem, if the app is killed by the system, the resource create by the application context will change back to the OS's default locality.

The fix is to apply this locality fix to the application level.

Add android:configChanges="locale" to the AndroidManifest Application tag, and extends the Application class. Apply the language hack in
@Override
public void onConfigurationChanged(Configuration newConfig) {
//language hack here.
}.

Anonymous said...

Haii Thank you very much for ur help...

Anonymous said...

Thank you............

In the HELL of Cyber Mania said...

You have mentioned that we need to add the locale in our menifest's file like "android:configChanges="locale",but if i removed this the program still showing ChineseHello like.

In the HELL of Cyber Mania said...

In ur article if we didn't mention in the menifests's file "configchanges="locale"".still the program running with the correct outpur.

venky said...

i wrote total code but languages not changes .... what i do ? even i also i wrote
android:configChanges="locale"