我的应用程序应该支持运行时语言更改。我正在使用 SwiftGen 5.0。 ViewController 订阅语言更改通知,并且我已检查本地化功能是否正确触发。我的重写
tr
函数如下所示:
fileprivate static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
guard let bundle = LanguageManager.shared.bundle else {
fatalError("Cannot find bundle!")
}
let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "")
let locale = Locale(identifier: LanguageManager.shared.currentLanguageKey!)
return String(format: format, locale: locale, arguments: args)
}
bundle
设置如下:
if let path = Bundle.main.path(forResource: currentLanguageKey, ofType: "lproj") {
bundle = Bundle(path: path)
}
但是,
tr
函数主要返回以前的语言字符串。当前内存中的所有标签中只有一个会刷新。在函数内部设置断点并打印 bundle
返回
NSBundle </var/containers/Bundle/Application/ED5A6C7D-1807-4319-8817-45E693BC45E2/MyApp.app/en_US.lproj> (not yet loaded)
这是正确的新语言。应用程序重新启动后,语言设置正确。我是不是做错了什么?
好的,我发现问题了。模板正在生成静态变量:
static let label = L10n.tr("Localizable", "registration_verify.pin_code.label")
更改模板以生成计算属性修复了该行为:
static var label: String {
return L10n.tr("Localizable", "registration_verify.pin_code.label")
}
现在您可以在 swiftgen.yml 文件中配置 LookupFunction 参数
strings:
inputs:
- en.lproj
outputs:
- templateName: structured-swift5
params:
lookupFunction: Localize_Swift_bridge(forKey:table:fallbackValue:)
output: L10n-Constants.swift
在你的项目中你只需要实现lookupFunction, 您可以使用 Localize_Swift 库
import Localize_Swift;
func Localize_Swift_bridge(forKey:String,table:String,fallbackValue:String)->String {
return forKey.localized(using: table);
}
生成的代码可能像这样:
internal enum Localizable {
internal static var baseConfig: String { return
L10n.tr("Localizable", "base config", fallback: #"Base Config"#) }}
extension L10n {
private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String {
let format = Localize_Swift_bridge(forKey:table:fallbackValue:)(key, table, value)
return String(format: format, locale: Locale.current, arguments: args)
}
}
https://github.com/SwiftGen/SwiftGen/blob/stable/Documentation/templates/strings/structed-swift5.md
我在 Swift 应用程序中遇到了由运行时本地化/语言更改引起的相同问题。为了解决这个问题,我遵循 Kacper's 解决方案并扩展了内部扩展,如下所述:
原点模板:
// MARK: - Implementation Details
extension {{enumName}} {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
// Default Setup
{% if param.lookupFunction %}
let format = {{ param.lookupFunction }}(key, table)
{% else %}
let format = {{param.bundle|default:"Bundle.main"}}.localizedString(forKey: key, value: nil, table: table)
{% endif %}
return String(format: format, locale: Locale.current, arguments: args)
}
}
修改后的模板:
// MARK: - Implementation Details
extension {{enumName}} {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
// Custom Setup
let storedLanguages = ["de", "en"]
if let languages = UserDefaults.standard.array(forKey: "AppleLanguages") as? [String],
let language = languages.first,
storedLanguages.contains(language),
{% if param.lookupFunction %}
let path = {{ param.lookupFunction }}.path(forResource: language, ofType: "lproj"),
{% else %}
let path = {{param.bundle|default:"Bundle.main"}}.path(forResource: language, ofType: "lproj"),
{% endif %}
let bundle = Bundle(path: path)
{
return bundle.localizedString(forKey: key, value: nil, table: nil)
}
// Default Setup
{% if param.lookupFunction %}
let format = {{ param.lookupFunction }}(key, table)
{% else %}
let format = {{param.bundle|default:"Bundle.main"}}.localizedString(forKey: key, value: nil, table: table)
{% endif %}
return String(format: format, locale: Locale.current, arguments: args)
}
}
其想法是使应用程序能够立即利用新解决的本地化表,而不需要任何重新启动或重新打开。我还使用了Kacper的解决方案:
static var label: String {
return L10n.tr("Localizable", "registration_verify.pin_code.label")
}
原点模板:
{{accessModifier}}static let {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{enumName}}.tr("{{table}}", "{{string.key}}")
修改后的模板:
{{accessModifier}}static var {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}: String { {{enumName}}.tr("{{table}}", "{{string.key}}") }