Получить текущий язык устройства в iOS?

431

Я хотел бы показать текущий язык, который использует пользовательский интерфейс устройства. Какой код я бы использовал?

Я хочу это как NSStringполностью изложенный формат. (Не @ "en_US")

РЕДАКТИРОВАТЬ: Для тех, кто проезжает мимо, здесь есть множество полезных комментариев, поскольку ответ эволюционировал с новыми выпусками iOS.

Моше
источник
1
Это встроено в NSLocale. Смотри мой ответ.
Эрик Б,
15
Комментарий iOS9: обратите внимание на тот факт, что по какой-то странной причине Apple изменила формат, который возвращает [NSLocale preferredLanguages]. Раньше его разделяли подчеркиванием (например en_US), но теперь оно было изменено на тире:en-US
Ишахак
7
Подробнее о iOS9: получение [NSLocale предпочитаемых языков] на симуляторе iOS 8.4 против симулятора 9.0 также имеет несоответствия. На iOS 8.4 это «en», а на iOS 9.0 - «en-US»
Крис Субраманян
Этот комментарий мне очень помог! Мы застряли с простой проблемой, задаваясь вопросом, что пошло не так в течение приблизительно 1 часа, пока я не увидел ваш комментарий.
thandasoru
3
NSLocaleимеет методы componentsFromLocaleIdentifier:и localeIdentifierFromComponents:, вероятно, является правильным способом обработки (потенциально изменяемого) формата.
Бенджон

Ответы:

808

Предоставленные решения фактически возвращают текущий регион устройства, а не текущий выбранный язык. Это часто одно и то же. Однако, если я нахожусь в Северной Америке и установил свой язык на японский, моим регионом все равно будет английский (США). Чтобы восстановить выбранный в данный момент язык, вы можете сделать:

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

Это вернет двухбуквенный код для текущего выбранного языка. «en» для английского, «es» для испанского, «de» для немецкого и т. д. Дополнительные примеры см. в этой записи в Википедии (в частности, столбец 639-1):

Список кодов ISO 639-1

Тогда нужно просто преобразовать двухбуквенные коды в строку, которую вы хотите отобразить. Так что, если это «en», выведите «English».

Надеюсь, это поможет кому-то, кто хочет отличить регион от выбранного языка.

РЕДАКТИРОВАТЬ

Стоит процитировать информацию заголовка из 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

Люди, интересующиеся языком приложения, смотрят на ответ @ mindvision

Dubron
источник
2
Именно то, что я искал. У меня была такая же проблема, когда регион не совпадает с языком.
Jasarien
12
плохой ответ: возвращает zh-Hans для китайского языка, который не является ISO-кодом.
cyrilchampier
2
Первые два символа обозначают страну, материал после тире - регион, а остальные - только для его сужения (например, местные диалекты). ZH указан как ISO-код для китайского языка. Для тех, кто ищет конкретный язык, как я, попробуйте реестр IANA
Xono
3
zh-Hans - единственное исключение или есть другие языковые коды, которые отличаются от стандарта ISO 639-1?
MPaulo
57
Внимание: в iOS 9 возвращаемое значениеNSLocale preferredLanguagesизменено. Если до этого вы получали только «en», в iOS 9 вы получите «en-US» или «en-JP» и т. Д. Ссылка: happyteamlabs.com/blog/…
Dj S
281

Выбранный ответ возвращает текущий язык устройства, но не фактический язык, используемый в приложении. Если вы не предоставляете локализацию в своем приложении для предпочтительного языка пользователя, используется первая доступная локализация, упорядоченная в соответствии с предпочтительным порядком пользователя.

Чтобы узнать текущий язык, выбранный в вашей локализации, используйте

[[NSBundle mainBundle] preferredLocalizations];

Пример:

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

Swift:

let language = NSBundle.mainBundle().preferredLocalizations.first as NSString
mindvision
источник
Отлично, это то, что меня также интересовало. Проверено и работает правильно!
smileyborg
5
идеально! это позволяет мне создавать локализованные пути к удаленным ресурсам только с теми языками, которые мое приложение поддерживает в предпочтительном порядке.
Евгений Дубинин
что если мы хотим получить полное название языка после этого?
Шабаринатх Пабба
Если вы хотите получить полное имя языка из предпочитаемой локализации, вы можете использовать [[NSLocale alloc] initWithLocaleIdentifier: language] (сверху). Тогда у вас есть локаль и вы можете вызвать displayNameForKey.
Ванесса Форни
87

Решение для iOS 9:

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

language = "en-US"

NSDictionary *languageDic = [NSLocale componentsFromLocaleIdentifier:language];

languageDic будет иметь необходимые компоненты

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

countryCode = "США"

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

languageCode = "en"

эмир
источник
5
kCFLocaleLanguageCodeKey - это определенная константа, которую вы можете использовать вместо создания собственной строки.
SNyamathi
1
NSLocaleLanguageCode = @ "kCFLocaleCountryCodeKey"
ворона
используйте NSLocaleCountryCode и NSLocaleLanguageCode для @ "kCFLocaleCountryCodeKey", @ "kCFLocaleLanguageCodeKey", соответственно
ворона
65

Это, вероятно, даст вам то, что вы хотите:

NSLocale *locale = [NSLocale currentLocale];

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

Он покажет название языка, на самом языке. Например:

Français (France)
English (United States)
Филипп Лейбер
источник
31
неправильный ответ: это возвращает язык, а не язык, который может быть другим ...
cyrilchampier
4
Это определенно неправильно, например, если вы установили язык в настройках телефона на английский, а формат Region - на немецкий, Германия, в приведенном выше примере возвращается «немецкий». Тем не менее язык телефона установлен на английский.
jake_hetfield
2
Это совсем не так. Локаль содержит информацию о языке и регионе. Таким образом, в примере @ jake_hetfield он не будет возвращать «немецкий», он будет возвращать «английский (Германия)». Это в сочетании с ответом Dreamlab должно быть правильным ответом.
SeanR
36

предупреждениеВсе принятые и другие ответы не учитывают, что предпочтительным языком может быть язык, отличный от языка устройства .

Язык устройства - это язык, на котором представлены элементы операционной системы и приложения Apple.

Предпочтительный язык является языком пользователь хотел бы иметь приложение , локализованное в. Apple , предоставляет только ограниченный набор переводов. Если предпочтительным языком является один язык, на который Apple перевела свои приложения, это также будет язык устройства. Однако, если пользователь предпочитает язык, для которого Apple не предоставляет переводы, устройство и предпочтительные языки не будут совпадать . Язык устройства не будет на первой позиции в списке предпочтительных языков.

Следующая функция просматривает список предпочитаемых языков и проверяет, есть ли перевод в платформах Apple. Первый язык для перевода - это язык устройства. Функция вернет свой код языка.

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
}

Это работает, если список предпочитаемых языков:

  1. Африкаанс (iOS не переводится на африкаанс)
  2. Испанский (язык устройства)

Список предпочитаемых языков можно редактировать в : Settings.app -> Общие -> Язык и регион -> Порядок предпочтительных языков


Вы можете использовать код языка устройства и перевести его на название языка. В следующих строках будет напечатан язык устройства на языке устройства. Например, «Español», если устройство настроено на испанский.

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
источник
Насколько я понимаю, инициализируя свой экземпляр пакета, NSBundle(forClass: UIView.self)вы пытаетесь предоставить наиболее конкретный язык для данного представления. Однако, используя это, я столкнулся с проблемой, когда для данного класса язык не был возвращен. Я изменил инициализацию на NSBundle.mainBundle()и мне вернули ожидаемый код языка.
Пальми
Разъяснение: Инициализация свертка с , mainBundle()кажется, один Яблоком рекомендуется , как предложено в заголовке для 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 NSBundle.mainBundle()возвращает ваш пакет приложений, тогда как NSBundle(forClass: UIView.self)возвращает системный пакет UIKit. описанный метод ищет каталоги в комплекте. ваш пакет приложений будет содержать только те языки, на которые вы хотите установить локализацию. Чтобы определить язык устройства, вам необходимо проверить комплектацию системы.
Dreamlab
1
@ Пориа проблема могла заключаться в том, что iOS 9 изменила возвращаемые значения с NSLocale.preferredLanguages(). я обновил ответ для поддержки iOS 9 .
Dreamlab
@dreamlab, к сожалению, этот подход дает ложноположительные результаты, когда вы включаете сторонние компоненты, такие как модули, с локализацией, которую вы не поддерживаете в настройках проекта.
Кококо
12

я использую это

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

игнорировать утечку памяти ..

и результат

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
источник
просто для любопытства, где здесь утечка памяти?
Может Пойразоглу
Утечка - [[[NSLocale alloc] initWithLocaleIdentifier: lan].
Павел
1
Только для не-ARC проектов.
Джош Хинман
12

Перевод кодов языков, таких как en_US, на английский (США) является встроенной функцией NSLocaleи NSLocaleне имеет значения, откуда вы получаете коды языков. Таким образом, на самом деле нет оснований для реализации собственного перевода, как предполагает принятый ответ.

// 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);

Принты: английский, немецкий, шведский

Эрик Б
источник
1
На самом деле, вы должны использовать [NSLocale autoupdatingCurrentLocale] для инициализации вашего экземпляра локали. Таким образом, названия языков будут отображаться на родном языке пользователя. Например, шведский станет Свенска.
Maciej Swic
8

Даже есть лучший способ узнать текущий язык устройства. Давайте попробуем это по приведенному ниже коду -

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

Предложил Abizern на здесь

Praveenkumar
источник
7

Вы можете использовать displayNameForKey:value:метод 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"]);

Это распечатает:

français (France)
anglais tats-Unis)

Если вы укажете тот же идентификатор локали для метода, initWithLocaleIdentifier:а также для displayNameForKey:value:метода, он даст вам родное имя языка. Я обнаружил, что если вы удаляете код страны и используете just frand en, то он также пропускает страну из отображаемого имени (по крайней мере, в Mac OS X, не уверен насчет iOS).

dreamlax
источник
6

стриж

Получить текущий язык устройства

NSLocale.preferredLanguages()[0] as String

Чтобы получить язык приложения

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

Замечания:

Он выбирает язык, который вы указали в CFBundleDevelopmentRegion info.plist

если CFBundleAllowMixedLocalizations имеет значение true в info.plist, тогда возвращается первый элемент CFBundleLocalizations в info.plist

Durai Amuthan.H
источник
6

Я пытался найти правильное решение для себя. При использовании Locale.preferredLanguages.firstбыл возвращен предпочитаемый язык из настроек вашего приложения.

Если вы хотите узнать язык из настроек устройства пользователя, вам следует использовать строку ниже:

Свифт 3

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

Чтобы развернуть и использовать, посмотрите на строку ниже:

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

    // For example
    if currentDeviceLanguage == "he" {
        UIView.appearance().semanticContentAttribute = .forceRightToLeft
    } else {
        UIView.appearance().semanticContentAttribute = .forceLeftToRight
    }
}
Роман Романенко
источник
вам не нужно разворачивать, если вы используете этот Bundle.main.preferredLocalizations [0] как String
μολὼν.λαβέ
5

Для получения текущего языка пользовательского устройства используйте следующий код, он работал для меня.

NSString * myString = [[NSLocale preferredlanguage]objectAtIndex:0];
Шайлендра
источник
4

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

Пользователи могут выбирать предпочитаемый язык приложения независимо от языка ОС.

Вы можете использовать это:

    // 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
источник
3

Для разработчиков MonoTouch C # используйте:

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

Примечание: я знаю, что это был вопрос для iOS, но, поскольку я являюсь разработчиком MonoTouch, ответ на этой странице привел меня в правильном направлении, и я решил поделиться результатами.

Чак Сэвидж
источник
В настоящее время я использую NSLocale.PreferredLanguages ​​и получаю пустой массив. Я предполагаю, что вы прочитали в документации, что она никогда не может быть пустой, но я нигде не вижу этого?
JFoulkes
Нет, честно, это было только мое предположение.
Чак Сэвидж
@LarryF Посмотрите это видео: jonas.follesoe.no/2011/07/22/cross-platform-mobile-ndc-2011 Это очень информативно о том, как структурировать ваш код / ​​мультиплатформенные приложения.
Чак Сэвидж
3

В Swift:

let languageCode = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode) as? String
подветренный
источник
3

Свифт 3

let locale = Locale.current
let code = (locale as NSLocale).object(forKey: NSLocale.Key.countryCode) as! String?
print(code!)
Тарик
источник
Добро пожаловать в переполнение стека! Хотя этот фрагмент кода может ответить на вопрос, лучше включить описание того, в чем заключалась проблема, и как ваш код будет решать данную проблему. На будущее, вот некоторая информация о том , как найти отличный ответ на переполнение стека.
dirtydanee
3

Простая функция Swift 3:

  @discardableResult
  func getLanguageISO() -> String {
    let locale = Locale.current
    guard let languageCode = locale.languageCode,
          let regionCode = locale.regionCode else {
        return "de_DE"
    }
    return languageCode + "_" + regionCode
  }
Саша прохоренко
источник
3

Если вы ищете код предпочитаемого языка («en», «de», «es» ...) и локализованное имя предпочитаемого языка (для текущей локали), вот простое расширение в 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)!
}

}

Йован Станкович
источник
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;

}
Джонни Рокекс
источник
2

Если вы хотите получить только язык, вот мой предложенный ответ:

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

В моем случае я просто хотел только язык Locale, а не регион locale.

Вывод: Если ваш язык локали - японский, а регион - Япония, то:

langplusreg = ja-JP

langonly = ja

Danboz
источник
1

Ответ @amir в Swift:

// Get language prefered by user
    let langageRegion = NSLocale.preferredLanguages().first!
    let languageDic = NSLocale.componentsFromLocaleIdentifier(langageRegion)
    let language = languageDic[NSLocaleLanguageCode]
CedricSoubrie
источник
1

Очевидно, что решения, основанные, например, на

[[NSLocale preferredLanguages] objectAtIndex:0]

обычно работают нормально и возвращают текущий язык устройства.

Но это может вводить в заблуждение в некоторых случаях:

Если приложение, в котором вы хотите получить это значение, уже изменило язык, например, с таким кодом:

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

В этом случае [NSLocale предпочитаемый язык] фактически возвращает набор предпочтительного языка (и использованный) в этом конкретном приложении, а не текущий язык устройства!

И ... в этом случае единственный способ правильно получить текущий текущий язык устройства (а не тот, который был ранее установлен в приложении), это сначала очистить ключ @ "appleLanguages" в NSUserDefaults, например так:

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

Затем [NSLocale предпочитаемый язык] теперь возвращает правильное значение.

Надеюсь, это поможет.

Chrysotribax
источник
1

Обновленный ответ для Swift 4

let language = Bundle.main.preferredLocalizations.first
Ибрагим Хасан
источник
Обратите внимание, что при этом извлекается агрегированный список доступных (поддерживаемых пакетом, т. Е. Вами) и предпочтительных (пользователем) локализаций. NSLocale.preferredLanguagesдолжен вернуть предпочтительные для пользователя, не обращая внимания на то, что поддерживается пакетом.
Джонни
1

Для Swift 3.0 ниже код может быть использован для ответа на ваш вопрос:

 let language = Bundle.main.preferredLocalizations.first! as NSString
Апурв Сони
источник
1

В Swift 4.2 и Xcode 10.1

let language = NSLocale.preferredLanguages[0]
print(language)//en
IOS
источник
0

Согласно документации Apple

NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString* preferredLang = [languages objectAtIndex:0];
Макс Тымчий
источник
0

Формат двух букв. Apple использует стандарт ISO ISO-3166 .

NSString *localeCountryCode = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleCountryCode];
Якуб Трухларж
источник
0

Для Swift 3:

NSLocale.preferredLanguages ​​[0] as String

Билл Чан
источник
0

Начиная с iOS 9, если вам нужен код языка без кода страны, вам понадобится такая вспомогательная функция, поскольку язык будет содержать код страны.

// 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
источник
0

СВИФТ-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)
Anshul-systematix
источник
Обратите внимание, что при этом извлекается агрегированный список доступных (поддерживаемых пакетом, т. Е. Вами) и предпочтительных (пользователем) локализаций. NSLocale.preferredLanguagesдолжен вернуть предпочтительные для пользователя, не обращая внимания на то, что поддерживается пакетом.
Джонни