30

I have an Android application with English strings in values/strings.xml. For each string in that file, I have an entry in values-ja/strings.xml with the Japanese translation of that string. If I set the emulator, a Nexus One or Nexus S to Japanese, the UI shows Japanese text throughout. Most of the time.

Sometimes, some portion of the UI will appear in English, even though the current locale is ja-JP. For instance, I wrote this test code in the onCreate() method of one of my activities:

Log.e(TAG, "Default locale = '" + Locale.getDefault().toString() + "'");
Log.e(TAG, "My string = '" + getResources().getString(R.string.my_string) + "'");

Sometimes I will see in LogCat:

Default locale is 'ja_JP'
My string is '日本'

Other times I will see:

Default locale is 'ja_JP'
My string is 'English'

Sometimes this issue is resolved by rotating the phone. Sometimes it's resolved by exiting and restarting the app. Sometimes only a portion of a single screen is in English. Sometimes this issue occurs with strings that are pulled out of the resources via code, and sometimes it occurs with strings that are only referenced by a layout. Nowhere in my application do I call Locale.setDefault(), so that's not causing the issue.

UPDATE

I've found a way to correct the issue for a specific activity. In that activity's onCreate():

Log.e(TAG, "getString: '" + getString(R.string.my_string) + "'");
Log.e(TAG, "getResources().getConfiguration(): '" +
      getResources().getConfiguration().toString() + "'");
Log.e(TAG, "getResources().getDisplayMetrics(): '" +
      getResources().getDisplayMetrics().toString() + "'");

Log.e(TAG, "Setting configuration to getConfiguration()");
getResources().updateConfiguration(getResources().getConfiguration(),
     getResources().getDisplayMetrics());

Log.e(TAG, "getString: '" + getString(R.string.my_string) + "'");
Log.e(TAG, "getResources().getConfiguration(): '" +
      getResources().getConfiguration().toString() + "'");
Log.e(TAG, "getResources().getDisplayMetrics(): '" +
      getResources().getDisplayMetrics().toString() + "'");

This results in the following in LogCat:

getString: 'English'
getResources().getConfiguration(): '{ scale=1.0 imsi=0/0 loc=ja_JP touch=3 keys=1/1/2 nav=3/1 orien=1 layout=34 uiMode=17 seq=8}'
getResources().getDisplayMetrics(): 'DisplayMetrics{density=1.5, width=480, height=800, scaledDensity=1.5, xdpi=254.0, ydpi=254.0}'
Setting configuration to getConfiguration()
getString: '日本'
getResources().getConfiguration(): '{ scale=1.0 imsi=0/0 loc=ja_JP touch=3 keys=1/1/2 nav=3/1 orien=1 layout=34 uiMode=17 seq=8}'
getResources().getDisplayMetrics(): 'DisplayMetrics{density=1.5, width=480, height=800, scaledDensity=1.5, xdpi=254.0, ydpi=254.0}'

As you can see from the log, nothing in the current configuration changes, but getString() gives different results.

It's impractical to use this workaround in every place in my application where a resource might be used, but hopefully this provides a hint about what's going wrong.

Bob Whiteman
  • 2,481
  • 2
  • 23
  • 27
  • Have you tried the google android bug tracker? http://code.google.com/p/android/issues/ – Sebastian Roth Feb 11 '11 at 04:54
  • what version of the AVD are you using ? – rockeye Feb 11 '11 at 14:33
  • I looked through every defect in the bug tracker that contains "language" or "locale". I didn't see anyone else reporting this issue. – Bob Whiteman Feb 11 '11 at 20:34
  • As far as I know I'm using the latest version of the emulator and SDK tools.. I believe that's 9.0.0.20110119.etcetc. – Bob Whiteman Feb 11 '11 at 20:38
  • Can you share the layout XML for one of the views that has this problem? If not the whole thing, perhaps the header and one of the elements where this is exhibited. Do you have locale-specific layouts for these pages or do you just use the layout/main.xml? I'm curious if there is some attribute of your layout that is causing the string search mechanism to eliminate values-ja-rJP/strings.xml for those elements. Either directly or by inference. – Eric Cloninger Feb 12 '11 at 16:21
  • I don't think the layout XML is relevant because the issue affects calls directly to getString(). The application does not have locale-specific layout XML files. – Bob Whiteman Feb 14 '11 at 19:22
  • I believe the `Locale` is changed for this thread somewhere else in the code. If you can reproduce while writing everything on a single Log message (or after adding a `synchronize` block), it means you have a AVD or Android bug. – rds Mar 06 '11 at 00:07
  • Have you solved this issue? I am facing the same problem and do not what to do. – shelll Nov 21 '12 at 09:02
  • I haven't, @shelll. In fact, I've moved off the product, and the new development team that took over hasn't been able to solve the issue either. – Bob Whiteman Jan 03 '13 at 22:14
  • We're having the same problem with our app, except the strings are never in the correct Japanese locale. They are always in English. Our strings.xml is translated under values-ja. – Jeff Lockhart Jun 27 '18 at 20:58

3 Answers3

2

This is just a theory but you could be leaking a Context. Basically, the old activity might be reporting the string values rather than the newly created on.

A way to test this is:

  1. Change TAG to a member variable (NOT STATIC!).
  2. OnCreate, set TAG = this.toString(), this will put the memory address of the activity as the tag.
  3. Have the activity print out stuff using the initial locale.
  4. Do whatever to change the locale. This should (never verified this) restart the activity and you get a new activity. If you do. THen look at the log and see if the memory address is changing for the tag. If the memory address is the same as before the context was leaked.
Jeremy Edwards
  • 14,620
  • 17
  • 74
  • 99
  • I tried a slightly different method: I put a breakpoint on the getString() call which is in the onCreate() method of an Activity. I look at the value of this, which is the Activity (which is also the context). It's different each time. I don't think this is the cause of the problem. – Bob Whiteman Apr 29 '11 at 22:32
0

Are you changing Locale while the application is running? If so, have you properly implemented the various elements of the Activity lifecycle (including onSaveInstanceState() and onRestoreInstanceState())?

According to http://developer.android.com/guide/topics/resources/runtime-changes.html, a change in configuration at runtime should cause the Activity to be destroyed & restarted. It sounds like your app is noticing the new configuration but is not restarting properly (until restarting the whole App, or changing orientation).

Are you doing anything funky in onSaveInstanceState or onDestroy?

P.s. If it corrects itself only on certain orientation changes, can you advise if those orientation changes occur on layouts that have different vertical & horizontal layout files?

Farray
  • 8,290
  • 3
  • 33
  • 37
  • I was concerned about activity life cycle as well. I put Log.e() statements on each onCreate() and onDestroy(). When you change language in the settings, the operating system destroys and re-creates your activities automatically. None of our onSaveInstanceState() implementations do anything except for one that saves a local log file. – Bob Whiteman Feb 14 '11 at 22:12
  • Speaking of life cycle, the application contains both native code and a background service. I don't believe these should affect the resources, though. – Bob Whiteman Feb 14 '11 at 22:14
  • The application doesn't declare any android:configChanges clauses in the AndroidManifest.xml, so handling of config changes is automatic. The application doesn't have different layout files for different orientations. – Bob Whiteman Feb 14 '11 at 22:26
  • Bummer. I was hoping it was a one-off where something was going on in those. I'll have to ponder further. – Farray Feb 14 '11 at 23:00
0

I faced the same issue.

For me, I was trying to get the string (in the onCreate()) before importing language settings from shared preferences (done in the onResume()).

user2342558
  • 5,567
  • 5
  • 33
  • 54