SwiftUI 本地化和枚举

SwiftUI Localization and Enums

有很多关于本地化的一般性讨论,但 none 我发现到目前为止已经解决了我的问题。

我正在使用一个 Localizable.strings 文件,然后是另一个 swift 文件,其中包含一个名为 LocalizationStrings 的枚举。在枚举中,我使用静态 let 语句,这样我就可以避免在我的各种文件中出现拼写错误。 (有很多要翻译的,每天都会有更多)

所有这些都运行良好,除非您有一个包含字符串插值的本地化字符串。这种情况会失败,因为您不能将枚举括在引号中,或者它会作为输入的字符串被读回,而不是被翻译成枚举实际等同的内容(这是预期的行为)。

当然,将枚举从等式中剔除并使用字符串插值效果很好,但我非常想知道是否有办法继续使用枚举值,即使存在字符串插值。

这里有一些代码来解释:

Localizable.strings

"MY_NAME %@" = "My name is %@";
"YOUR_NAME" = "Your name is Fred";

LocalizationString.swift

enum LocalizationString {
    static let myName: LocalizedStringKey = "MY_NAME %@"
    static let yourName: LocalizedStringKey = "YOUR_NAME"
}

内容视图

struct CA_EmailVerifyView: View {

    let name = "Tom"

    var body: some View {
        VStack {
            // This works
            Text(LocalizationString.yourName)

            // This works (not using the enum)
            Text("myName \(name)")

            // This does not work (won't compile, but this is how I would love to use it)
            Text(LocalizationString.myName \(name))

            // This does not work (output is LocalizationString.myName Tom)
            Text("LocalizationString.myName \(name)")
        }
    }
}

这个有用吗?

enum LocalizationString {
    static func myName(_ name: String) -> String {
        String(format: NSLocalizedString("MY_NAME", comment: "My Name"), name)
    }
    static let yourName: LocalizedStringKey = "YOUR_NAME"
}

var name = "Nobody"
Text(LocalizationString. myName(name))

另一种可能性是对 CustomStringConvertible 或 CVarArg 类型使用扩展:

enum LocalizationString {
    static let myName: String = "MY_NAME"
    static let yourName: LocalizedStringKey = "YOUR_NAME"
}

extension String {
    func format(_ str: CustomStringConvertible) -> String {
        String(format: NSLocalizedString(self, comment: self), "\(str)")
    }
    func formatArg(_ arg: CVarArg) -> String {
        String(format: NSLocalizedString(self, comment: self), arg)
    }
}


var name = "Nobody"
var other = 500
Text(LocalizationString.myName.format(name))
Text(LocalizationString.myName.formatArg(name))
Text(LocalizationString.myName.format(other))
Text(LocalizationString.myName.formatArg(other))

另一个使用 % :

enum LocalizationString {
    static let myName: String = "MY_NAME"
}

extension String {
    static func %(_ key: String, _ arg: CVarArg) -> String {
        String(format: NSLocalizedString(key, comment: key), arg)
    }
}

var name = "Nobody"
var other = 500
Text(LocalizationString.myName % name)
Text(LocalizationString.myName % other)

编辑: 对于多个参数,使用数组和 arguments: in format :

    static func %(_ key: String, _ arg: [CVarArg]) -> String {
        String(format: NSLocalizedString(key, comment: key), arguments: arg)
    }

    Text(LocalizationString.myName % [other, name])

编辑:使用 LOcalizedStringKey :

extension LocalizedStringKey {
    // [how-to-change-localizedstringkey-to-string-in-swiftui](
    var stringKey: String {
        let description = "\(self)"
        let components = description.components(separatedBy: "key: \"")
                    .map { [=14=].components(separatedBy: "\",") }
        return components[1][0]
    }
    static func %(_ key: LocalizedStringKey, _ arg: [CVarArg]) -> String {
        String(format: NSLocalizedString(key.stringKey, comment: key.stringKey), arguments: arg)
    }
    static func %(_ key: LocalizedStringKey, _ arg: CVarArg) -> String {
        String(format: NSLocalizedString(key.stringKey, comment: key.stringKey), arg)
    }
}

enum LocalizationString {
    static let myName: LocalizedStringKey = "MY_NAME"
    static let yourName: LocalizedStringKey = "YOUR_NAME"
}

var name = "Nobody"
var other = 500
Text(LocalizationString.myName % name)
Text(LocalizationString.myName % [other, name])

我在 how-to-change-localizedstringkey-to-string-in-swiftui

中找到了 stringKey

答案比编写扩展和做复杂的工作要简单得多。当一个变量存在时,你可以写一个静态函数,而不是写一个静态 let。这一切都发生在 LocalizationString.swift 文件的枚举中,看起来像这样:

static func testText(name: String) -> LocalizedStringKey { LocalizedStringKey("TEST_TEXT \(name)") }

要在您的视图中使用它:

Text(LocalizationStrings.testTest(name: varname))

如果您需要更多变量,只需将它们添加到函数中即可。