swiftui - SwiftUI 自动字符串本地化问题
问题描述
我一直在研究 SwiftUI 应用程序的本地化,但我遇到了一个我不太了解的与本地化相关的情况(鉴于,我对 SwiftUI 还不太精通,首先)
据我了解,至少在 iOS 14 中,SwiftUI 几乎会自动将本地化应用于所有“正常”字符串(只要我设置了正确的本地化文件——我会这样做)。但是,我有两个相同字符串文字的实例——一个得到自动本地化处理。另一个没有。
这就是我想要弄清楚的情况。
我有以下代码:
NavigationView {
NavigationLink(destination: CalendarSettingsView()) {
SettingsNavLinkView(label: "Calendar") // <- this doesn't get localized
}
}
并SettingsNavLinkView
设置如下(只是与问题相关的骨架):
struct SettingsNavLinkView: View {
var label:String
var body: some View {
Text(label) // <- localized "Calendar" is expected to be passed here
}
}
此外,CalendarSettingsView
将其标题定义为:
struct CalendarSettingsView: View {
var body: some View {
ScrollView {
//some code
}
.navigationBarTitle("Calendar", displayMode: .inline) // <- "Calendar" here does get localized
}
}
我的本地化文件中确实有“日历”的关键条目。
正在发生的事情(以及我不明白的事情)是针对SettingsNavLinkView(label: "Calendar")
组件的,“日历”没有被本地化,但是,对于CalendarSettingsView
组件(和相关的用例:), .navigationBarTitle("Calendar", displayMode: .inline)
“日历”字符串确实被本地化了。
这两种情况对我来说似乎都一样String
,所以我只是想弄清楚这里发生了什么。
SettingsNavLinkView
我确实通过专门添加 LocalizedStringKey 初始化来修改这个问题,如下所示:
struct SettingsNavLinkView: View {
var label:String
let localizedLabel = LocalizedStringKey(label) // <-- NEW
var body: some View {
Text(localizedLabel) // <-- UPDATED to use localizedLabel instead of label
}
}
但为什么我必须这样做?为什么“日历”字符串在SettingsNavLinkView
按照此代码传递给时没有自动本地化SettingsNavLinkView(label: "Calendar")
?
SwiftUI 本地化中的错误?我对本地化如何工作的不完全理解?我宁愿不必求助于LocalizedStringKey
“简单字符串”……但是从“自动”本地化如何真正起作用的角度来看,我不确定我所要求的是否有效。
任何想法表示赞赏。谢谢!
解决方案
Because different Text
constructors are inferred for literal string and for variable string and that is documented in SwiftUI API
/// Creates a text view that displays a stored string without localization.
///
/// Use this intializer to create a text view that displays — without
/// localization — the text in a string variable.
///
/// Text(someString) // Displays the contents of `someString` without localization.
///
/// SwiftUI doesn't call the `init(_:)` method when you initialize a text
/// view with a string literal as the input. Instead, a string literal
/// triggers the ``Text/init(_:tableName:bundle:comment:)`` method — which
/// treats the input as a ``LocalizedStringKey`` instance — and attempts to
/// perform localization.
///
/// By default, SwiftUI assumes that you don't want to localize stored
/// strings, but if you do, you can first create a localized string key from
/// the value, and initialize the text view with that. Using a key as input
/// triggers the ``Text/init(_:tableName:bundle:comment:)`` method instead.
///
/// - Parameter content: The string value to display without localization.
public init<S>(_ content: S) where S : StringProtocol
as they said no localization.
but next with localization:
/// Creates a text view that displays localized content identified by a key.
///
/// Use this intializer to look for the `key` parameter in a localization
/// table and display the associated string value in the initialized text
/// view. If the initializer can't find the key in the table, or if no table
/// exists, the text view displays the string representation of the key
/// instead.
///
/// Text("pencil") // Localizes the key if possible, or displays "pencil" if not.
///
/// When you initialize a text view with a string literal, the view triggers
/// this initializer because it assumes you want the string localized, even
/// when you don't explicitly specify a table, as in the above example. If
/// you haven't provided localization for a particular string, you still get
/// reasonable behavior, because the initializer displays the key, which
/// typically contains the unlocalized string.
///
/// If you initialize a text view with a string variable rather than a
/// string literal, the view triggers the ``Text/init(_:)-9d1g4``
/// initializer instead, because it assumes that you don't want localization
/// in that case. If you do want to localize the value stored in a string
/// variable, you can choose to call the `init(_:tableName:bundle:comment:)`
/// initializer by first creating a ``LocalizedStringKey`` instance from the
/// string variable:
///
/// Text(LocalizedStringKey(someString)) // Localizes the contents of `someString`.
///
/// If you have a string literal that you don't want to localize, use the
/// ``Text/init(verbatim:)`` initializer instead.
///
/// - Parameters:
/// - key: The key for a string in the table identified by `tableName`.
/// - tableName: The name of the string table to search. If `nil`, use the
/// table in the `Localizable.strings` file.
/// - bundle: The bundle containing the strings file. If `nil`, use the
/// main bundle.
/// - comment: Contextual information about this key-value pair.
public init(_ key: LocalizedStringKey, tableName: String? = nil, bundle: Bundle? = nil, comment: StaticString? = nil)
I would recommend to use the following (tested with Xcode 12.1 / iOS 14.1)
struct SettingsNavLinkView: View {
var label: String
var body: some View {
Text(LocalizedStringKey(label)) // << inline !!
}
}
推荐阅读
- c++ - 在 C++ 中使用阶乘级数评估 sin 函数
- r - 有谁知道为什么 R 中的鼠标包在不同的方法上给我一个错误?
- c++ - X86 架构 - 使用 unsigned long long 设置向量大小
- java - 使用 Viewpager 显示来自网络的图像,但它没有显示给我,有人帮我解决这个问题
- javascript - 如何保存 JavaScript 输出并同时显示它们?
- android - 如何在我的gridview builder列表末尾添加“添加更多”按钮,我不断收到错误消息
- excel - 在 Excel 中发送 cmd 消息
- r - R逻辑回归 - 错误消息
- python - Pyinstaller python to .exe没有在命令行界面上显示任何输出
- php - 每次打开新终端时如何让laravel自动运行?