Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to I get the IETF BCP47 Language code in Android API < 21

Is there a clever way to get the BCP47 language code in Android for APIs less than 21? In API level 21+ the Locale.toLanguageTag is exactly what I need. How would you get this in lower API levels?

like image 941
superdave Avatar asked Apr 15 '15 18:04

superdave


People also ask

What does locale specify in Android?

A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user.

What is a device locale?

Device locale - Android Tutorial Locale is the representation of a specific region. Here's the locale for the United States, E-N underscore U-S. En indicates English and US indicates that it's English specifically spoken in the United States. Locales are used on Android to tailor the app to that specific region.

What is getLanguage () in android studio?

As described in Locale reference the best way to get language is: Locale.getDefault().getLanguage() this method returns string with language id according to ISO 639-1 standart.

How do I find device locale?

Using an Application (don't forget to define it in your manifest) we get the default locale when the app starts (onCreate()) and we update it when the user changes the language in the Android settings (onConfigurationChanged(Configuration)). That's all there is.


1 Answers

The good people of Apache Cordova developed a solution for this, as seen here.

I modified there code into the following solution:

/**
 * Modified from:
 * https://github.com/apache/cordova-plugin-globalization/blob/master/src/android/Globalization.java
 * 
 * Returns a well-formed ITEF BCP 47 language tag representing this locale string
 * identifier for the client's current locale
 *
 * @return String: The BCP 47 language tag for the current locale
 */
public static String toBcp47Language(Locale loc) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        return loc.toLanguageTag();
    }

    // we will use a dash as per BCP 47
    final char SEP = '-';
    String language = loc.getLanguage();
    String region = loc.getCountry();
    String variant = loc.getVariant();

    // special case for Norwegian Nynorsk since "NY" cannot be a variant as per BCP 47
    // this goes before the string matching since "NY" wont pass the variant checks
    if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
        language = "nn";
        region = "NO";
        variant = "";
    }

    if (language.isEmpty() || !language.matches("\\p{Alpha}{2,8}")) {
        language = "und";       // Follow the Locale#toLanguageTag() implementation
        // which says to return "und" for Undetermined
    } else if (language.equals("iw")) {
        language = "he";        // correct deprecated "Hebrew"
    } else if (language.equals("in")) {
        language = "id";        // correct deprecated "Indonesian"
    } else if (language.equals("ji")) {
        language = "yi";        // correct deprecated "Yiddish"
    }

    // ensure valid country code, if not well formed, it's omitted
    if (!region.matches("\\p{Alpha}{2}|\\p{Digit}{3}")) {
        region = "";
    }

    // variant subtags that begin with a letter must be at least 5 characters long
    if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}")) {
        variant = "";
    }

    StringBuilder bcp47Tag = new StringBuilder(language);
    if (!region.isEmpty()) {
        bcp47Tag.append(SEP).append(region);
    }
    if (!variant.isEmpty()) {
        bcp47Tag.append(SEP).append(variant);
    }

    return bcp47Tag.toString();
}
like image 128
myanimal Avatar answered Sep 17 '22 21:09

myanimal