什么是Swift中的NSLocalizedString等价物?

时间:2014-08-01 13:48:48

标签: ios swift localization nslocalizedstring

是否有一个等同于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

然而,它很长很不方便。

17 个答案:

答案 0 :(得分:357)

我使用下一个解决方案:

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

答案 1 :(得分:266)

NSLocalizedString也存在于Swift的世界中。

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

tableNamebundlevalue参数标有 default 关键字,这意味着我们可以在调用时忽略这些参数功能。在这种情况下,将使用它们的默认值。

这导致结论是方法调用可以简化为:

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

答案 2 :(得分:18)

现有答案的变体:

Swift 4.2:

extension String {

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

}

然后您可以在有或没有评论的情况下使用它:

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

请注意genstrings无法使用此解决方案。

答案 3 :(得分:11)

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

答案 4 :(得分:7)

为案例创建了一个小帮助方法,其中&#34;评论&#34;总是被忽略。更少的代码更容易阅读:

select count(*) from something

只需将它放在任何地方(课外),Xcode就会找到这种全局方法。

答案 5 :(得分:7)

Swift 3版本:)...

import Foundation

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

答案 6 :(得分:5)

可能最好的方法是here

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仍然可以使用
  • 您可以添加更多扩展程序,例如每个视图控制器一个以保持整洁

答案 7 :(得分:4)

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

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

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

1.1)然后你应该使用genstrings来生成Localizable.strings:

$ genstrings *swift

2)之后,您应该使用此answer

2.1)根据正则表达式使用XCode“查找和替换”选项。 至于给定的例子(如果你没有评论),正则表达式将是:

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

并将其替换为

$1.localized

或(如果您有评论)

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

并将其替换为

$1.localizedWithComment(comment: $2)

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

答案 8 :(得分:2)

在开发SDK时。您需要一些额外的操作。

1)像往常一样在YourLocalizeDemoSDK中创建 Localizable.strings

2)在YourLocalizeDemo中创建相同的 Localizable.strings

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,则会得到错误的值(实际上,它与键是相同的字符串)。

但是,如果您想使用dr OX提到的String扩展名。您还需要做更多。原点扩展名看起来像这样。

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

我们知道,我们正在开发一个SDK,Bundle.main将获得YourLocalizeDemo的捆绑包。那不是我们想要的。我们需要YourLocalizeDemoSDK中的捆绑软件。这是一种快速找到它的技巧。

在YourLocalizeDemoSDK的NSObject实例中运行以下代码。然后,您将获得YourLocalizeDemoSDK的URL。

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

同时打印两个URL,您会发现我们可以基于mainBundleURL构建SDK的bundleURL。在这种情况下,它将是:

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

希望有帮助。

答案 9 :(得分:1)

我创建了自己的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文件,并将代码中的字符串和注释导出到.strings文件中。

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

答案 10 :(得分:1)

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

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

答案 11 :(得分:1)

有助于在单元测试中使用

这是一个简单的版本,可以扩展到不同的用例(例如使用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")

答案 12 :(得分:1)

这是对“ .localized”方法的改进。首先添加类扩展名,因为这将有助于您以编程方式设置的任何字符串:

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)

现在Xcode的情节提要翻译文件使文件管理器变得混乱,也无法很好地处理情节提要的更新。更好的方法是创建一个新的基本标签类,并将其分配给所有情节提要标签:

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()
    }
}

现在,假设您已为其提供了翻译,则在情节提要中添加并为其提供默认默认值的每个标签都将自动翻译。

您可以对UIButton做同样的事情

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

答案 13 :(得分:0)

当你翻译时,比较用英语,短语是相同的,到另一种不同的语言(因为性别,动词结合或变化) 最简单的 < / strong> Swift中的NSString形式在所有情况下都适用于三个参数之一。例如,英语短语“previous was”,对于“weight”(“предыдущийбыл”)和“腰”(“предыдущая< / strong>была“)。

在这种情况下,您需要为一个来源进行两种不同的翻译(根据WWDC 2018中推荐的XLIFF工具)。你不能用两个参数NSLocalizedString来实现它,其中“previous is”对于“key”和英语翻译(即对于值)都是相同的。唯一的方法是使用三个参数形式

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

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

其中键(“previousWasFeminine”和“previousWasMasculine”)不同。

我知道一般的建议是将整个短语翻译成一个整体,但是,有时它太耗费时间和不方便。

答案 14 :(得分:0)

使用默认语言进行本地化:

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

答案 15 :(得分:0)

除了伟大的扩展写 here 如果你懒得查找和替换旧的 NSLocalizedString 你可以在 Xcode 中打开查找和替换,在查找部分你可以写 NSLocalizedString\(\(".*"\), comment: ""\) 然后在替换部分,您需要编写 $1.localized 以将项目中的所有 NSLocalizedString 更改为 "blabla".localized

答案 16 :(得分:0)

没有足够的声誉来评论我对@Kay 的 fantastic solution 的附加内容:

对于 SwiftUI:

elseo

没有genstrings -SwiftUI *.swift -s localize -o . ,它只会解析-SwiftUI内的那个