455

I'd like to show the current language that the device UI is using. What code would I use?

I want this as an NSString in fully spelled out format. (Not @"en_US")

EDIT: For those driving on by, there are a ton of useful comments here, as the answer has evolved with new iOS releases.

Naresh
  • 16,698
  • 6
  • 112
  • 113
Moshe
  • 57,511
  • 78
  • 272
  • 425
  • 1
    This is built into `NSLocale`. See my answer. – Erik B Jul 24 '13 at 14:15
  • 18
    **iOS9 comment:** pay attention to the fact that for some weird reason, Apple has changed the format returned by `[NSLocale preferredLanguages]`. it used to be separated by underscore (e.g. `en_US`), but now it was changed into a dash: `en-US` – ishahak Aug 06 '15 at 06:53
  • 7
    More on iOS9: Getting [NSLocale preferredLanguages] on a iOS 8.4 simulator versus 9.0 simulator also has discrepancies. On iOS 8.4 it is "en" and iOS 9.0 it is "en-US" – Kris Subramanian Sep 17 '15 at 15:52
  • This comment helped me a lot! We were stuck with a simple issue wondering what went wrong for about 1 hour until I saw your comment. – thandasoru Oct 27 '15 at 09:52
  • 4
    `NSLocale` has methods `componentsFromLocaleIdentifier:` and `localeIdentifierFromComponents:` which are probably the right way to handle the (potentially changeable) format. – Benjohn Feb 09 '16 at 17:26

33 Answers33

830

The solutions provided will actually return the current region of the device - not the currently selected language. These are often one and the same. However, if I am in North America and I set my language to Japanese, my region will still be English (United States). In order to retrieve the currently selected language, you can do:

NSString * language = [[NSLocale preferredLanguages] firstObject];

This will return a two letter code for the currently selected language. "en" for English, "es" for Spanish, "de" for German, etc. For more examples, please see this Wikipedia entry (in particular, the 639-1 column):

List of ISO 639-1 codes

Then it's a simple matter of converting the two letter codes to the string you would like to display. So if it's "en", display "English".

EDIT

Worth to quote the header information from NSLocale.h:

+ (NSArray *)preferredLanguages NS_AVAILABLE(10_5, 2_0); // note that this list does not indicate what language the app is actually running in; the [NSBundle mainBundle] object determines that at launch and knows that information

People interested in app language take a look at @mindvision's answer

Halo
  • 1,730
  • 1
  • 8
  • 31
Dubron
  • 8,661
  • 2
  • 15
  • 10
  • 2
    Exactly what I was looking for. I had the same issue where region is not the same as language. – Jasarien Aug 12 '11 at 08:37
  • 13
    bad answer: returns zh-Hans for chinese, which is not the iso code. – cyrilchampier Aug 27 '12 at 19:21
  • 2
    The first two characters give the country, the stuff after the dash gives the region, the rest is just for narrowing it down further (such as local dialects). zh is listed as the iso code for Chinese. For those looking for a specific language like I was, try the [IANA registry](http://www.iana.org/assignments/language-subtag-registry) – Xono Sep 25 '12 at 05:52
  • This is working in the simulator, but when I use this on my iPhone 5 running iOS 6, it always returns "en" even though I've selected Español as my language, for testing. I've also tried also selecting Mexico as my region, that has no effect. Every time I start the app up it reports "en." Any ideas? – Mason G. Zhwiti Oct 16 '12 at 06:19
  • @MasonG.Zhwiti: I haven't revisited this code since I wrote it back a a couple of years. However, after searching for a few minutes I haven't found any indication that this functionality has changed in iOS6. Without seeing your specific implementation I'm unsure where the issue may be. I hope you were able to track down the source. – Dubron Oct 18 '12 at 21:27
  • Still looking, sadly. It's totally bizarre because it works fine in the simulator, just not on my actual phone. I'll report back if I figure anything out. – Mason G. Zhwiti Oct 19 '12 at 01:26
  • So strange... my code works fine in simulator AND on an iPhone 4 running iOS 6. But on my iPhone 5, it always sees my language as "en." The language change is reflected everywhere else on the phone, except my app. – Mason G. Zhwiti Oct 19 '12 at 21:11
  • Note: British English is en-GB – Wex Nov 29 '12 at 17:32
  • 3
    zh-Hans is the only exception or there are other language codes which differ from the ISO 639-1 standard? – MPaulo Jun 23 '14 at 17:57
  • @Elsint this is the approach that fits my use case. – ToddB Oct 23 '14 at 19:59
  • It seems `[[NSLocale preferredLanguages] objectAtIndex:0]` doesn't work on simulators in Xcode 6.1. I'm having the problem http://stackoverflow.com/questions/26572115/nslocale-preferredlanguages-objectatindex0-always-return-en – S1U Oct 27 '14 at 22:56
  • Just a warning that it's not just Chinese that's a bit different. My device returns en-GB for British English. So you do need to parse the output carefully. – Jamie Brown Nov 08 '14 at 19:41
  • 59
    ***Warning: in iOS 9***, the return value of the `NSLocale preferredLanguages` changed. If before you have been getting "en" only, in iOS 9 you will get "en-US" or "en-JP", etc. Reference: https://happyteamlabs.com/blog/nslocale-preferredlanguages-changes-in-ios-9/ – Dj S Sep 28 '15 at 11:21
  • what is solution for iOS 9? – Mehul Thakkar Oct 29 '15 at 17:42
  • 2
    preferredLanguages amy not return the actual language the phone is set to. See dreamlab's answer: http://stackoverflow.com/a/30293909/555807 – SeanR Dec 18 '15 at 02:38
  • 1
    It is not true, because in Apple documentation there is a note about that method: `// note that this list does not indicate what language the app is actually running in; the [NSBundle mainBundle] object determines that at launch and knows that information` – Bartłomiej Semańczyk Jan 10 '16 at 15:02
  • @MikeRhodes WARNING, PLEASE CHANGE YOUR COMMENT ASAP. This DOES NOT WORK for differentiating Chinese Simplified vs Chinese Traditional. – ninjaneer Aug 07 '16 at 00:47
  • @ajnin I'm not sure what to change my comment to -- if you have a suggestion, let me know and I'll update it. As mentioned a couple of times in this thread, and hinted at in my comment, for differentiating certain things you'll need to poke further down the locale string. – Mike Rhodes Aug 08 '16 at 16:28
  • @MikeRhodes The thread has gotten quite long and this SO question has gotten quite popular. Since your comment is highly upvoted, putting a warning that this doesn't work with Chines languages will help everyone out substantially, even if it's already mentioned in other comments. – ninjaneer Aug 08 '16 at 22:28
  • 1
    Given no one has mentioned this, the returned code is IETF BCP 47 (tools.ietf.org/html/bcp47) so can have various parts beyond the initial two. Often just two chars are needed, so the best thing is: [[[NSLocale preferredLanguages] objectAtIndex:0] substringToIndex:2]. Note that some differentiations require more than the first two characters (e.g., Chinese simplified vs. traditions, English GB vs US). – Mike Rhodes Aug 10 '16 at 11:02
  • How to get the list of supported iOS languages with Country – Anil Sep 23 '19 at 19:51
  • You should use `[NSLocale autoupdatingCurrentLocale]` to reflect the last changes. – Nike Kov Oct 19 '20 at 14:55
292

The selected answer returns the current device language, but not the actual language used in the app. If you don't provide a localization in your app for the user's preferred language, the first localization available, ordered by the user's preferred order, is used.

To discover the current language selected within your localizations use

[[NSBundle mainBundle] preferredLocalizations];

Example:

NSString *language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];

Swift:

let language = NSBundle.mainBundle().preferredLocalizations.first as NSString
murrayc
  • 2,103
  • 4
  • 17
  • 32
mindvision
  • 2,929
  • 1
  • 14
  • 6
  • what if we want to get the entire language name after this? – Shabarinath Pabba Jul 17 '17 at 18:37
  • If you want to get the entire language name from the preferredLocalization, you can use [[NSLocale alloc] initWithLocaleIdentifier:language] (from above). Then you have the locale and can call displayNameForKey. – Vanessa Forney Jan 18 '18 at 09:59
  • Hey it's not working for iOS 14.5, I've set Device Language as Spanish and app is still getting the English language. Don't know why. – Gautam Sareriya Nov 23 '21 at 12:07
92

iOS13, Swift 5+

Locale.preferredLanguages.first

Solution for iOS 9:

NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];

language = "en-US"

NSDictionary *languageDic = [NSLocale componentsFromLocaleIdentifier:language];

languageDic will have the needed components

NSString *countryCode = [languageDic objectForKey:@"kCFLocaleCountryCodeKey"];

countryCode = "US"

NSString *languageCode = [languageDic objectForKey:@"kCFLocaleLanguageCodeKey"];

languageCode = "en"

amir
  • 1,332
  • 8
  • 15
  • 5
    [kCFLocaleLanguageCodeKey](https://github.com/opensource-apple/CF/blob/master/CFLocaleKeys.c#L47) is a defined constant you can use rather than making your own string. – SNyamathi Feb 17 '16 at 06:26
  • 1
    NSLocaleLanguageCode = @"kCFLocaleCountryCodeKey" – dcrow May 12 '19 at 19:56
  • use NSLocaleCountryCode and NSLocaleLanguageCode for @"kCFLocaleCountryCodeKey", @"kCFLocaleLanguageCodeKey", repectively – dcrow May 12 '19 at 19:56
67

This will probably give you what you want:

NSLocale *locale = [NSLocale currentLocale];

NSString *language = [locale displayNameForKey:NSLocaleIdentifier 
                                         value:[locale localeIdentifier]];

It will show the name of the language, in the language itself. For example:

Français (France)
English (United States)
Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
  • 35
    wrong answer: this returns the locale, not the language, which can be different... – cyrilchampier Aug 27 '12 at 19:21
  • 6
    This is definitely wrong, for example if you set the language in the phone settings to English and the Region format to lets say German, Germany, the example above returns "German". Still the phone language is set to English. – jake_hetfield May 23 '13 at 09:17
  • 2
    This is not wrong at all. The locale contains both language and region information. So in @jake_hetfield's example it wouldn't return "German", it would return "English (Germany)". This combined with dreamlab's answer should be the correct answer. – SeanR Dec 18 '15 at 02:32
38

warning The accepted, and the other answers all don't take into account that the preferred language can be another language than the device language.

The device language is the language in which operating system elements and Apple apps are presented.

The preferred language is the language the user would like to have apps localized in. Apple only provides a limited set of translations. If the preferred language is one language Apple translated their apps to, it will also be the device language. However if the user prefers a language for which Apple doesn't provide translations the device and preferred languages won't match. The device language will not be on first position in the preferred languages list.

The following function will go through the preferred languages list and check if there is a translation in the Apple frameworks. The first language to have a translation is the device language. The function will return its language code.

func deviceLanguage() -> String? {
    let systemBundle: NSBundle = NSBundle(forClass: UIView.self)
    let englishLocale: NSLocale = NSLocale(localeIdentifier: "en")

    let preferredLanguages: [String] = NSLocale.preferredLanguages()

    for language: String in preferredLanguages {
        let languageComponents: [String : String] = NSLocale.componentsFromLocaleIdentifier(language)

        guard let languageCode: String = languageComponents[NSLocaleLanguageCode] else {
            continue
        }

        // ex: es_MX.lproj, zh_CN.lproj
        if let countryCode: String = languageComponents[NSLocaleCountryCode] {
            if systemBundle.pathForResource("\(languageCode)_\(countryCode)", ofType: "lproj") != nil {
                // returns language and country code because it appears that the actual language is coded within the country code aswell
                // for example: zh_CN probably mandarin, zh_HK probably cantonese
                return language
            }
        }

        // ex: English.lproj, German.lproj
        if let languageName: String = englishLocale.displayNameForKey(NSLocaleIdentifier, value: languageCode) {
            if systemBundle.pathForResource(languageName, ofType: "lproj") != nil {
                return languageCode
            }
        }

        // ex: pt.lproj, hu.lproj
        if systemBundle.pathForResource(languageCode, ofType: "lproj") != nil {
            return languageCode
        }
    }

    return nil
}

This works if the preferred language list is:

  1. Afrikaans (iOS is not translated into Afrikaans)
  2. Spanish (Device Language)

The preferred language list can be edited in: Settings.app -> General -> Language & Region -> Preferred Language Order


You can than use the device language code and translate it into the language name. The following lines will print the device language in the device language. For example "Español" if the device is set to spanish.

if let deviceLanguageCode: String = deviceLanguage() {
    let printOutputLanguageCode: String = deviceLanguageCode
    let printOutputLocale: NSLocale = NSLocale(localeIdentifier: printOutputLanguageCode)

    if let deviceLanguageName: String = printOutputLocale.displayNameForKey(NSLocaleIdentifier, value: deviceLanguageCode) {
        // keep in mind that for some localizations this will print a language and a country
        // see deviceLanguage() implementation above
        print(deviceLanguageName)
    }
} 
dreamlab
  • 3,321
  • 20
  • 23
  • My understanding is that by initializing your bundle instance with `NSBundle(forClass: UIView.self)` you're trying to provide the most specific language for a given view. However, using this I ran into an issue where for the given class a language was not returned. I changed the initialization to `NSBundle.mainBundle()` and was returned the expected language code. – Pouria Almassi Jan 21 '16 at 23:58
  • Clarification: Initializing the bundle with `mainBundle()` appears to be the one recommended by Apple as suggested in the header for `NSLocale`, `// note that this list does not indicate what language the app is actually running in; the [NSBundle mainBundle] object determines that at launch and knows that information`. – Pouria Almassi Jan 22 '16 at 00:06
  • @Pouria `NSBundle.mainBundle()` returns your app bundle, whereas `NSBundle(forClass: UIView.self)` returns the systems UIKit bundle. the described method looks for directories in the bundle. your app bundle will only contain the ones for the languages you intend to localize to. to determine the device language you will need to check the system bundle. – dreamlab Jan 22 '16 at 10:47
  • 1
    @Pouria the issue might have been that iOS 9 changed the return values from `NSLocale.preferredLanguages()`. i **updated the answer to support iOS 9**. – dreamlab Jan 22 '16 at 11:58
  • @dreamlab unfortunately this approach gives false-positive results when you include 3rd party components, such as pods, with localizations you don't support in project settings. – kokoko Mar 02 '16 at 13:20
  • @kokoko can you please explain why and how? do the pods change the system bundles? – dreamlab Mar 02 '16 at 13:41
  • @dreamlab no, but when I added German for example as one of preferred languages before English in system settings, I launched this test and it fired the last condition, looking for German.lproj in UIKit.framework. My project was not supposed to support german language, there was only english localization. – kokoko Mar 02 '16 at 14:31
  • @kokoko this is correct. this solution returns the device ui language. not your apps language. see second sentence: _The device language is the language in which operating system elements and Apple apps are presented._ – dreamlab Mar 02 '16 at 14:36
  • @dreamlab is there any way to find intersection between supported localizations of app and preferred languages, defined in system settings? – kokoko Mar 02 '16 at 14:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/105159/discussion-between-kokoko-and-dreamlab). – kokoko Mar 02 '16 at 15:36
  • No we are not getting device system language with this. always getting "English" – Bhavesh Lathigara May 13 '21 at 05:04
18

iOS13, Swift 5+, WWDC2019 https://developer.apple.com/videos/play/wwdc2019/403/

Users can select the preferred language of an app independently from the OS language.

You can use these:

    // Returns a list of the user's preferred languages.
    // Maybe more than (or none of) your app supports!
    Locale.preferredLanguages

    // a subset of this bundle's localizations, re-ordered into the preferred order
    // for this process's current execution environment; the main bundle's preferred localizations
    // indicate the language (of text) the user is most likely seeing in the UI
    Bundle.main.preferredLocalizations



    // The current running app language
    Bundle.main.preferredLocalizations.first

    // list of language names this bundle appears to be localized to
    Bundle.main.localizations
norbDEV
  • 4,795
  • 2
  • 37
  • 28
12

i use this

    NSArray *arr = [NSLocale preferredLanguages];
for (NSString *lan in arr) {
    NSLog(@"%@: %@ %@",lan, [NSLocale canonicalLanguageIdentifierFromString:lan], [[[NSLocale alloc] initWithLocaleIdentifier:lan] displayNameForKey:NSLocaleIdentifier value:lan]);
}

ignore memory leak..

and result is

2013-03-02 20:01:57.457 xx[12334:907] zh-Hans: zh-Hans 中文(简体中文)
2013-03-02 20:01:57.460 xx[12334:907] en: en English
2013-03-02 20:01:57.462 xx[12334:907] ja: ja 日本語
2013-03-02 20:01:57.465 xx[12334:907] fr: fr français
2013-03-02 20:01:57.468 xx[12334:907] de: de Deutsch
2013-03-02 20:01:57.472 xx[12334:907] nl: nl Nederlands
2013-03-02 20:01:57.477 xx[12334:907] it: it italiano
2013-03-02 20:01:57.481 xx[12334:907] es: es español
enzoyang
  • 847
  • 4
  • 13
  • 25
12

Translating language codes such as en_US into English (United States) is a built in feature of NSLocale and NSLocale does not care where you get the language codes from. So there really is no reason to implement your own translation as the accepted answer suggests.

// Example code - try changing the language codes and see what happens
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"];
NSString *l1 = [locale displayNameForKey:NSLocaleIdentifier value:@"en"];
NSString *l2 = [locale displayNameForKey:NSLocaleIdentifier value:@"de"];
NSString *l3 = [locale displayNameForKey:NSLocaleIdentifier value:@"sv"];
NSLog(@"%@, %@, %@", l1, l2, l3);

Prints: English, German, Swedish

Erik B
  • 40,889
  • 25
  • 119
  • 135
  • 2
    Actually, you should use [NSLocale autoupdatingCurrentLocale] to initialize your locale instance. That way the language names will be displayed in the users native language. For example Swedish will become Svenska. – Maciej Swic Nov 09 '14 at 13:26
8

Even there's a better way to get current device language. Let's try it by below code -

NSLog(@"Current Language - %@", [[NSLocale preferredLanguages] firstObject]);

Suggested by Abizern on here

Community
  • 1
  • 1
Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
8

I tried to found out the right solution for myself. When I use Locale.preferredLanguages.first was returned the preferred language from your app settings.

If you want get to know language from user device settings, you should the use string below:

Swift 3

let currentDeviceLanguage = Locale.current.languageCode
// Will return the optional String

To unwrap and use look at the line below:

if let currentDeviceLanguage = Locale.current.languageCode {
    print("currentLanguage", currentDeviceLanguage)

    // For example
    if currentDeviceLanguage == "he" {
        UIView.appearance().semanticContentAttribute = .forceRightToLeft
    } else {
        UIView.appearance().semanticContentAttribute = .forceLeftToRight
    }
}
Moshe
  • 57,511
  • 78
  • 272
  • 425
Roman Romanenko
  • 736
  • 9
  • 24
7

You can use the displayNameForKey:value: method of NSLocale:

// get a French locale instance
NSLocale *frLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"] autorelease];

// use it to get translated display names of fr_FR and en_US
NSLog(@"%@", [frLocale displayNameForKey:NSLocaleIdentifier value:@"fr_FR"]);
NSLog(@"%@", [frLocale displayNameForKey:NSLocaleIdentifier value:@"en_US"]);

This will print out:

français (France)
anglais (États-Unis)

If you specify the same locale identifier for the initWithLocaleIdentifier: and also the displayNameForKey:value: method, then it will give you the native name of the language. I've discovered that if you remove the country code and use just fr and en, that it will also omit the country from the display name (on Mac OS X at least, not sure about iOS).

dreamlax
  • 93,976
  • 29
  • 161
  • 209
6

Swift

To get current language of device

NSLocale.preferredLanguages()[0] as String

To get application language

NSBundle.mainBundle().preferredLocalizations[0] as NSString

Note:

It fetches the language that you have given in CFBundleDevelopmentRegion of info.plist

if CFBundleAllowMixedLocalizations is true in info.plist then first item of CFBundleLocalizations in info.plist is returned

Durai Amuthan.H
  • 31,670
  • 10
  • 160
  • 241
5

For getting user device current language use the following it code it worked for me.

NSString * myString = [[NSLocale preferredlanguage]objectAtIndex:0];
Smern
  • 18,746
  • 21
  • 72
  • 90
shailendra
  • 59
  • 1
  • 1
5

If you're looking for preferred language code ("en", "de", "es" ...), and localized preferred language name (for current locale), here's a simple extension in Swift:

extension Locale {
    static var preferredLanguageIdentifier: String {
        let id = Locale.preferredLanguages.first!
        let comps = Locale.components(fromIdentifier: id)
        return comps.values.first!
    }

    static var preferredLanguageLocalizedString: String {
        let id = Locale.preferredLanguages.first!
        return Locale.current.localizedString(forLanguageCode: id)!
    }
}
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Jovan Stankovic
  • 4,661
  • 4
  • 27
  • 16
3

For MonoTouch C# developers use:

NSLocale.PreferredLanguages.FirstOrDefault() ?? "en"

Note: I know this was an iOS question, but as I am a MonoTouch developer, the answer on this page led me in the right direction and I thought I'd share the results.

Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
  • I'm currently using NSLocale.PreferredLanguages and I'm getting an empty array. I assume you've read in the documentation that it may never be empty but I can't see this anywhere? – JFoulkes Apr 17 '12 at 09:36
  • No, honestly that was just an assumption of my own. – Chuck Savage Apr 17 '12 at 16:43
  • @LarryF Watch this video: http://jonas.follesoe.no/2011/07/22/cross-platform-mobile-ndc-2011/ It is very informative on how to structure your code / multi-platform apps. – Chuck Savage Sep 14 '12 at 16:51
3

In Swift:

let languageCode = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode) as? String
lee
  • 7,955
  • 8
  • 44
  • 60
3

Swift 3

let locale = Locale.current
let code = (locale as NSLocale).object(forKey: NSLocale.Key.countryCode) as! String?
print(code!)
Tarik
  • 539
  • 7
  • 16
  • Welcome to Stack Overflow! While this piece of code may answer the question, it is better to include a description of what the problem was, and how your code will tackle the given problem. For the future, here is some information, [how to crack a awesome answer](http://stackoverflow.com/help/how-to-answer) on Stack Overflow. – dirtydanee Jan 17 '17 at 16:49
3

Simple Swift 3 function:

@discardableResult
func getLanguageISO() -> String {
    let locale = Locale.current
    guard let languageCode = locale.languageCode,
          let regionCode = locale.regionCode else {
        return "de_DE"
    }
    return languageCode + "_" + regionCode
}
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
2
-(NSString *)returnPreferredLanguage { //as written text

NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
NSArray *preferredLanguages = [defaults objectForKey:@"AppleLanguages"];
NSString *preferredLanguageCode = [preferredLanguages objectAtIndex:0]; //preferred device language code
NSLocale *enLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"]; //language name will be in English (or whatever)
NSString *languageName = [enLocale displayNameForKey:NSLocaleIdentifier value:preferredLanguageCode]; //name of language, eg. "French"
return languageName;

}
Johnny Rockex
  • 4,136
  • 3
  • 35
  • 55
2

If you want to get only language here is my suggested answer:

NSString *langplusreg = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString * langonly = [[langplusreg componentsSeparatedByString:@"-"] 
objectAtIndex:0];

In my case i just wanted only Locale language not locale region.

Output: If your Locale language is Japanese and locale region is Japan then:

langplusreg = ja-JP

langonly = ja

Danboz
  • 561
  • 1
  • 5
  • 14
2

Obviously, the solutions relying, for example, on

[[NSLocale preferredLanguages] objectAtIndex:0]

usually work fine and return the current device language.

But it could be misleading in some cases :

If the app in which you want to get this value has already changed the language, for example with this kind of code :

NSString *lg = @"en"; // or anything like @"en", @"fr", etc.
[[NSUserDefaults standardUserDefaults] 
    setObject:[NSArray arrayWithObjects:lg, nil]  
    forKey:@"AppleLanguages"]

In this case, [NSLocale preferredLanguages] actually returns the preferred language set (and used) in this particular app, not the current device language !

And... in this case the only way to properly get the actual current device language (and not that previously set in the app), is to firstly clear the key @"appleLanguages" in NSUserDefaults, like this :

[[NSUserDefaults standardUserDefaults]removeObjectForKey:@"AppleLanguages"];

Then, [NSLocale preferredLanguages] now returns the correct value.

Hope this help.

Chrysotribax
  • 789
  • 1
  • 9
  • 17
2

In Swift 4.2 and Xcode 10.1

let language = NSLocale.preferredLanguages[0]
debugPrint(language)//en

In Swift 5.x

let langStr = Locale.current.languageCode
debugPrint(langStr ?? "") //en  el
Naresh
  • 16,698
  • 6
  • 112
  • 113
1

@amir response in Swift :

// Get language prefered by user
let langageRegion = NSLocale.preferredLanguages().first!
let languageDic = NSLocale.componentsFromLocaleIdentifier(langageRegion)
let language = languageDic[NSLocaleLanguageCode]
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
CedricSoubrie
  • 6,657
  • 2
  • 39
  • 44
1

SWIFT-4

 // To get device default selected language. It will print like short name of zone. For english, en or spain, es.

let language = Bundle.main.preferredLocalizations.first! as NSString
print("device language",language)
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
  • Note that this fetches the aggregated list of *available* (supported by the bundle ie you) and *preferred* (by the user) localizations. `NSLocale.preferredLanguages` should return the user's preferred ones without paying respect to what is supported by the bundle. – Jonny Sep 11 '18 at 02:08
1

I actually misread the original question, thought it asked for the "app UI" language (that's what I had googled for), not the "device UI", in which case the best answers would be the ones using preferredLocalizations, but those answers still give you a code, there is one more step to get a nice string to display. So, while the "device UI" language is already answered, if you want to display a nice string for which of the UI languages you support is currently in use, obviously the simplest solution is:

NSLocalizedString(@"currentLanguage", @"")

Where in every one of your UI localizations you have specified it exactly the way you want it shown. E.g. in the en version of your .strings file you'd have:

"currentLanguage"="English";

in your fr version of the .strings file you'd have:

"currentLanguage"="Francais";

etc. No messing with codes etc, you make your own strings to nicely match your UI.

Ecuador
  • 1,014
  • 9
  • 26
0

According to Apple documentation

NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString* preferredLang = [languages objectAtIndex:0];
Max Tymchii
  • 826
  • 8
  • 16
0

Two letters format. Apple uses the ISO standard ISO-3166.

NSString *localeCountryCode = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleCountryCode];
Jakub Truhlář
  • 20,070
  • 9
  • 74
  • 84
0

For Swift 3:

NSLocale.preferredLanguages[0] as String

Bill Chan
  • 3,199
  • 36
  • 32
0

As of iOS 9, if you just want the language code without country code, you'll want this sort of helper function - since the language will contain the country code.

// gets the language code without country code in uppercase format, i.e. EN or DE
NSString* GetLanguageCode()
{
    static dispatch_once_t onceToken;
    static NSString* lang;
    dispatch_once(&onceToken, ^
    {
        lang = [[[NSLocale preferredLanguages] objectAtIndex:0] uppercaseString];
        NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"^[A-Za-z]+" options:0 error:nil];
        NSTextCheckingResult* match = [regex firstMatchInString:lang options:0 range:NSMakeRange(0, lang.length)];
        if (match.range.location != NSNotFound)
        {
            lang = [lang substringToIndex:match.range.length];
        }
    });
    return lang;
}
jjxtra
  • 20,415
  • 16
  • 100
  • 140
0

Updated answer for Swift 4

let language = Bundle.main.preferredLocalizations.first
Md. Ibrahim Hassan
  • 5,359
  • 1
  • 25
  • 45
  • Note that this fetches the aggregated list of *available* (supported by the bundle ie you) and *preferred* (by the user) localizations. `NSLocale.preferredLanguages` should return the user's preferred ones without paying respect to what is supported by the bundle. – Jonny Sep 11 '18 at 02:11
  • I can vouch that the above code works for Swift 5. You would have to do guard or let to quite the warning or preferredLanguages[0]. – Jiraheta Sep 22 '21 at 18:02
0

For Swift 3.0 below code can be used to answer your question:

 let language = Bundle.main.preferredLocalizations.first! as NSString
rak007
  • 973
  • 12
  • 26
Apurv Soni
  • 51
  • 1
  • 5
0

Swift 5.x
Device Language we can get it using Locale.current.languageCode but it would return
en for english,
zh for Chinese-simplified , and
zh for Chinese - traditional

Actually it would more helpful when we will get something like.
zh-Hans for Chinese-simplified , and
zh-Hant for Chinese - traditional

Here zh is language code and Hans is scriptCode.

Solution:

extension Locale {
    
    static var preferredLanguageNScripCodes: [String] {
        Locale.preferredLanguages.compactMap {
            if let scriptCode = Locale(identifier: $0).scriptCode,
               let languageCode = Locale(identifier: $0).languageCode {
                return languageCode + "-" + scriptCode
            }
            return Locale(identifier: $0).languageCode
        }
    }
}

For example: ["zh-Hant", "en", "zh-Hans", "ko", "ja", "es", "de", "it", "fr", "en"]
Ilesh P
  • 3,940
  • 1
  • 24
  • 49
-1

In Swift, there is a way simpler answer to get the current app language:

Locale(identifier: Bundle.main.preferredLocalizations[0]).languageCode!

It could be switched over like this for example:

let supportUrl: URL = {
    switch Locale(identifier: Bundle.main.preferredLocalizations[0]).languageCode {
    case "de":
        return Constants.supportUrlGerman

    default:
        return Constants.supportUrlEnglish
    }
}

I hope this helps!

Jeehut
  • 20,202
  • 8
  • 59
  • 80