String(localized:) 没有单独的键和值?

String(localized:) has no separate key and value?

iOS15 中的新功能,我们受邀使用此字符串初始化方法在我们的 Swift 代码中创建可本地化的字符串:

init(localized keyAndValue: String.LocalizationValue, 
    table: String? = nil, bundle: Bundle? = nil, 
    locale: Locale = .current, comment: StaticString? = nil)

麻烦的是,正如内部名称所暗示的那样,第一个参数同时用于键和值。您可以从这个本地化的法语字符串文件中看到:

/* Alert message: Report a tap */
"You tapped me!" = "Vous m'avez tapé!";

我说的结果

String(localized:"You tapped me!", comment: "Alert message: Report a tap")

并本地化为法语。

完全错了!这应该是一个键值对列表;我们不应该使用面向用户的英文文本作为 key.

一方面,如果我们现在更改 String(localized:comment:) 调用中的英文文本,我们的法语翻译将会中断。此外,我们将无法对在不同上下文中使用的相同英文文本进行不同的法语翻译。

我们应该怎么办?

我认为这是 String(localizable:) 中的一个主要错误。如果我们使用 NSLocalizedString,我们将有单独的 key:value: 参数。 String(localizable:) 需要那个。

我可以想到两个解决方法。一是:不要使用String(localizable:)。继续使用 NSLocalizedString。

另一个是针对英语进行明确的本地化。不要输入面向用户的英文文本作为 localized: 参数,而是输入一个关键字符串。然后,为了防止键出现在用户界面中,导出英文本地化并将键“翻译”成所需的面向用户的英文文本。现在导入本地化以生成正确的英文 .strings 文件。

(如果您的开发语言不是英语,请将开发语言替换为这些说明。)

现在,当您导出不同的本地化版本(例如法语)时,<trans-unit> 元素的 id 值是关键,翻译者不会注意它,而 <source> 是英语,翻译人员及时翻译。

以后要更改面向用户的英文文本,请编辑英文 Localizable.strings 文件 — 而不是代码。什么都不会破坏,因为密钥保持不变。

我在使用 SwiftGen 生成我的本地化字符串时遇到了同样的问题,我的解决方案是确保我生成的本地化字符串文件位于适当的语言文件夹中,而不是单独的 Generated 否则我会使用的文件夹。

在我看来,使用键的显式本地化方法是正确的方法,我认为参数名称 keyAndValue 只是误导。

查看另一个使用 String.LocalizationValue 的初始化器,用于 AttributedString:

https://developer.apple.com/documentation/foundation/attributedstring/3867590-init

在那一个上,参数只是命名为键:

init(localized key: String.LocalizationValue, options: AttributedString.FormattingOptions = [], table: String? = nil, bundle: Bundle? = nil, locale: Locale? = nil, comment: StaticString? = nil)

毕竟,这似乎与 SwiftUI 对 LocalizedStringKey 的用法非常吻合,其中键旁边也没有给出任何值。

除了目前缺乏文档之外,我不明白有必要引入 String.LocalizationValue 和提到的 LocalizedStringKey 但至少它似乎与它在 SwiftUI 中的完成方式一致,但不是从以前的 localizedString(forKey:value:table) / NSLocalizedString 方式。

在我最近的项目中,我们总是使用 key-based 翻译,即使是对于开发语言,所以这个新的初始化器会工作得很好。但是 Apple 应该更改参数名称并相应地更新文档,就像他们为 AttributedString.

所做的那样