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

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.

@NonNullpublic 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


You can save all the strings of the default locale in a Map inside a global class, like Application that is executed when launching the app:

public class DualLocaleApplication extends Application {    private static Map<Integer, String> defaultLocaleString;    public void onCreate() {        super.onCreate();        Resources currentResources = getResources();        AssetManager assets = currentResources.getAssets();        DisplayMetrics metrics = currentResources.getDisplayMetrics();        Configuration config = new Configuration(                currentResources.getConfiguration());        config.locale = Locale.ENGLISH;        new Resources(assets, metrics, config);        defaultLocaleString = new HashMap<Integer, String>();        Class<?> stringResources = R.string.class;        for (Field field : stringResources.getFields()) {            String packageName = getPackageName();            int resId = getResources().getIdentifier(field.getName(), "string", packageName);            defaultLocaleString.put(resId, getString(resId));        }        // Restore device-specific locale        new Resources(assets, metrics, currentResources.getConfiguration());    }    public static String getStringInDefaultLocale(int resId) {        return defaultLocaleString.get(resId);    }}

This solution is not optimal, but you won't have concurrency problems.


Thanks to @Khaled Lela answer, I've made a Kotlin extension:

fun Context.getStringByLocale(@StringRes stringRes: Int, locale: Locale, vararg formatArgs: Any): String {    val configuration = Configuration(resources.configuration)    configuration.setLocale(locale)    return createConfigurationContext(configuration).resources.getString(stringRes, *formatArgs)}

And I'm using directly within an Activity, Fragment or Context related classes, just simply calling:

getStringByLocale(R.string.my_text, Locale.UK) or with arguments:

getStringByLocale(R.string.my_other_text, Locale.RU, arg1, arg2, arg3)