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

Существует ли 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

Однако он очень длинный и совсем не удобный.

Ответ 1

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")

Swift 5 - без изменений, все так же работает.

Ответ 2

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

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

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

2) в файле Localizable.strings:

"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) в файле .strings:

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

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

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

Ответ 3

Вариант существующих ответов:

Swift 5.1:

extension String {

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

}

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

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

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

Ответ 4

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

genstrings MyCoolApp/Views/SomeView.swift -s localize -o .
Расширение

:

import UIKit

extension String {
    public static func localize(key: String, comment: String) -> String {
        return NSLocalizedString(key, comment: comment)
    }
}

использование:

String.localize("foo.bar", comment: "Foo Bar Comment :)")

Ответ 5

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

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

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

Ответ 6

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

import Foundation

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

Ответ 7

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

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 все еще будет работать
  • Вы можете добавить больше расширений, например, по одному на контроллер каждого представления, чтобы все было в порядке

Ответ 8

На самом деле вы можете использовать две фазы для перевода ваших текстов в проекты Swift:

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

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

1.1) Затем вы должны использовать genstrings для генерации Localizable.strings:

$ genstrings *swift

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

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

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

и замените его на

$1.localized

или (если у вас есть комментарии)

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

и замените его на

$1.localizedWithComment(comment: $2)

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

Ответ 9

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

1) создайте Localizable.strings как обычно в YourLocalizeDemoSDK.

2) создайте те же Localizable.strings в YourLocalizeDemo.

3) найдите свой путь к пакету 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, вы получите неправильное значение (фактически это будет та же строка с ключом).

Но если вы хотите использовать расширение String, упомянутое доктором OX. Вам нужно сделать еще немного. Исходное расширение выглядит следующим образом.

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

И расширение String будет:

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: "")
    }
}

Надеюсь, поможет.

Ответ 10

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

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

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")

Ответ 11

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

extension String {

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

}

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

Он будет анализировать все ваши быстрые файлы и экспортировать строки и комментарии в ваш код в файл .strings.

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

Ответ 12

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

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

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

Ответ 13

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

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

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

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

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

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

Ответ 14

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

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: "")
    }
}