Use Case: Logging error messages as displayed to the user.
However you don't want to have messages in your log that depend on the locale of the user's device. On the other hand you don't want to change the locale of the user's device just for your (technical) logging. Can this be achieved? I found a couple of potential solutions here on stackoverflow:
However, they all result in changing the locale of my device (until the next configuration change).
Anyway, my current workaround is like so:
public String getStringInDefaultLocale(int resId) { Resources currentResources = getResources(); AssetManager assets = currentResources.getAssets(); DisplayMetrics metrics = currentResources.getDisplayMetrics(); Configuration config = new Configuration( currentResources.getConfiguration()); config.locale = DEFAULT_LOCALE; /* * Note: This (temporiarily) 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; }
To be honest, I don't like this approach at all. It's not efficient and - thinking about concurrency and all that - it might result in some view in the "wrong" locale.
So - Any ideas? Maybe this could be achieved using ResourceBundles, just like in standard Java?
Localizing Strings In order to localize the strings used in your application , make a new folder under res with name of values-local where local would be the replaced with the region. Once that folder is made, copy the strings. xmlfrom default folder to the folder you have created. And change its contents.
Internationalization (i18n) is the engineering effort to make a product — an app in our case — ready for localization, i.e. adaptation to different regions. It includes important simplifications in the source code needed to avoid individual changes when entering foreign markets.
You'll find this screen either in the System Settings app: Languages, or System Settings: System: Languages and input. The Language preference screen should contain one entry called “English (Europe)”. Click Add language and add a fallback language.
Go to app > res > values > right-click > New > Value Resource File and name it as strings. Now, we have to choose qualifiers as Locale from the available list and select the language as Hindi from the drop-down list.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With