<commit_before>---
layout: post
title: Preferred languages and iOS 9
---

In iOS 9 Apple introduced some [changes](https://developer.apple.com/library/ios/technotes/tn2418/_index.html#//apple_ref/doc/uid/DTS40016588-CH1-LANGUAGE_IDENTIFIERS_IN_IOS_9) at how NSLocale `+preferredLanguages` returns languages. It returns strings like `en-US`, `ru-RU` instead of `en`, `ru` as it used to. Some (looks like a lot) of developers got confused by that, they reported that behavior as a bug, it even broke some codebases. The sad truth is that if this change breaks your codebase, you used it wrong making false assumptions.

As I've noted in my [previous article]({% post_url 2015-9-22-understanding-ios-internationalization %}), `+preferredLanguages` returns `language ID`s. `Language ID` [is a combination of](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html):

 1. **Required** language designator, like `en` or `ru`.
 2. **Optional** script designator, like `Hans` or `Hant`.
 3. **Optional** region designator like `US` or `RU` or `GB`.

joined by hyphen `-`. These are valid `language IDs`: `en`, `ru`, `en-US`, `en-RU`, `ru-RU`, `zh-Hans`, `zh-Hans-US`, `zh`.

> Even before iOS 9 `+[NSLocale preferredLanguages]` always returned list of valid `language ID`s, the only thing changed is that **since iOS 9 they are most likely include region designator**, for example `en-US`, `ru-RU` vs `en`, `ru`. 

That is, if you expected it to return **not** `language ID`s but language  **designator**-s such as `en` or `ru` (which are at the same time wide range `language ID`s without region designator specified), you, probably, did it wrong even before iOS 9.
To work around this issue or make some fast fixes you may use `+componentsFromLocaleIdentifier:` from `NSLocale`, here is an example of how it could be done:


<!-- language: lang-objc -->
``` objc
NSArray *preferredLanguages = [NSLocale preferredLanguages];

NSLog(@"[NSLocale currentLocale] = %@", [NSLocale currentLocale].localeIdentifier);
NSLog(@"[NSLocale preferredLanguages] = %@", preferredLanguages);

// extracted language designators will go here
NSMutableArray *extractedLanguageDesignators = [NSMutableArray array];<commit_msg>Added more specific details on language id format (it could be vider, but ios and osx supports only described format)<commit_after>---
layout: post
title: Preferred languages and iOS 9
---

In iOS 9 Apple introduced some [changes](https://developer.apple.com/library/ios/technotes/tn2418/_index.html#//apple_ref/doc/uid/DTS40016588-CH1-LANGUAGE_IDENTIFIERS_IN_IOS_9) at how NSLocale `+preferredLanguages` returns languages. It returns strings like `en-US`, `ru-RU` instead of `en`, `ru` as it used to. Some (looks like a lot) of developers got confused by that, they reported that behavior as a bug, it even broke some codebases. The sad truth is that if this change breaks your codebase, you used it wrong making false assumptions.

As I've noted in my [previous article]({% post_url 2015-9-22-understanding-ios-internationalization %}), `+preferredLanguages` returns `language ID`s. In iOS and OS X `Language ID` [is a combination of](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html):

 1. **Required** language designator, like `en` or `ru`.
 2. **Optional** script designator, like `Hans` or `Hant`.
 3. **Optional** region designator like `US` or `RU` or `GB`.

joined by hyphen `-`. These are valid `language IDs`: `en`, `ru`, `en-US`, `en-RU`, `ru-RU`, `zh-Hans`, `zh-Hans-US`, `zh`.

> Even before iOS 9 `+[NSLocale preferredLanguages]` always returned list of valid `language ID`s, the only thing changed is that **since iOS 9 they are most likely include region designator**, for example `en-US`, `ru-RU` vs `en`, `ru`. 

That is, if you expected it to return **not** `language ID`s but language  **designator**-s such as `en` or `ru` (which are at the same time wide range `language ID`s without region designator specified), you, probably, did it wrong even before iOS 9.
To work around this issue or make some fast fixes you may use `+componentsFromLocaleIdentifier:` from `NSLocale`, here is an example of how it could be done:


<!-- language: lang-objc -->
``` objc
NSArray *preferredLanguages = [NSLocale preferredLanguages];

NSLog(@"[NSLocale currentLocale] = %@", [NSLocale currentLocale].localeIdentifier);
NSLog(@"[NSLocale preferredLanguages] = %@", preferredLanguages);

// extracted language designators will go here
NSMutableArray *extractedLanguageDesignators = [NSMutableArray array];
{'fraction_non_alphanumeric': 0.12077811030354853, 'fraction_numerical': 0.012398460880718255, 'mean_word_length': 5.116339869281045, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5519817', 'n_tokens_mistral': 1441, 'n_tokens_neox': 1353, 'n_words': 555}