I'm going to add localization to our application...
I know Android to its core, but I haven't used localization before, (never needed to).
So I'm so thrilled to start this new journey, and be able to share my insights...
Given the fact that I'm a critic, this should be joyful :)
So here I go:
If I've got the basic correct, then:
- If you want to target a specific locale, your values folder containing the strings.xml should be 'values-xx-rYY', note that the locale region referred in the specs is with underscore, while the values folder MUST NOT have underscores in them.
- If you want to target a group of locales, and by group I mean locales which fits 'xx_*', then your values folder should be 'values-xx'.
First you would like to know which are the available languages, I've got it from
here:
(I have no idea how credible the data is, but it is a start)
Arabic, Egypt (ar_EG)
Arabic, Israel (ar_IL)
Bulgarian, Bulgaria (bg_BG)
Catalan, Spain (ca_ES)
Czech, Czech Republic (cs_CZ)
Danish, Denmark(da_DK)
German, Austria (de_AT)
German, Switzerland (de_CH)
German, Germany (de_DE)
German, Liechtenstein (de_LI)
Greek, Greece (el_GR)
English, Australia (en_AU)
English, Canada (en_CA)
English, Britain (en_GB)
English, Ireland (en_IE)
English, India (en_IN)
English, New Zealand (en_NZ)
English, Singapore(en_SG)
English, US (en_US)
English, South Africa (en_ZA)
Spanish (es_ES)
Spanish, US (es_US)
Finnish, Finland (fi_FI)
French, Belgium (fr_BE)
French, Canada (fr_CA)
French, Switzerland (fr_CH)
French, France (fr_FR)
Hebrew, Israel (he_IL)
Hindi, India (hi_IN)
Croatian, Croatia (hr_HR)
Hungarian, Hungary (hu_HU)
Indonesian, Indonesia (id_ID)
Italian, Switzerland (it_CH)
Italian, Italy (it_IT)
Japanese (ja_JP)
Korean (ko_KR)
Lithuanian, Lithuania (lt_LT)
Latvian, Latvia (lv_LV)
Norwegian-Bokmol, Norway(nb_NO)
Dutch, Belgium (nl_BE)
Dutch, Netherlands (nl_NL)
Polish (pl_PL)
Portuguese, Brazil (pt_BR)
Portuguese, Portugal (pt_PT)
Romanian, Romania (ro_RO)
Russian (ru_RU)
Slovak, Slovakia (sk_SK)
Slovenian, Slovenia (sl_SI)
Serbian (sr_RS)
Swedish, Sweden (sv_SE)
Thai, Thailand (th_TH)
Tagalog, Philippines (tl_PH)
Turkish, Turkey (tr_TR)
Ukrainian, Ukraine (uk_UA)
Vietnamese, Vietnam (vi_VN)
Chinese, PRC (zh_CN)
Chinese, Taiwan (zh_rTW)
Next thing you would like to do, is be able to switch the languages dynamically.
Why? Simply because it would take far less time to evaluate each screen while switching languages, and been able to see the twigging each causes.
To do that you will first need to
distinct whether the application runs in debug mode, or in production...
What I've done, is added a menu while running in debug, then launched a dialog for choosing the language I want to display.
A code snippet for changing the Locale:
Resources res = getApplicationContext().getResources();
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = newLocale;
res.updateConfiguration(conf, dm);
Afterwards I've tried to dismiss the dialog which for some weird reason it did not work... but
I've found the solution for it.
The last part is rendering the UI... That was one of the biggest hacks I faced!
I'll start of and say that in order to render the UI without writing 10 TONs of code, you should(I think MUST) have a parenting layer of, Application, BaseActivity, BaseFragment, BaseDialogFragment, and so on...
Since the only way (I could find) to check if the locale had change within an activity, in its onResume you need to compare the Context.getResources().getConfiguration().locale, with a value which you save on each onResume, in your BaseActivity, this value I believe can be static.
Once you've recognize a change in the locale, there are a couple of approaches you can and need to take:
- You can refresh your activity with its intent. (Re-launch the activity and close the current one)
- You can refresh your activity manually. (Rener the views one by one)
- If you are using a ViewPager, make sure you are setting its adapter via Handler.post(...), otherwise you might get a 'Recursive entry to executePendingTransactions' error.
- Since I'm loading all my fragment dynamically, after an activity has gone to background, e.g. the onSaveInstanceState was called on the fragments, I could not commit the new changes to the FragmentTransaction, I had to use the commitAllowingStateLoss.
And I was done...
All took less then a day, there is no greater satisfaction then to see the languages changes live in front of your eyes!
Good luck...
(I'm going to number these as I think there are going to be more then one... prof is in the comments :))
NOTES:
- Since Android 4.2 the API to change the Device's Locale has been disabled for non-os-signature applications, so all the Locale changing apps are DOOMED...