get the application's resources languages

It's complicated because even if you have a folder named values-de it doesn't mean you have any resources there. If you have string.xml in values-de it doesn't mean you have string value there.

values:

<resources>
    <string name="app_name">LocTest</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
</resources>

values-de:

<resources>
    <string name="hello_world">Hallo Welt!</string>
</resources>

You can test if a resource for a specific locale is different than the default:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources r = getResources();
Configuration c = r.getConfiguration();
String[] loc = r.getAssets().getLocales();
for (int i = 0; i < loc.length; i++) {
    Log.d("LOCALE", i + ": " + loc[i]);

    c.locale = new Locale(loc[i]);
    Resources res = new Resources(getAssets(), metrics, c);
    String s1 = res.getString(R.string.hello_world);
    c.locale = new Locale("");
    Resources res2 = new Resources(getAssets(), metrics, c);
    String s2 = res2.getString(R.string.hello_world);

    if(!s1.equals(s2)){
        Log.d("DIFFERENT LOCALE", i + ": "+ s1+" "+s2 +" "+ loc[i]);
    }
}

It has one fault - you can check one value whether it has translation.

The dirty code above will print something like:

LOCALE(5667): 51: en_NZ LOCALE(5667): 52: uk_UA LOCALE(5667): 53: nl_BE LOCALE(5667): 54: de_DE DIFFERENT LOCALE(5667): 54: Hallo Welt! Hello world! de_DE LOCALE(5667): 55: ka_GE LOCALE(5667): 56: sv_SE LOCALE(5667): 57: bg_BG LOCALE(5667): 58: de_CH DIFFERENT LOCALE(5667): 58: Hallo Welt! Hello world! de_CH LOCALE(5667): 59: fr_CH LOCALE(5667): 60: fi_FI


AssetManager.getLocales() is actually the way to do this. However, from the public API every AssetManager you create also has the framework resources included in its search path... so when you call AssetManager.getLocales() you will also see any locales that are part of the framework resources. There is no way to get around this with the SDK, sorry.


Inspired by Mendhak's solution I created something a bit cleaner:

    defaultConfig {
        ....

        def locales = ["en", "it", "pl", "fr", "es", "de", "ru"]

        buildConfigField "String[]", "TRANSLATION_ARRAY", "new String[]{\""+locales.join("\",\"")+"\"}"
        resConfigs locales
    }

Then in Java use:

BuildConfig.TRANSLATION_ARRAY

Advatages of this method:

  • Smaller apk - resConfigs will cut out resources from libraries which you don't need (some have hundreds)
  • Fast - No need to parse resource configurations

Tags:

Android