Swift 包管理器本地化

标签 swift localization swift-package-manager

我想知道本地化如何与 swift 包一起使用。我看到了 WWDC20/10169 视频 - Swift 包:资源和本地化 .我正在尝试在我自己的项目中做同样的事情。
如果我做相同的配置(如 WWDC 视频)并添加 .environment(\.locale, Locale(identifier: "es"))View预览,它有效(但仅在 sp 内部测试时)。
当我尝试在实际应用程序中使用本地化资源时,问题就开始了。
这个过程非常简单 - 我只是使用一个 View ,其中包含来自应用程序包中的本地化字符串。出于测试目的,我使用特定的语言环境(方案设置)启动我的应用程序 - 结果,我总是得到 en翻译。
我的 list :

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"]),
  ]
)
包的结构:
Structure of the packageresource_bundle_accessor生成良好 - 所以我可以访问 Bundle.module ,实际上我可以按预期列出所有本地化 - enes .
我还在项目本身中添加了支持的语言:
Supported languages
这是一个快速演示:
demo
为了生成本地化字符串,我想使用 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 内):
testLocalization.app
这是一个 link for project .
所以我的问题 - 我做错了什么?错误在哪里?

最佳答案

我找到了这个问题的原因 - 应用本身需要本地化并在项目设置中设置它是不够的,相反,我们还应该添加 CFBundleLocalizations在 info plist 中,将所需的本地化作为字符串数组。即使在官方文档中说只支持少数本地化,我们也可以在那里添加额外的本地化(使用与 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 是正确的解决方案” - 来自 SDGGiesbrecht

关于Swift 包管理器本地化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66694610/

相关文章:

iphone - 从应用程序包中获取本地化文件?

reporting-services - 格式编号 Rdlc 报告

Android WebView 国际化

ios - Xcode 12 - 当有另一个 Swift 包作为依赖项时,SwiftUI 预览在 Swift 包上不起作用 - 'previewInstances' 给代理的消息

swift - 生成的 swift 包中的 XCTestManifests

objective-c - 无法在 SwiftPM 的 ObjC 模块中导入 AppKit

ios - 如何在编辑表格 View 单元格中的文本字段时重新加载所有表格 View 单元格 - iOS Swift

objective-c - 使用 Swift CFunctionPointer 将回调传递给 CoreMIDI API

swift - 使用 Swift 查找字符串中的第一个非重复字符

ios - 如何在 iOS Swift 中将图像从框架发送到示例项目?