Что такое эквивалент NSLocalizedString в Swift?

есть ли быстрый эквивалент NSLocalizedString(...)? В Objective-C, мы обычно используем:

NSString *string = NSLocalizedString(@"key", @"comment");

как я могу достичь того же в Swift? Я нашел функцию:

func NSLocalizedString(
    key: String,
    tableName: String? = default,
    bundle: NSBundle = default,
    value: String = default,
    #comment: String) -> String

однако, это очень долго и совсем не удобно.

14 ответов


Я использую следующее решение:

1) создать расширение:

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}

2) в локализации.струны:

"Hi" = "Привет";

3) Пример использования:

myLabel.text = "Hi".localized

наслаждайтесь! ;)

--upd:--

в случае с комментариями вы можете использовать это решение:

1 расширение):

extension String {
    func localized(withComment:String) -> String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: withComment)
    }
}

2) in .файл строк:

/* with !!! */
"Hi" = "Привет!!!";

3), используя:

myLabel.text = "Hi".localized(withComment: "with !!!")

на NSLocalizedString существует также в мире Swift.

func NSLocalizedString(
    key: String,
    tableName: String? = default,
    bundle: NSBundle = default,
    value: String = default,
    #comment: String) -> String

на tableName, bundle и value параметры отмечены знаком default ключевое слово, которое означает, что мы можем опустить эти параметры при вызове функции. В этом случае будут использоваться значения по умолчанию.

это приводит к выводу, что вызов метода можно упростить до:

NSLocalizedString("key", comment: "comment")

используя этот способ, можно создать другую реализацию для разных типов (например, Int или пользовательские классы, такие как CurrencyUnit,...). Его также можно сканировать для этого метода вызова с помощью утилиты genstrings. Просто добавьте флаг routine в команду

genstrings MyCoolApp/Views/SomeView.swift -s localize -o .

вариация существующих ответов:

Swift 4:

extension String {

    func localized(withComment comment: String? = nil) -> String {
        return NSLocalizedString(self, comment: comment ?? "")
    }

}

затем вы можете просто использовать его с или без комментария:

"Goodbye".localized()
"Hello".localized(withComment: "Simple greeting")

обратите внимание, что genstrings не работать с этим решением.


создал небольшой вспомогательный метод для случаев, когда "комментарий" всегда игнорируется. Меньше кода легче читать:

public func NSLocalizedString(key: String) -> String {
    return NSLocalizedString(key, comment: "")
}

просто поместите его в любом месте (вне класса) и Xcode найдете этот глобальный метод.


Swift 3 версия :)...

import Foundation

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}

наверное, самый лучший способ это здесь.

fileprivate func NSLocalizedString(_ key: String) -> String {
    return NSLocalizedString(key, comment: "")
}

и

import Foundation
extension String {
    static let Hello = NSLocalizedString("Hello")
    static let ThisApplicationIsCreated = NSLocalizedString("This application is created by the swifting.io team")
    static let OpsNoFeature = NSLocalizedString("Ops! It looks like this feature haven't been implemented yet :(!")
}

вы можете использовать его следующим образом

let message: String = .ThisApplicationIsCreated
print(message)

для меня это лучше, потому что

  • жестко закодированные строки находятся в одном конкретном файле, поэтому в день, когда вы хотите изменить его, это очень легко
  • проще в использовании, чем вручную вводить строки в файл каждый раз
  • genstrings все еще будет работать
  • вы можете добавьте больше расширений, как один на контроллер вида, чтобы держать вещи аккуратными

на самом деле, вы можете использовать два этапа для перевода текстов в проектах Swift:

1) Первый этап использует старый способ создания всех ваших переводимых строк:

NSLocalisedString("Text to translate", comment: "Comment to comment")

1.1), то вы должны использовать genstrings для создания локализации.строки:

$ genstrings *swift

2) После этого вы должны использовать это ответ.

2.1) используйте опцию XCode "найти и заменить" на основе регулярного выражения. Что касается данного примера (если вы без комментариев) регулярное выражение будет:

NSLocalizedString\((.*)\, comment:\ \"\"\) 

и заменить

.localized

или (если у вас есть замечания)

NSLocalizedString\((.*)\, comment:\ (.*)\)

и заменить

.localizedWithComment(comment: )

вы можете играть с регулярным выражением и различными комбинациями расширений, как вы хотите. Общий способ-разделить весь процесс на две фазы. Надеюсь, это поможет.


когда вы разрабатываете SDK. Тебе нужна дополнительная операция.

1) создать локализации.струны как обычно в YourLocalizeDemoSDK.

2) Создайте то же самое локализации.струны в YourLocalizeDemo.

3) найти Bundle Path из YourLocalizeDemoSDK.

Swift4:

// if you use NSLocalizeString in NSObject, you can use it like this
let value = NSLocalizedString("key", tableName: nil, bundle: Bundle(for: type(of: self)), value: "", comment: "")

Bundle(for: type(of: self)) помогает найти пакет в YourLocalizeDemoSDK. Если вы используете Bundle.main вместо этого вы получите неправильное значение(на самом деле это будет та же строка с ключом).

но если вы хотите использовать расширение строки, упомянутые доктор ОКС. Тебе нужно сделать еще кое-что. Расширение origin выглядит так.

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}

как мы знаем, мы разрабатываем SDK,Bundle.main получит пакет пакета YourLocalizeDemo. Это не то, чего мы хотим. Нам нужен пакет в YourLocalizeDemoSDK. Это трюк, чтобы найти его. быстро.

запустите приведенный ниже код в экземпляре NSObject в YourLocalizeDemoSDK. И вы получите URL-адрес YourLocalizeDemoSDK.

let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL

распечатайте оба url-адреса, вы обнаружите, что мы можем построить базу bundleURLofSDK на mainBundleURL. В этом случае, это будет:

let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main

и расширение строки будет:

extension String {
    var localized: String {
        let bundle = Bundle(url: Bundle.main.bundleURL.appendingPathComponent("Frameworks").appendingPathComponent("YourLocalizeDemoSDK.framework")) ?? Bundle.main
        return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "")
    }
}

надеюсь, что это помогает.


Я создал свой собственный genstrings своего рода инструмент для извлечения строк с помощью пользовательской функции перевода

extension String {

    func localizedWith(comment:String) -> String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: comment)
    }

}

https://gist.github.com/Maxdw/e9e89af731ae6c6b8d85f5fa60ba848c

он проанализирует все ваши swift-файлы и экспортирует строки и комментарии в вашем коде в a .файл строк.

наверное, не самый простой способ сделать это, но это возможно.


хотя это не отвечает на проблему сокращения, но это помогло мне организовать сообщения, я создал структуру для сообщений об ошибках, как показано ниже

struct Constants {
    // Error Messages
    struct ErrorMessages {
        static let unKnownError = NSLocalizedString("Unknown Error", comment: "Unknown Error Occured")
        static let downloadError = NSLocalizedString("Error in Download", comment: "Error in Download")
    }
}

let error = Constants.ErrorMessages.unKnownError

таким образом, вы можете организовать сообщения и сделать genstrings работы.

и это команда genstrings используется

find ./ -name \*.swift -print0 | xargs -0 genstrings -o .en.lproj

полезно для использования в модульных тестах:

Это простая версия, которая может быть расширена до различных случаев использования (например, с использованием табличных имен).

public func NSLocalizedString(key: String, referenceClass: AnyClass, comment: String = "") -> String 
{
    let bundle = NSBundle(forClass: referenceClass)
    return NSLocalizedString(key, tableName:nil, bundle: bundle, comment: comment)
}

используйте его так:

NSLocalizedString("YOUR-KEY", referenceClass: self)

или такой комментарий:

NSLocalizedString("YOUR-KEY", referenceClass: self, comment: "usage description")

локализация с языком по умолчанию:

extension String {
func localized() -> String {
       let defaultLanguage = "en"
       let path = Bundle.main.path(forResource: defaultLanguage, ofType: "lproj")
       let bundle = Bundle(path: path!)

       return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
    }
}

при переводе, скажем, с английского языка, где фраза одна и та же, на другой язык, где она отличается (из-за Пола, спряжения глаголов или склонения) простой форма NSString в Swift, которая работает во всех случаях, - это три аргумента. Например, английская фраза "previous was", по-разному переводится на русский язык для случая" weight "("предыдущий был") и для "талии" ("предыдущая была").

в этом случае вам нужно два разных перевода для одного источника (с точки зрения инструмента XLIFF, рекомендованного в WWDC 2018). Вы не можете достичь этого с помощью двух аргументов NSLocalizedString, где " предыдущий был "будет одинаковым как для" ключа", так и для английского перевода (т. е. для значения). Единственный способ-использовать форму трех аргументов

NSLocalizedString("previousWasFeminine", value: "previous was", comment: "previousWasFeminine")

NSLocalizedString("previousWasMasculine", value: "previous was", comment: "previousWasMasculine")

где ключи ("previousWasFeminine "и" previousWasMasculine") различны.

I знаю, что общий совет, перевести фразу в целом, однако, иногда это слишком трудоемко и неудобно.