How to Get String from Different Locales in Android

how to get string from different locales in Android?

NOTE If your minimum API is 17+, go straight to the bottom of this answer. Otherwise, read on...

NOTE If you are using App Bundles, you need to make sure you either disable language splitting or install the different language dynamically. See https://stackoverflow.com/a/51054393 for this. If you don't do this, it will always use the fallback.

If you have various res folders for different locales, you can do something like this:

Configuration conf = getResources().getConfiguration();
conf.locale = new Locale("pl");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources resources = new Resources(getAssets(), metrics, conf);
String str = resources.getString(id);

Alternatively, you can just restart your activity using the method pointed to by @jyotiprakash.

NOTE Calling the Resources constructor like this changes something internally in Android. You will have to invoke the constructor with your original locale to get things back the way they were.

EDIT A slightly different (and somewhat cleaner) recipe for retrieving resources from a specific locale is:

Resources res = getResources();
Configuration conf = res.getConfiguration();
Locale savedLocale = conf.locale;
conf.locale = desiredLocale; // whatever you want here
res.updateConfiguration(conf, null); // second arg null means don't change

// retrieve resources from desired locale
String str = res.getString(id);

// restore original locale
conf.locale = savedLocale;
res.updateConfiguration(conf, null);

As of API level 17, you should use conf.setLocale() instead of directly setting conf.locale. This will correctly update the configuration's layout direction if you happen to be switching between right-to-left and left-to-right locales. (Layout direction was introduced in 17.)

There's no point in creating a new Configuration object (as @Nulano suggests in a comment) because calling updateConfiguration is going to change the original configuration obtained by calling res.getConfiguration().

I would hesitate to bundle this up into a getString(int id, String locale) method if you're going to be loading several string resources for a locale. Changing locales (using either recipe) calls for the framework to do a lot of work rebinding all the resources. It's much better to update locales once, retrieve everything you need, and then set the locale back.

EDIT (Thanks to @Mygod):

If your minimum API level is 17+, there's a much better approach, as shown in this answer on another thread. For instance, you can create multiple Resource objects, one for each locale you need, with:

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) {
Configuration conf = context.getResources().getConfiguration();
conf = new Configuration(conf);
conf.setLocale(desiredLocale);
Context localizedContext = context.createConfigurationContext(conf);
return localizedContext.getResources();
}

Then just retrieve the resources you like from the localized Resource object returned by this method. There's no need to reset anything once you've retrieved the resources.

Android: How to get string in specific locale WITHOUT changing the current locale

You can use this for API +17

@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static String getStringByLocal(Activity context, int id, String locale) {
Configuration configuration = new Configuration(context.getResources().getConfiguration());
configuration.setLocale(new Locale(locale));
return context.createConfigurationContext(configuration).getResources().getString(id);
}

Update (1) : How to support old versions.

@NonNull
public static String getStringByLocal(Activity context, int resId, String locale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
return getStringByLocalPlus17(context, resId, locale);
else
return getStringByLocalBefore17(context, resId, locale);
}

@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static String getStringByLocalPlus17(Activity context, int resId, String locale) {
Configuration configuration = new Configuration(context.getResources().getConfiguration());
configuration.setLocale(new Locale(locale));
return context.createConfigurationContext(configuration).getResources().getString(resId);
}

private static String getStringByLocalBefore17(Context context,int resId, String language) {
Resources currentResources = context.getResources();
AssetManager assets = currentResources.getAssets();
DisplayMetrics metrics = currentResources.getDisplayMetrics();
Configuration config = new Configuration(currentResources.getConfiguration());
Locale locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
/*
* Note: This (temporarily) changes the devices locale! TODO find a
* better way to get the string in the specific locale
*/
Resources defaultLocaleResources = new Resources(assets, metrics, config);
String string = defaultLocaleResources.getString(resId);
// Restore device-specific locale
new Resources(assets, metrics, currentResources.getConfiguration());
return string;
}

Update (2): Check this article

Get a string from another locales string.xml file

Let's assume you have a <string name="hello">Hello</string> inside your values/strings.xml, which also has a translation (say French) inside values-fr/strings.xml <string name="hello">Bonjour</string>. Normally you'd do the following:

String s = getResources.getString(R.string.hello); // s: "Hello"

To get the "Bonjor" string you'd have to create an alternative resources instance and use it to access the French string by changing to appropirate Locale:

Resources normalResources = getResources();
AssetManager assets = normalResources.getAssets();
DisplayMetrics metrics = normalResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = Locale.FRENCH;
Resources frenchResources = new Resources(assets, metrics, config);

String s = defaultResources.getString(R.string.hello); // s: "Bonjour"

Hope this helps.

Get string from default locale using string in specific locale

You have to identify the element by something else, like an id, or even the English Name.

It is not possible to get the original string for a given localized string. One of the reason is that localization of strings is not a transitive function, but there are many other reasons why this is not a good direction.

Get String From Different Values Folder in Android


Locale locale = new Locale("cn");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());

http://developer.android.com/guide/topics/resources/localization.html



Related Topics



Leave a reply



Submit