Ios 什么';s NSLocalizedString在Swift中的等效值?

Ios 什么';s NSLocalizedString在Swift中的等效值?,ios,swift,localization,nslocalizedstring,Ios,Swift,Localization,Nslocalizedstring,是否有类似于NSLocalizedString(…)的Swift? 在Objective-C中,我们通常使用: NSString *string = NSLocalizedString(@"key", @"comment"); 如何在Swift中实现同样的目标?我发现了一个函数: func NSLocalizedString( key: String, tableName: String? = default, bundle: NSBundle = default,

是否有类似于NSLocalizedString(…)的Swift? 在
Objective-C
中,我们通常使用:

NSString *string = NSLocalizedString(@"key", @"comment");
如何在Swift中实现同样的目标?我发现了一个函数:

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

但是,它很长,一点也不方便。

Swift的世界中也存在着
NSLocalizedString

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-没有变化,仍然可以这样工作。

我使用下一个解决方案:

1) 创建扩展名:

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}
2) 在可本地化的.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) 使用:


通过使用这种方式,可以为不同的类型创建不同的实现(即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 :)")

为始终忽略“注释”的情况创建了一个小的辅助方法。代码越少,越容易阅读:

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

只要把它放在任何地方(类之外),Xcode就会找到这个全局方法。

在单元测试中使用的帮助信息:

extension String {

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

}
这是一个简单的版本,可以扩展到不同的用例(例如使用表名)

像这样使用它:

NSLocalizedString("YOUR-KEY", referenceClass: self)
或者像这样加上一句评论:

NSLocalizedString("YOUR-KEY", referenceClass: self, comment: "usage description")
Swift 3版本:)


当你需要翻译时,比如说从一个短语相同的英语翻译到另一个不同的语言(因为性别、动词变位或变位)Swift中最简单的、适用于所有情况的字符串形式是三个参数一。例如,英语短语“previous was”在“weight”(重量)和“腰围”(腰围)的翻译与俄语不同

在这种情况下,一个源需要两种不同的翻译(根据WWDC 2018中推荐的XLIFF工具)。您无法使用两个参数NSLocalizedString实现它,其中“键”和英文翻译(即值)的“previous was”将是相同的。唯一的方法是使用三参数形式

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

NSLocalizedString("previousWasMasculine", value: "previous was", comment: "previousWasMasculine")
其中键(“PreviousWasNegimal”和“PreviousWasMangimal”)不同


我知道一般的建议是把这个短语作为一个整体来翻译,然而,有时它太费时和不方便。

也许最好的方法就是这个方法

你可以这样使用它

let message: String = .ThisApplicationIsCreated
print(message)
对我来说这是最好的,因为

  • 硬编码字符串位于一个特定的文件中,因此在您想要更改它的那天,它非常容易
  • 比每次在文件中手动键入字符串更容易使用
  • 发电机串仍能工作
  • 您可以添加更多扩展,例如每个视图控制器一个扩展,以保持整洁

实际上,在Swift项目中,您可以使用两个阶段来翻译文本:

1) 第一阶段是使用旧方法创建所有可翻译字符串:

NSLocalisedString("Text to translate", comment: "Comment to comment")
1.1)然后应使用genstring生成可本地化的.strings:

$ genstrings *swift
2) 之后,你应该使用这个

2.1)使用基于正则表达式的XCode“查找并替换”选项。 对于给定的示例(如果没有注释),正则表达式将是:

NSLocalizedString\((.*)\, comment:\ \"\"\) 
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: "")
    }
}
并将其替换为

$1.localized
$1.localizedWithComment(comment: $2)
或者(如果您有意见)

并将其替换为

$1.localized
$1.localizedWithComment(comment: $2)

您可以随意使用正则表达式和不同的扩展组合。一般的方法是将整个过程分为两个阶段。希望这能有所帮助。

我已经创建了自己的GenString类工具,用于使用自定义翻译函数提取字符串

extension String {

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

}

它将解析所有swift文件,并将代码中的字符串和注释导出到.strings文件


这可能不是最简单的方法,但它是可能的。

虽然这不能解决缩短问题,但这有助于我组织消息,我为错误消息创建了一个结构,如下所示

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
这样可以组织消息并使genstring工作

这是使用的genstrings命令

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

现有答案的变化:

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
不能与此解决方案一起使用。

当您开发SDK时。你需要做些额外的手术

1) 像往常一样在LocalizeDemoSDK中创建可本地化的.strings

let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL
2) 在LocalizeDemo中创建相同的可本地化字符串

3) 找到LocalizeDemoSDK的捆绑路径

let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL
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))
帮助您在LocalizeDemoSDK中找到该Bundle。如果改用
Bundle.main
,则会得到一个错误的值(实际上,它与键是同一个字符串)

但是如果您想使用中提到的字符串扩展名。你需要多做一些。原点扩展如下所示

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}
正如我们所知,我们正在开发一个SDK,
Bundle.main将获得YourLocalizeDemo的Bundle包。这不是我们想要的。我们需要您的本地化DemoSDK中的捆绑包。这是一个快速找到它的技巧

在LocalizeDemoSDK中的NSObject实例中运行以下代码。您将获得LocalizeDemoSDK的URL

let bundleURLOfSDK = Bundle(for: type(of: self)).bundleURL
let mainBundleURL = Bundle.main.bundleURL
打印这两个url,您将发现
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: "")
    }
}
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: "")
    }
}
extension String {
    func localized (bundle: Bundle = .main, tableName: String = "Localizable") -> String {
        return NSLocalizedString(self, tableName: tableName, value: "\(self)", comment: "")
    }
}
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
class BasicLabel: UILabel {
    //initWithFrame to init view from code
    override init(frame: CGRect) {
      super.init(frame: frame)
      setupView()
    }

    //initWithCode to init view from xib or storyboard
    required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      setupView()
    }

    //common func to init our view
    private func setupView() {
        let storyboardText = self.text
        text = storyboardText?.localized()
    }
}
class BasicBtn: UIButton {
    //initWithFrame to init view from code
    override init(frame: CGRect) {
      super.init(frame: frame)
      setupView()
    }

    //initWithCode to init view from xib or storyboard
    required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      setupView()
    }

    //common func to init our view
    private func setupView() {
        let storyboardText = self.titleLabel?.text
        let lclTxt = storyboardText?.localized()
        setTitle(lclTxt, for: .normal)
    }
}
genstrings -SwiftUI *.swift -s localize -o .