Swift 包管理器本地化

Swift package manager localization

我想知道本地化是如何与 swift 包一起工作的。我看了 WWDC20/10169 视频 - Swift 软件包:资源和本地化 。我正在尝试在我自己的项目中做同样的事情。

如果我进行相同的配置(如 WWDC 视频)并将 .environment(\.locale, Locale(identifier: "es")) 添加到 View 预览,它会起作用(但仅当在 sp 中测试时)。

当我尝试在实际应用程序中使用本地化资源时,问题就开始了。 这个过程非常简单 - 我只是使用一个视图,其中包含应用程序内部包中的本地化字符串。出于测试目的,我使用特定区域设置(方案设置)启动我的应用程序 - 结果,我总是得到 en 翻译。

我的清单:

let package = Package(
  name: "MyLibrary",
  defaultLocalization: "en",
  platforms: [
    .iOS(.v14),
  ],
  products: [
    .library(
      name: "MyLibrary",
      targets: ["MyLibrary"]),
  ],
  dependencies: [
  ],
  targets: [
    .target(
      name: "MyLibrary",
      dependencies: [],
      path: "Sources"
    ),
    .testTarget(
      name: "MyLibraryTests",
      dependencies: ["MyLibrary"]),
  ]
)

包的结构:

resource_bundle_accessor 生成得很好 - 所以我可以访问 Bundle.module,实际上我可以按预期列出所有本地化 - enes.

我还在项目本身中添加了支持的语言:

这是一个快速演示:

为了生成本地化字符串,我想使用 SwiftGen:

extension L10n {
  private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
    let format = BundleToken.bundle.localizedString(forKey: key, value: nil, table: table)
    return String(format: format, locale: Locale.current, arguments: args)
  }
}

// swiftlint:disable convenience_type
private final class BundleToken {
  static let bundle: Bundle = {
    #if SWIFT_PACKAGE
    return Bundle.module
    #else
    return Bundle(for: BundleToken.self)
    #endif
  }()
}
// swiftlint:enable convenience_type

或者,我测试了

let text = NSLocalizedString("welcome", tableName: "Localizable", bundle: .module, value: "", comment: "")

或类似 Bundle - Bundle.module.localizedString 方法和 SwiftUI Text("welcome", bundle: .module).

结果相同 - 它不会改变语言 - 我总是得到开发语言 - en

我也可以确认,构建包含本地化(在 lib 包的 testLocalization.app 内):

这是一个link for project.

那么我的问题 - 我做错了什么?哪里出错了?

我找到了这个问题的原因 - 应用程序本身需要本地化并在项目设置中设置它是不够的,相反,我们还应该在信息 plist 中添加 CFBundleLocalizations 并将所需的本地化作为字符串数组.即使在官方文档中说它只支持少数本地化,我们也可以在那里添加额外的本地化(使用与 lproj 文件夹相同的语言环境代码),一切都会正常。

<key>CFBundleLocalizations</key>
<array>
    <string>en</string>
    <string>es</string>
    <string>uk-UA</string>
</array>

来自旧的过时文档:

An application can notify the system that it supports additional localizations through its information property list (Info.plist) file. To specify localizations not included in your bundle’s .lproj directories, add the CFBundleLocalizations key to this file. The value for the key is an array of strings, each of which contains an ISO language designator as described in “Language and Locale Designations.”

像往常一样,Apple 没有在任何与 SP 相关的文档中提及这一点...

-----更新

正确的解决方案是 ”在应用程序的 Info.plist 中将 CFBundleAllowMixedLocalizations 设置为 YES 是正确的解决方案 - 来自SDGGiesbrecht