2

There are many exceptions when dealing with locals, therefore I thought it would be nice to use the system Locale.getAvailableLocales() to list all the locals available for the device.

But I do not provide translations for all the locals, therefore I want to find a method that will give me only the locals for which a specific string resource is available(Ex: R.strings.welcome).

How can it be done?

Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216

1 Answers1

0

Edited:

I think loop-and-find string resource is one of the answer.

List<Pair<Locale, String>> stringLocals = getAvailableLocales(R.string.example);

method is:

private List<Pair<Locale, String>> getAvailableLocales(@StringRes int example) {
    List<Pair<Locale, String>> results = new ArrayList<>();
    Locale[] locales = Locale.getAvailableLocales();

    for (Locale locale : locales) {
        if (isLocaleStringAvailable(example, locale)) {
            String string = getLocaleString(example, locale);
            results.add(new Pair<Locale, String>(locale, string));
        }
    }

    return results;
}

But it seems that it is not so fast, because there is so many locales to loop (over 600). Therefore, use this settings to prevent too many loops.

defaultConfig {

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

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

https://stackoverflow.com/a/45884682/850347


You can use this code for get strings by locale:

List<String> strings = getAvailableStrings(Locale.KOREA);

And methods are:

private List<String> getAvailableStrings(Locale locale) {
    List<Integer> stringIds = getAllStringIds();
    List<String> strings = getAllStrings();

    List<String> results = new ArrayList<>();

    for (int i = 0; i < stringIds.size(); i++) {
        boolean result = isLocaleStringAvailable(stringIds.get(i), locale);
        if (result == true) {
            results.add(strings.get(i));
        }
    }

    return results;
}

private List<Integer> getAllStringIds() {
    Field[] fields = R.string.class.getFields();
    List<Integer> ids = new ArrayList<>();
    for (int i = 0; i < fields.length; i++) {
        try {
            int resno = fields[i].getInt(null);
            ids.add(resno);
        } catch (IllegalAccessException e) {
            // Catch exception
        }
    }
    return ids;
}

private List<String> getAllStrings() {
    Field[] fields = R.string.class.getFields();
    List<String> ids = new ArrayList<>();
    for (int i = 0; i < fields.length; i++) {
        String res = fields[i].getName();
        ids.add(res);
    }
    return ids;
}

private boolean isLocaleStringAvailable(@StringRes int id, Locale locale) {
    String globalString = getLocaleString(id, Locale.ENGLISH); // Modify if your default language is not english.
    String localeString = getLocaleString(id, locale);
    return !globalString.equalsIgnoreCase(localeString);
}

public String getLocaleString(@StringRes int id, Locale locale) {
    Configuration conf = getResources().getConfiguration();
    conf.locale = locale;
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    Resources resources = new Resources(getAssets(), metrics, conf);
    return resources.getString(id);
}
Stanley Ko
  • 3,383
  • 3
  • 34
  • 60