Always get ISO 639-2 (three character) language code in iOS?
Asked Answered
S

5

6

I'm working on a project that requires a three letter (ISO 639-2) language code to access a REST service. I was hoping to use the current language setting using [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]. Unfortunately, this method prefers to return two letter (ISO 639-1) language codes. Is there a way I can force NSLocale to return the updated codes, or is there another method I can use to convert a two letter language code to a three letter language code?

Slavism answered 22/6, 2011 at 22:18 Comment(0)
G
6

No, you cannot do that. You have to convert them manually and this is not very simple.

Geer answered 22/6, 2011 at 22:23 Comment(3)
If such a conversion exists, I don't see how it would be any more complex than using a simple mapping table.Kirovograd
depends on the size of the table and the format of the input data, which btw is not quite 639-1Geer
If I understand Apple's documentation correctly, it will return 639-2 codes if a 639-1 code does not exist for the current language. I've found a full list of codes here: loc.gov/standards/iso639-2/php/code_list.php While a lookup table certainly seems possible, it would be tedious and that many string comparisons would be expensive. I really wish they would do it server-side.Slavism
L
8

Check my code at Github for a category on NSLocale to get an ISO 639.2 language code. It is as simple as:

[[NSLocale currentLocale] ISO639_2LanguageIdentifier];
Lupita answered 5/6, 2013 at 20:12 Comment(0)
G
6

No, you cannot do that. You have to convert them manually and this is not very simple.

Geer answered 22/6, 2011 at 22:23 Comment(3)
If such a conversion exists, I don't see how it would be any more complex than using a simple mapping table.Kirovograd
depends on the size of the table and the format of the input data, which btw is not quite 639-1Geer
If I understand Apple's documentation correctly, it will return 639-2 codes if a 639-1 code does not exist for the current language. I've found a full list of codes here: loc.gov/standards/iso639-2/php/code_list.php While a lookup table certainly seems possible, it would be tedious and that many string comparisons would be expensive. I really wish they would do it server-side.Slavism
P
5

It's really basic, but I wrote this class to serve my needs:

class CountryUtilities {
  
  class func getAlphaThreeCode(byAlpha2Code alpha2code: String) -> String? {
    return countries[alpha2code]
  }
  
  private static let countries: [String: String] = [
    "AF": "AFG",
    "AX": "ALA",
    "AL": "ALB",
    "DZ": "DZA",
    "AS": "ASM",
    "AD": "AND",
    "AO": "AGO",
    "AI": "AIA",
    "AQ": "ATA",
    "AG": "ATG",
    "AR": "ARG",
    "AM": "ARM",
    "AW": "ABW",
    "AU": "AUS",
    "AT": "AUT",
    "AZ": "AZE",
    "BS": "BHS",
    "BH": "BHR",
    "BD": "BGD",
    "BB": "BRB",
    "BY": "BLR",
    "BE": "BEL",
    "BZ": "BLZ",
    "BJ": "BEN",
    "BM": "BMU",
    "BT": "BTN",
    "BO": "BOL",
    "BQ": "BES",
    "BA": "BIH",
    "BW": "BWA",
    "BV": "BVT",
    "BR": "BRA",
    "IO": "IOT",
    "BN": "BRN",
    "BG": "BGR",
    "BF": "BFA",
    "BI": "BDI",
    "CV": "CPV",
    "KH": "KHM",
    "CM": "CMR",
    "CA": "CAN",
    "KY": "CYM",
    "CF": "CAF",
    "TD": "TCD",
    "CL": "CHL",
    "CN": "CHN",
    "CX": "CXR",
    "CC": "CCK",
    "CO": "COL",
    "KM": "COM",
    "CG": "COG",
    "CD": "COD",
    "CK": "COK",
    "CR": "CRI",
    "CI": "CIV",
    "HR": "HRV",
    "CU": "CUB",
    "CW": "CUW",
    "CY": "CYP",
    "CZ": "CZE",
    "DK": "DNK",
    "DJ": "DJI",
    "DM": "DMA",
    "DO": "DOM",
    "EC": "ECU",
    "EG": "EGY",
    "SV": "SLV",
    "GQ": "GNQ",
    "ER": "ERI",
    "EE": "EST",
    "SZ": "SWZ",
    "ET": "ETH",
    "FK": "FLK",
    "FO": "FRO",
    "FJ": "FJI",
    "FI": "FIN",
    "FR": "FRA",
    "GF": "GUF",
    "PF": "PYF",
    "TF": "ATF",
    "GA": "GAB",
    "GM": "GMB",
    "GE": "GEO",
    "DE": "DEU",
    "GH": "GHA",
    "GI": "GIB",
    "GR": "GRC",
    "GL": "GRL",
    "GD": "GRD",
    "GP": "GLP",
    "GU": "GUM",
    "GT": "GTM",
    "GG": "GGY",
    "GN": "GIN",
    "GW": "GNB",
    "GY": "GUY",
    "HT": "HTI",
    "HM": "HMD",
    "VA": "VAT",
    "HN": "HND",
    "HK": "HKG",
    "HU": "HUN",
    "IS": "ISL",
    "IN": "IND",
    "ID": "IDN",
    "IR": "IRN",
    "IQ": "IRQ",
    "IE": "IRL",
    "IM": "IMN",
    "IL": "ISR",
    "IT": "ITA",
    "JM": "JAM",
    "JP": "JPN",
    "JE": "JEY",
    "JO": "JOR",
    "KZ": "KAZ",
    "KE": "KEN",
    "KI": "KIR",
    "KP": "PRK",
    "KR": "KOR",
    "KW": "KWT",
    "KG": "KGZ",
    "LA": "LAO",
    "LV": "LVA",
    "LB": "LBN",
    "LS": "LSO",
    "LR": "LBR",
    "LY": "LBY",
    "LI": "LIE",
    "LT": "LTU",
    "LU": "LUX",
    "MO": "MAC",
    "MK": "MKD",
    "MG": "MDG",
    "MW": "MWI",
    "MY": "MYS",
    "MV": "MDV",
    "ML": "MLI",
    "MT": "MLT",
    "MH": "MHL",
    "MQ": "MTQ",
    "MR": "MRT",
    "MU": "MUS",
    "YT": "MYT",
    "MX": "MEX",
    "FM": "FSM",
    "MD": "MDA",
    "MC": "MCO",
    "MN": "MNG",
    "ME": "MNE",
    "MS": "MSR",
    "MA": "MAR",
    "MZ": "MOZ",
    "MM": "MMR",
    "NA": "NAM",
    "NR": "NRU",
    "NP": "NPL",
    "NL": "NLD",
    "NC": "NCL",
    "NZ": "NZL",
    "NI": "NIC",
    "NE": "NER",
    "NG": "NGA",
    "NU": "NIU",
    "NF": "NFK",
    "MP": "MNP",
    "NO": "NOR",
    "OM": "OMN",
    "PK": "PAK",
    "PW": "PLW",
    "PS": "PSE",
    "PA": "PAN",
    "PG": "PNG",
    "PY": "PRY",
    "PE": "PER",
    "PH": "PHL",
    "PN": "PCN",
    "PL": "POL",
    "PT": "PRT",
    "PR": "PRI",
    "QA": "QAT",
    "RE": "REU",
    "RO": "ROU",
    "RU": "RUS",
    "RW": "RWA",
    "BL": "BLM",
    "SH": "SHN",
    "KN": "KNA",
    "LC": "LCA",
    "MF": "MAF",
    "PM": "SPM",
    "VC": "VCT",
    "WS": "WSM",
    "SM": "SMR",
    "ST": "STP",
    "SA": "SAU",
    "SN": "SEN",
    "RS": "SRB",
    "SC": "SYC",
    "SL": "SLE",
    "SG": "SGP",
    "SX": "SXM",
    "SK": "SVK",
    "SI": "SVN",
    "SB": "SLB",
    "SO": "SOM",
    "ZA": "ZAF",
    "GS": "SGS",
    "SS": "SSD",
    "ES": "ESP",
    "LK": "LKA",
    "SD": "SDN",
    "SR": "SUR",
    "SJ": "SJM",
    "SE": "SWE",
    "CH": "CHE",
    "SY": "SYR",
    "TW": "TWN",
    "TJ": "TJK",
    "TZ": "TZA",
    "TH": "THA",
    "TL": "TLS",
    "TG": "TGO",
    "TK": "TKL",
    "TO": "TON",
    "TT": "TTO",
    "TN": "TUN",
    "TR": "TUR",
    "TM": "TKM",
    "TC": "TCA",
    "TV": "TUV",
    "UG": "UGA",
    "UA": "UKR",
    "AE": "ARE",
    "GB": "GBR",
    "US": "USA",
    "UM": "UMI",
    "UY": "URY",
    "UZ": "UZB",
    "VU": "VUT",
    "VE": "VEN",
    "VN": "VNM",
    "VG": "VGB",
    "VI": "VIR",
    "WF": "WLF",
    "EH": "ESH",
    "YE": "YEM",
    "ZM": "ZMB",
    "ZW": "ZWE"
    ]
}
Procto answered 3/9, 2018 at 11:15 Comment(0)
O
2

I needed a similar conversion for ISO 3166-1 countrycodes. iOS gave me the 2-letter code, but I needed the 3 letter code. Here is my solution:

  1. Find a resource file/API to get the ISO countries from. (for example here: https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes/tree/master/all)
  2. Lookup the 2-letter code and convert it to the matching 3-letter code.

Some example code (given you have a iso-countries.json file in the format of lukes GIT project above)

import UIKit 

import CoreTelephony

class CountryCode {

internal var _countries: [String: [AnyHashable: Any]]?
internal var countries: [String: [AnyHashable: Any]]? {
    get {
        if _countries == nil {
            _countries = countriesDictionary()
        }
        return _countries
    }
}

func convertToThreeCharacterCountryCode(twoCharacterCountryCode: String) -> String? {
    let country = countries?[twoCharacterCountryCode.uppercased()]
    return country?["alpha-3"] as? String
}

fileprivate func countriesDictionary() -> [String: [AnyHashable: Any]] {
    var countries = [String: [AnyHashable: Any]]()
    guard let url = Bundle.main.url(forResource: "iso-countries", withExtension: "json") else {
        return countries
    }
    do {
        let data = try Data(contentsOf: url)
        if let dictionaries = try JSONSerialization.jsonObject(with: data, options: []) as? [[AnyHashable: Any]] {
            for countryDictionary in dictionaries {
                if let key = countryDictionary["alpha-2"] as? String {
                    countries[key] = countryDictionary
                }
            }
            return countries
        }
        return countries
    } catch {
        return countries
    }

}
}

You can consider making this a Singleton class, so the countries only have to load once. I did not as I didn't want to keep the countries in memory (in my app this was only needed once during startup).

Opportunism answered 25/2, 2017 at 14:31 Comment(0)
T
-3

In Swift it's as simple as this:

let currentLocale = NSLocale.current as? NSLocale
let code = currentLocale?.iso639_2LanguageCode()
Treat answered 12/12, 2017 at 22:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.