xcode 如何在SwiftUI中将LocalizedStringKey更改为字符串

kuarbcqp  于 2022-11-26  发布在  Swift
关注(0)|答案(6)|浏览(299)

我正在尝试使用SwiftUI本地化AppleMapView中显示的标记。
但是,MKAnnotation的标记标题的类型固定为String。我不想继承或创建自定义类,因为这太麻烦了。
我需要的只是将LocalizedStringKey转换为String以设置标记的标题。对此有帮助吗?

gxwragnw

gxwragnw1#

EDIT:此答案已编辑过一次,以便在stringKey中实现更清晰的代码和更好的性能。

LocalizedStringKey有一个名为key的成员,其中包含与本地化文件中的本地化字符串相对应的密钥字符串。不幸的是,我们无法直接访问密钥,因此我们需要解决获取密钥的问题。

// An Example that won't work:
let localizedKey = LocalizedStringKey.init("SOME_LOCALIZED_KEY_HERE")

localizedKey.key // ERRROOOOORR! `key` is an internal member of `LocalizedStringKey` and you can't access it!

解决方法扩展,并提供一个工作原理示例,以从LocalizedStringKey中获取密钥:

extension LocalizedStringKey {

    // This will mirror the `LocalizedStringKey` so it can access its 
    // internal `key` property. Mirroring is rather expensive, but it 
    // should be fine performance-wise, unless you are  
    // using it too much or doing something out of the norm.
    var stringKey: String? {
        Mirror(reflecting: self).children.first(where: { $0.label == "key" })?.value as? String
    }
}

// An Example:
let localizedKey = LocalizedStringKey("KEY_HERE")
print(localizedKey.stringkey)
// prints `KEY_HERE`

现在我们有了一个字符串形式的键,你可以很容易地得到LocalizedStringKey的键所指向的本地化字符串。

extension String {
    static func localizedString(for key: String,
                                locale: Locale = .current) -> String {
        
        let language = locale.languageCode
        let path = Bundle.main.path(forResource: language, ofType: "lproj")!
        let bundle = Bundle(path: path)!
        let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")
        
        return localizedString
    }
}

要理解这一点,请查看https://stackoverflow.com/a/27879342/11837341
现在,您可以轻松地将LocalizedStringKey值转换为字符串:

extension LocalizedStringKey {
func stringValue(locale: Locale = .current) -> String {
        return .localizedString(for: self.stringKey, locale: locale)
    }
}

TL; DR(汇总)

将这些扩展添加到您的项目:

extension LocalizedStringKey {
    var stringKey: String? {
        Mirror(reflecting: self).children.first(where: { $0.label == "key" })?.value as? String
    }
}

extension String {
    static func localizedString(for key: String,
                                locale: Locale = .current) -> String {
        
        let language = locale.languageCode
        let path = Bundle.main.path(forResource: language, ofType: "lproj")!
        let bundle = Bundle(path: path)!
        let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")
        
        return localizedString
    }
}

extension LocalizedStringKey {
    func stringValue(locale: Locale = .current) -> String {
        return .localizedString(for: self.stringKey, locale: locale)
    }
}

示例

let localizedKey = LocalizedStringKey("KEY_NAME_HERE")

print(localizedKey.stringKey)
//prints `KEY_NAME_HERE`

print(localizedKey.stringValue())
// prints Localized value of `KEY_NAME_HERE`
// DOESNT print `KEY_NAME_HERE`
kfgdxczn

kfgdxczn2#

只需使用以下命令即可:String(localized: "YOUR_LOCALIZED_KEY")
Mahdi BM的解决方案有一个问题,因为Swift只返回语言代码,即使你使用的是西班牙语和葡萄牙语等其他语言的变体。两个例子的语言代码总是返回ES和PT,但是带有本地化键的文件夹的名称将是不同的:PT可以是“pt-PT”或“pt-BR”,西班牙语可以是“es”或“es-419”(拉丁美洲),这些情况将导致您的应用程序崩溃。

hmmo2u0o

hmmo2u0o3#

您可以使用NSLocalizedString。

let localizedString = NSLocalizedString("LOCALIZED-STRING-KEY", comment: "Describe what is being localized here")
qncylg1j

qncylg1j4#

我修改了top answer以在Xcode14上编译,删除了强制解包,并在找不到翻译时返回密钥:

extension LocalizedStringKey {
    var stringKey: String? {
        Mirror(reflecting: self).children.first(where: { $0.label == "key" })?.value as? String
    }
    
    func stringValue(locale: Locale = .current) -> String? {
        guard let stringKey = self.stringKey else { return nil }
        let language = locale.languageCode
        guard let path = Bundle.main.path(forResource: language, ofType: "lproj") else { return stringKey }
        guard let bundle = Bundle(path: path) else { return stringKey }
        let localizedString = NSLocalizedString(stringKey, bundle: bundle, comment: "")
        return localizedString
    }
}
xurqigkl

xurqigkl5#

import Foundation
import SwiftUI

@available(macOS 10.15, *)
public extension LocalizedStringKey {
    private var keyStr: String {
        return "\(self)".keyFromLocalizedStringKey
    }
    
    func localizedStr(locale: Locale = .current) -> String {
        return String.localizedString(for: self.keyStr, locale: locale)
    }
}

fileprivate extension String {
    static func localizedString(for key: String, locale: Locale = .current) -> String {
        
        let language = locale.languageCode
        let path = Bundle.main.path(forResource: language, ofType: "lproj")!
        let bundle = Bundle(path: path)!
        let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")
        
        return localizedString
    }
    
    var keyFromLocalizedStringKey: String {
        let comp2 = self.substring(from: 25).components(separatedBy:"\", hasFormatting")
        
        if comp2.count == 2 {
            return comp2.first!
        }
        
        return "failed to get stringKey"
    }
}

使用方法:

let lsk = LocalizedStringKey("KEY_NAME_HERE")

let key = lsk.keyStr
let translatedToCurrLocale = lsk.localizedStr()
uqcuzwp8

uqcuzwp86#

将扩展名添加到字符串以读取本地化语言

extension String {
    func localized() -> String {
        let path = Bundle.main.path(forResource: "your language", ofType: "lproj")!
        if let bundle = Bundle(path: path) {
            let str = bundle.localizedString(forKey: self, value: nil, table: nil)
            return str
        }
        return ""
    }
}

使用LocalizedStringKey加载示例代码

let title: String = "LocalizedStringKey".localized()

相关问题