使用 SwiftGen 在运行时更改语言

问题描述 投票:0回答:3

我的应用程序应该支持运行时语言更改。我正在使用 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)

这是正确的新语言。应用程序重新启动后,语言设置正确。我是不是做错了什么?

ios swift localization internationalization
3个回答
9
投票

好的,我发现问题了。模板正在生成静态变量:

static let label = L10n.tr("Localizable", "registration_verify.pin_code.label")

更改模板以生成计算属性修复了该行为:

static var label: String { 
    return L10n.tr("Localizable", "registration_verify.pin_code.label")
}

5
投票

现在您可以在 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

https://github.com/marmelroy/Localize-Swift


0
投票

我在 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}}") }
© www.soinside.com 2019 - 2024. All rights reserved.