SwiftUI:变量字符串未导出以进行本地化。

3
根据苹果文档,应该可以这样做:
如果您使用字符串变量而不是字符串字面量初始化文本视图,则视图会触发init(:)初始化程序,因为它假定您在这种情况下不需要本地化。如果您确实想要将存储在字符串变量中的值本地化,可以选择先从字符串变量创建一个LocalizedStringKey实例,然后再调用init(:tableName:bundle:comment:)初始化程序: Text(LocalizedStringKey(someString)) // 本地化someString的内容。 链接:https://developer.apple.com/documentation/swiftui/text/init(_:tablename:bundle:comment:)
这在这里也得到了推荐:https://www.ibabbleon.com/swiftui_localization_tutorial.html
但是,至少在我的情况下,它并没有生效。在以下示例中,只有“Some content 1”值被导出进行本地化。
struct ContentView: View {
    let text = "Some content 2"
    var body: some View {
        Text("Some content 1", comment: "This text is exported for localization, as expected.")
            .padding()
        Text(LocalizedStringKey(text), comment: "This text is not exported for localization, which is not expected behaviour.")
            .padding()
    }
}

在应用程序设置中,“使用编译器提取Swift字符串”设置为是。
我错过了什么?

它说的是“如果你确实想要本地化” - 它并没有说“如果你想要导出以进行本地化” - 前者是框架功能,后者属于Xcode行为。按照文档工作 - 在运行时显示变量的本地化字符串。 - Asperi
我明白了。所以根据这个例子,“Some content 2”不会被导出进行本地化,但是如果找到相应的键,则会进行本地化?我不确定我是否理解其中的意义;我希望这些字符串都能够被导出和本地化。经过一些测试,我发现我可以声明let content2: LocalizedStringKey = "Some content 2"并将其用作Text(content2)。这样就可以很好地导出进行本地化。但是我不知道如何向字符串添加注释。如果我添加Text(content2, comment: "Some comment"),则该注释将不会被导出进行本地化。 - blueFox
3个回答

5

好的,所以在进一步尝试本地化后,我找到了一个有效的方法。

我提供的教程(https://www.ibabbleon.com/swiftui_localization_tutorial.html)没有谈到这个问题,并且使用了LocalizedStringKey和Text(String,comment: String)使事情变得混乱。一些其他的教程也是这样做的,但这会使代码变得非常丑陋,因为它将数据移动到了Text中。因此,如果您想要将数据与视图分离,您必须在视图模型中包含Text(一个UI元素)。或者,如果您使用LocalizedStringKey,则无法为翻译者添加注释。

幸运的是,有一个简单得多的方法!

struct ContentView: View {
  let normalString = "This is not exported for localization. Good for previews!"
  let localizedString = String(localized: "This is exported for localization.", comment: "You can add a comment for the translator, too!")

  var body: some View {
    VStack {
      Text(normalString)
      Text(localizedString)
    }
  }
}

此 API 仅适用于最新的操作系统。因此,使用旧的 NSLocalizedString(, comment:) 宏更为合理。 - Owen Zhao

1

你已经发现使用let content2: LocalizedStringKey = "一些内容 2"可以解决你的问题,但仍然有一个问题是如何添加注释。

在WWDC21的本地化你的SwiftUI应用会议上,苹果公司指出一种方法是让你的视图的参数是Text类型,这样你就可以提供注释了。

struct ContentView: View {
    let text = Text("Some content 2", comment: "This gets exported!")
    var body: some View {
        Text("Some content 1", comment: "This text is exported for localization, as expected.")
            .padding()
        text
            .padding()
    }
}

谢谢你的回答。是的,我知道,但对于注入的字符串来说并不有用。例如,我有一个enum ColorScheme: String, Identifiable {,它持有dark/light选项,比如case light = "Light",还有var id: String { self.rawValue }。我想将此字符串与注释一起导出,但如果我将其传递给ContentView,Xcode要求我将其转换为LocalizedStringKey,例如Text(LocalizedStringKey(ColorScheme.dark.id), comment: "Comment"),这样无法导出,或者像Text("\(ColorScheme.light.id)", comment: "Comment.")这样将其放在引号中,这样会导出字符串为%@。 - blueFox
是的。看起来这种情况在新的本地化导出工具中无法很好地处理。在这种情况下,我可能会放弃使用案例的原始值作为您想要导出的字符串,而是在枚举上有一个计算属性,例如@ViewBuilder var foo: Text { switch self { case .light: Text("Light", comment: "my comment") } } - Helam
由于导出过程是在编译时而不是运行时完成的,因此任何尝试将String变量传递到LocalizedStringKey初始化程序中都无法按照您想要的方式进行导出。它必须在编译时知道LocalizedStringKey字符串的值。我能想到的所有方法都涉及将字符串文字直接与LocalizedStringKey类型相关联,例如通过在变量中拥有它,如let foo:LocalizedStringKey =“yay”,或者通过将字符串文字作为LocalizedStringKey参数的值传递进来,例如Text(“yay”) - Helam

0
到目前为止,我已经发现了两种使用SwiftUI本地化字符串的方法。第一种可以在WWDC关于本地化的讲座此文章中找到。如果你只想避免在视图中使用字符串字面量,但不一定需要将其本地化,可以像这样操作:
创建一个Swift归档文件并创建一个类似示例的enum:
enum MyLocalizable: LocalizedStringKey {
 case mytest
}

现在,在您的项目中创建一个 Localizable.strings 文件并设置您的字符串。
例如:
"mytest" = "Lorem ipsum dolor sit amet.";

最后,您可以在此表单上访问视图中的值:
Text(MyLocalizable.mytest.rawValue)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接