Динамическое изменение файла локализации в swift

#swift #localization

Вопрос:

Я использую немецкий язык в своем приложении, и существует два типа обращения к человеку «Du» и «Sie». Я хотел бы добавить в свой проект еще один локализуемый файл, в котором будет использоваться «Du». В принципе, я хотел бы знать, возможно ли каким-либо образом проверить, выбран ли немецкий язык и адрес «Du», и если да, использовать файл локализации «Du»? Теперь в проекте существует только файл «Sie», из которого берется локализация.

Комментарии:

1. почему бы не создать файл .strings и не добавить локализацию для другого языка, а в приложении delgate использовать функцию getLanguage, чтобы получить язык устройства и установить требуемый язык в соответствии с этим

2. Конечно! Вопрос в том, как это сделать? Locale.currentLahguage является { get } только property. Было бы неплохо, если бы вы могли поделиться фрагментом кода для этого.

Ответ №1:

Найдено решение этой проблемы, описанное здесь: принудительная локализация iOS во время выполнения. Однако главное, что Bundle.swizzleLocalization() должно быть вызвано в main.swift файле.

 if Locale.current.languageCode == "de" {
     let appConfig = ApplicationConfiguration()
     if appConfig.germanLanguageType == "du" {
         Bundle.swizzleLocalization()
     }
 }
 

Таким образом, в файле main.swift я проверяю предпочитаемый язык устройства, и если он немецкий, я проверяю свой appConfig.swift файл, где указано, следует ли использовать адресацию «du» или «sie» в приложении, если я вызываю «du» Bundle.swizzleLocalization()

В расширении к Bundle я просто указываю путь к локализованному файлу, который следует использовать (ранее добавленный в проект)

 extension Bundle {

    static func swizzleLocalization() {
        let orginalSelector = #selector(localizedString(forKey:value:table:))
        guard let orginalMethod = class_getInstanceMethod(self, orginalSelector) else { return }
        
        let mySelector = #selector(myLocaLizedString(forKey:value:table:))
        guard let myMethod = class_getInstanceMethod(self, mySelector) else { return }
        
        if class_addMethod(self, orginalSelector, method_getImplementation(myMethod), method_getTypeEncoding(myMethod)) {
            class_replaceMethod(self, mySelector, method_getImplementation(orginalMethod), method_getTypeEncoding(orginalMethod))
        } else {
            method_exchangeImplementations(orginalMethod, myMethod)
        }
    }
    
    @objc func myLocaLizedString(forKey key: String,value: String?, table: String?) -> String {
        guard let bundlePath = Bundle.main.path(forResource: "de-DE", ofType: "lproj"),
              let bundle = Bundle(path: bundlePath) else {
                  return Bundle.main.myLocaLizedString(forKey: key, value: value, table: table)
              }
        return bundle.myLocaLizedString(forKey: key, value: value, table: table)
    }
}