使用Swift强制NSLocalizedString使用特定语言

ymzxtsji  于 2023-04-19  发布在  Swift
关注(0)|答案(5)|浏览(236)

使用swift,我如何强制我的应用从特定的Localizable.strings读取数据。
我在示例化ViewController之前把它放在didFinishLaunchingWithOptions中,但它仍然用英语向我显示应用程序。

NSUserDefaults.standardUserDefaults().removeObjectForKey("AppleLanguages")
NSUserDefaults.standardUserDefaults().setObject("fr", forKey: "AppleLanguages"   
NSUserDefaults.standardUserDefaults().synchronize()

我试着像这样为“AppleLanguages”键传递一个Array,但它仍然不起作用:

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages"

完成后,我是否可以在应用程序内调用此功能,并在不重新启动应用程序的情况下考虑更改?

of1yzvn4

of1yzvn41#

无法通过更改AppleLanguages的值立即更改应用的语言。需要重新启动应用才能使更改生效。
看起来你的问题是访问不同语言的本地化字符串,而不是更改应用的语言,对吗?如果你想让你的应用支持多种语言,你可以只提供翻译,并依靠settings.app进行实际更改。
如果你想从当前使用的本地化之外的地方访问本地化字符串,你需要访问适当的翻译包。然后只需要查询该包的翻译。下面的代码应该可以做到这一点。

let language = "en"
let path = Bundle.main.path(forResource: language, ofType: "lproj")
let bundle = Bundle(path: path!)
let string = bundle?.localizedStringForKey("key", value: nil, table: nil)
wqlqzqxt

wqlqzqxt2#

使用NSLocalizedString可以指定bundle。

let language = "fr"
let path = Bundle.main.path(forResource: language, ofType: "lproj")!
let bundle = Bundle(path: path)!
let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")

或者使用bundle,您也可以直接调用localizedStringForKey:value:table:

jgwigjjp

jgwigjjp3#

@Radu我也让这个工作XCUITests感谢@Markus的原始答案:
您可以显式指定MainBundle的路径,它只能在带有模拟器的Mac上工作,但它经常用于持续集成平台,因此这可能是可以接受的:

let language: String = "en"
let path = "/Users/{username}/{path_to_your_project}/\(language).lproj"
let bundle = Bundle(path: path)
let string = bundle?.localizedString(forKey: "key", value: nil, table: nil)
l5tcr1uw

l5tcr1uw4#

在swift 4中,我已经解决了这个问题,而不需要重新启动或使用库。在尝试了许多选项之后,我找到了这个函数,在这里你传递你想要翻译的stringToLocalize(Localizable.String,字符串文件),以及你想要翻译它的语言,它返回的是你在Strings文件中的String的值:

    func localizeString (stringToLocalize: String, language: String) -> String
    {
        let path = Bundle.main.path (forResource: language, ofType: "lproj")
        let languageBundle = Bundle (path: path!)
        return languageBundle! .localizedString (forKey: stringToLocalize, value: "", table: nil)
    }

考虑到这个函数,我在Swift文件中创建了全局函数:

struct CustomLanguage {

    func createBundlePath () -> Bundle {
        let selectedLanguage = //recover the language chosen by the user (in my case, from UserDefaults)
        let path = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj")
        return Bundle(path: path!)!
    }
}

要从整个应用程序访问,并在ViewControllers的其余部分的每个字符串中,而不是放入:

NSLocalizedString ("StringToLocalize", comment: “")

我把它换成

let customLang = CustomLanguage() //declare at top

NSLocalizedString("StringToLocalize", tableName: nil, bundle: customLang.createBundlePath(), value: "", comment: “”) //use in each String

我不知道这是不是最好的方法,但我发现它很简单,它对我很有效,我希望它能帮助你!

dced5bon

dced5bon5#

我发现所有其他答案都很有帮助。然而,我想在这里添加一点保护措施。第一次,针对所请求的语言可能不可用的情况。第二次,针对我们有更复杂的区域设置标识符的情况。
特别是在后一种情况下,它并不像简单地将localeMap到正确的lproj文件夹那样简单,因为它们的命名方式可能不完全相同。因此,我发现将这部分留给系统更容易。Bundle.preferredLocalizations正是这样做的。
假设您请求en-GB,但您的应用仅支持en-US或en。由于项目中没有en-GB.lproj文件夹,因此不会返回bundle。但是,调用preferredLocalizations应该将其解析为en. lproj。作为旁注,对于中文也是如此(zh,zh-Hans,zh-Hant等)。

func localizedBundle(locale: String?) -> Bundle {
    if let locale {
        if let preferredLocale = Bundle.preferredLocalizations(from: Bundle.main.localizations, forPreferences: [locale]).first {
            if let path = Bundle.main.path(forResource: preferredLocale, ofType: "lproj") {
                if let bundle = Bundle(path: path) {
                    return bundle
                }
            }
        }
    }
    return Bundle.main
}

请注意,preferredLocalizations应该至少返回一个值,该值可能不一定与请求的locale匹配。如果您想知道locale是否无法解析,则必须为每个locale创建两个Locale对象,输入locale字符串和返回的locale字符串,然后比较语言标记。但这不是这里答案的一部分。
使用bundle调用NSLocalizedString,如下所示。

NSLocalizedString("key", bundle: bundle, comment: "")

顺便说一句,如果bundle是主bundle,那么它相当于只使用key和comment参数调用NSLocalizedString,所以不用担心。
在调用NSLocalizedString之前缓存bundle并且不每次都检索它也是有意义的。

相关问题