Отримання мови поточного пристрою в iOS?


431

Я хотів би показати поточну мову, якою користувальницький інтерфейс пристрою. Який код я б використовував?

Я хочу, щоб це було NSStringповністю викладеним форматом. (Not @ "en_US")

EDIT: Для тих, хто їде далі, тут є маса корисних коментарів, оскільки відповідь розвинулася новими версіями iOS.


1
Це вбудовано в NSLocale. Дивіться мою відповідь.
Ерік Б

15
коментар iOS9: зверніть увагу на те, що Apple з якихось дивних причин змінила повернений формат [NSLocale preferredLanguages]. вона була відокремлена підкресленням (наприклад en_US), але тепер вона була перетворена на тире:en-US
ishahak

7
Детальніше про iOS9: Отримання [NSLocale preferenceLanguages] на симуляторі iOS 8.4 проти 9.0 симулятора також має розбіжності. На iOS 8.4 це "en", а iOS 9.0 - "en-US"
Kris Subramanian

Цей коментар мені дуже допоміг! Ми застрягли в простому питанні, цікаво, що пішло не так близько 1 години, поки я не побачив ваш коментар.
thandasoru

3
NSLocaleє методи componentsFromLocaleIdentifier:і localeIdentifierFromComponents:які, ймовірно , правильно обробляти (потенційно змінюваний) формат.
Бенджон

Відповіді:


808

Надані рішення фактично повернуть поточну область пристрою - не вибрану на даний момент мову. Це часто одне і те саме. Однак, якщо я перебуваю в Північній Америці і перекладу свою мову на японську, моїм регіоном все одно буде англійська (США). Щоб відновити вибрану мову, ви можете:

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

Це поверне двобуквенний код для вибраної мови. "en" для англійської, "es" для іспанської, "de" для німецької та ін. Для додаткових прикладів див. цей запис у Вікіпедії (зокрема, стовпець 639-1):

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

Тоді це проста проблема перетворення двох буквених кодів у рядок, який ви хочете відобразити. Тож якщо це "en", виведіть "English".

Сподіваємось, це допомагає тому, хто шукає, щоб розрізняти регіон та вибрану мову.

EDIT

Варто навести інформацію заголовка з 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


2
Саме те, що я шукав. У мене було те саме питання, де регіон не є таким, як мова.
Jasarien

12
погана відповідь: повертає zh-Hans для китайської мови, що не є ізо-кодом.
cyrilchampier

2
Перші два символи дають країну, матеріал після тире надає регіону, решта - лише для того, щоб звузити його далі (наприклад, місцеві діалекти). zh вказаний як ізо-код для китайців. Для тих, хто шукає певну мову, як я, спробуйте реєстр 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];

Швидкий:

let language = NSBundle.mainBundle().preferredLocalizations.first as NSString

Відмінно, це мене теж цікавило. Випробувано, і воно працює правильно!
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
Це, безумовно, неправильно, наприклад, якщо ви встановите мову в налаштуваннях телефону на англійській мові, а у форматі регіону, щоб сказати німецьку, Німеччину, приклад вище повертає "німецьку". Проте мова телефону встановлена ​​на англійську.
jake_hetfield

2
Це зовсім не помиляється. Локал містить інформацію про мову та регіон. Тож у прикладі @ jake_hetfield воно не поверне "німецьку", а поверне "англійську (Німеччину)". Ця комбінація з відповіддю сонника повинна бути правильною.
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 -> General -> Language & Region -> Preferred Order Language


Можна, ніж використовувати код мови пристрою, і перекласти його в назву мови. Наступні рядки надрукують мову пристрою мовою пристрою. Наприклад, "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)
    }
} 

Я розумію, що, ініціалізуючи свій екземпляр пакету, NSBundle(forClass: UIView.self)ви намагаєтеся надати найбільш конкретну мову для заданого перегляду. Однак, використовуючи це, я зіткнувся з проблемою, де для даного класу мова не поверталася. Я змінив ініціалізацію на NSBundle.mainBundle()і мені було повернуто очікуваний код мови.
palmi

Роз'яснення: Ініціалізація згортка з , 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.
palmi

@Pouria NSBundle.mainBundle()повертає ваш додаток, тоді як NSBundle(forClass: UIView.self)повертає системний пакет UIKit. описаний метод шукає каталоги в пакеті. ваш пакет додатків міститиме лише ті мови для мов, на яких ви хочете локалізуватись. щоб визначити мову пристрою, вам потрібно буде перевірити системний пакет.
dreamlab

1
@Pouria проблема могла полягати в тому, що 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

просто для цікавості, де тут просочується пам'ять?
Може Пойразоглу

Витік - [[[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], щоб ініціалізувати свій екземпляр локалі. Таким чином імена мов будуть відображатися на рідній мові користувачів. Наприклад, шведська стане Svenska.
Maciej Swic

8

Навіть є кращий спосіб отримати поточну мову пристрою. Давайте спробуємо за цим кодом нижче -

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

Запропонував Abizern на тут


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:метод, він дасть вам рідну назву мови. Я виявив, що якщо ви вилучите код країни та використовуєте просто frі en, що він також опустить країну з відображуваного імені (на Mac OS X принаймні, не впевнений у iOS).


6

Швидкий

Щоб отримати поточну мову пристрою

NSLocale.preferredLanguages()[0] as String

Щоб отримати мову програми

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

Примітка:

Він вибирає мову, яку ви вказали в CFBundleDevelopmentRegion of info.plist

якщо CFBundleAllowMixedLocalizations вірно в info.plist, тоді повертається перший елемент CFBundleLocalizations в info.plist


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

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!)

Ласкаво просимо до переповнення стека! Хоча цей фрагмент коду може відповісти на питання, краще включити опис, в чому була проблема, і як ваш код вирішить дану проблему. На майбутнє, ось деякі відомості, як зламати приголомшливу відповідь на переповнення стека.
бруднене

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];

У моєму випадку я просто хотів лише мови мови, а не локальної області.

Висновок: Якщо ваша мова локальної мови - японська, а регіональним регіоном є Японія, то:

langplusreg = ja-JP

langonly = я


1

@amir відповідь у Swift:

// Get language prefered by user
    let langageRegion = NSLocale.preferredLanguages().first!
    let languageDic = NSLocale.componentsFromLocaleIdentifier(langageRegion)
    let language = languageDic[NSLocaleLanguageCode]

1

Очевидно, рішення, які покладаються, наприклад, на

[[NSLocale preferredLanguages] objectAtIndex:0]

зазвичай працюють нормально і повертають поточну мову пристрою.

Але це може ввести в оману в деяких випадках:

Якщо додаток, у якому ви хочете отримати це значення, вже змінив мову, наприклад, з таким кодом:

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

У цьому випадку [NSLocale preferenceLanguages] фактично повертає бажаний набір мов (і використовуваний) у цьому конкретному додатку, а не поточну мову пристрою!

І ... в цьому випадку єдиний спосіб правильно отримати фактичну поточну мову пристрою (а не ту, яка раніше була встановлена ​​в додатку), це спочатку очистити ключ @ "appleLanguages" в NSUserDefaults, як це:

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

Потім [NSLocale preferenceLanguages] тепер повертає правильне значення.

Сподіваюся, що це допоможе.


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




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;
}

0

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)

Зауважте, що це отримує зведений список доступних (підтримується в комплекті, тобто ви) та бажаних (користувачем) локалізацій. NSLocale.preferredLanguagesповинні повернути бажані користувачі, не поважаючи того, що підтримується в комплекті.
Джоні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.