Locale.current 报告设备上的语言错误

Locale.current reporting wrong language on device

我正在尝试在 iOS 应用程序中设置货币值的格式,并且我正在使用设备上的当前区域设置来使用适当的货币格式。

在模拟器中,一切似乎 运行 都很好:当使用 currencyFormatter.locale = Locale.current 时,它采用正确的区域设置并以正确的货币格式打印数字。

然而,在我的 iPhone 上,它是用法语配置的,具有法语区域设置,我希望使用另一种格式(例如:1 234,56 € ).但它不起作用,并且似乎使用了英文格式样式(例如:€1 234,56)。

事实上,如果我在设备上打印我的应用程序的当前区域设置,它不会像我期望的那样 return fr_FR:

NSLog(Locale.current.identifier)
>>> en_FR

该地区很好,但语言不好,尽管该设备上的 iOS 显然是法语。

有人对此有想法吗?

谢谢!

根据@MartinR 的提示,我现在使用 currencyFormatter.locale = Locale(identifier: Locale.preferredLanguages.first!),它与设备的当前语言和区域设置完全对应。

虽然我不完全确定这段代码是防弹的(因为 first!,最值得注意的是)所以如果您有其他建议,请随意。

根据@Romain 的回答,first! 的强制展开可以通过使用 Locale.current.identifier 作为回退来避免。

func getPreferredLocale() -> Locale {
    guard let preferredIdentifier = Locale.preferredLanguages.first else {
        return Locale.current
    }
    return Locale(identifier: preferredIdentifier)
}

@floriger 的扩展形式的回答:

import Foundation

extension Locale {
    static func preferredLocale() -> Locale {
        guard let preferredIdentifier = Locale.preferredLanguages.first else {
            return Locale.current
        }
        return Locale(identifier: preferredIdentifier)
    }
}

然后像这样使用它:

dateFormatter.locale = Locale.preferredLocale()
datePicker.locale = Locale.preferredLocale()

@罗曼 这里的问题是您没有将您的应用程序本地化为法语,而只本地化为英语。

转到左上角带有您的应用程序名称的蓝色文件,select 项目 > 信息,您将在本地化区域看到 "English - Development Language"。 按 + 并选择法语 (fr)。

就是这样。 现在您可以使用 Locale.current,如果设备(或模拟器)的第一语言是法语,您的应用程序将显示法国货币格式。

如果一切都失败了

我花了一个小时调试这个。我在德国,我的 iPhone 语言设置是英语,我的地区是德国。

我正在调试一个应用程序,该应用程序从 iPhone 中获取区域设置并将其作为 header 的 API 调用传递给服务器。我想知道为什么我总是得到德语的所有数据字符串。查看应用程序,一切都正确完成:

    if let deviceLanguageCode = Locale.current.languageCode,
    deviceRegionCode = Locale.current.regionCode {
        // do stuff here
    }

上面的变量deviceLanguageCode总是returnsde.
不过应该是“en”!
我尝试了一切。我使用了 Locale.autoupdatingCurrent.languageCodeLocale.preferredLanguages.first 等,没有任何效果。我检查了我的项目设置,我的 Localizable.strings 文件。都好。如果我创建一个新的 Xcode 项目并打印这些变量,我将获得正确的语言环境和区域:en_DE.

太气人了!
只有当我用尽所有可能性时,我才阅读 Paul Hudson(还有谁?)的 post,最后,他给出了测试本地化的提示:

Tip: You can switch between languages by going to the Product menu, holding down the Alt key, then choosing “Run...” Look under the Options tab and you’ll see Application Language is set to System Language by default, but you can change to others there for testing purposes.

还有……'quelle horreur!' 有人在我之前去过那里,并将应用程序语言和地区设置为德国!!!难怪我过得很辛苦!

故事结束:确保这些已设置为系统,否则将无法正常工作;)

当小部件应该与应用程序具有相同的语言并且 iPhone 语言不同时,您可以使用此:

func getPreferredLocale() -> Locale {
    guard let preferredIdentifier = Bundle.main.preferredLocalizations.first else {
        return Locale.current
    }
    return Locale(identifier: preferredIdentifier)
}

使用此代码从iOS设备

获取当前系统语言代码
let pre = Locale.preferredLanguages[0]

如果您仍然遇到这个问题 如果你有错误的语言代码。请从 UserDefaults "AppleLanguages" 中删除此对象并使用相同的代码 Locale.preferredLanguages[0]

供大家参考

func getSystemLanguageCode() -> String {
    UserDefaults.standard.removeObject(forKey: "AppleLanguages")
    let pref_Language = NSLocale.preferredLanguages[0] as String //"fr-IN"
    let language = pref_Language.components(separatedBy: "-") //["fr","IN"]
    let lang_Code = language.first?.lowercased() ?? "" //"fr"
    UserDefaults.standard.set([lang_Code], forKey: "AppleLanguages")
    
    return lang_Code
}

总结

Apple 希望当开发人员决定支持本地化时,该项目将拥有可本地化的资源,如字符串或故事板,以提供 一致的 UI(例如,不仅仅是打印本地格式的货币),在这种情况下,使用 Locale.current 是合适的选择,它对支持的本地化工作得很好 (如 所述)。

但是,在像@Romain 的情况下:

"I would have hoped I would be able to print currency numbers in the user's regional settings without having to provide a localization for every language"

解决方法是在 null 的情况下使用 Locale.preferredLanguages.first 和回退(如 所述)