Swift에서 NSLocalizedString은 무엇입니까?


228

스위프트에 해당하는 것이 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

그러나 매우 길고 전혀 편리하지 않습니다.


2
가장 짧은 버전의 코드 스 니펫을 만드는 것이 가장 좋습니다 : NSLocalizedString ( "", comment : "") ... 확장 솔루션이 마음에 들지만 문제는 genstring이 이러한 문자열을 번역 파일로 캡처하지 않는다는 것입니다.
Matej Ukmar

3
Swift 3에서는 NSLocalizedString("Cancel", comment: "Cancel button title")기본값을 활용하여 사용할 수 있습니다 . 내가 생각하는 것이 편리하다.
LShi

이것은 현지화 (문자열 확장, 다른 문자열 표 및 심지어 복수화)에 관한 매우 좋은 기사입니다. medium.com/@marcosantadev/…
LightMan

이것은 강력한 아키텍처 medium.com/@mendibarouk/에
Mendy

답변:


373

다음 해결책을 사용합니다.

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

92
이것의 유일한 문제는 genstrings유틸리티를 사용하여 .strings 파일을 생성 할 수 없다는 것입니다.
Ned

9
아주 좋은 생각입니다! 나는 또한 func localized(comment: String = "") -> String더 작아지고 옵션 주석 으로 변경하여 조금 더 똑똑하게 만들었습니다 :)
Gui Moura

2
genstrings이것과 함께 사용하는 방법 이 있습니까?
Chris

48
이 답변에 대해 모두가 매우 기뻐하지만, 여러 언어를 사용하는 심각한 프로젝트의 경우 BIG 문제는 번역 된 메시지 관리를 완전히 genstrings망친다는 것입니다. NSLocalizedString에 전달 된 리터럴 문자열에서만 작동 하기 때문 입니다. 이 영리한 해결 방법으로 genstrings도구를 사용하여 .strings 파일을 업데이트하는 기능을 잃어 버릴 수 있습니다 . 적어도 저에게는이 단순화 된 접근 방식을 사용할 수 없다는 것을 의미합니다.
Erik van der Neut

14
이 훌륭한 솔루션은 github.com/marmelroy/Localize-Swift 에서 구현되었습니다 . 젠 스트링 문제는 저자가 포함한 커스텀 파이썬 스크립트로도 해결됩니다. 나는 저자가 아니다.
Tomek Cejner

279

NSLocalizedString스위프트의 세계도 존재한다.

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

tableName, bundlevalue매개 변수가 표시되는 default기능을 호출하는 동안 우리는 이러한 매개 변수를 생략 할 수 있습니다 수단 키워드. 이 경우 기본값이 사용됩니다.

이는 메소드 호출이 다음과 같이 단순화 될 수 있다는 결론으로 ​​이어집니다.

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

스위프트 5- 변화가 없지만 여전히 그렇게 작동합니다.


44
주석이 무의미하다는 것은 단지 차이점이며 자동 완성은 짧은 버전에서는 직관적이지 않습니다.
Marcin

1
이것은 더 이상 작동하지 않으며 충분한 인수가 사용되지 않았다는 오류가 발생합니다.
Apps 4 U

2
objective-c의 특정 변경 사항이있는 Xcode 6.3, Swift 1.2에서는 위의 내용이 정확하지 않지만 Marcin이 언급 한대로 주석은 0이 될 수 없지만 ""(빈) 수 있습니다.
Neil

2
주석이 없거나 비어 있으면 나중에 문자열 파일에서 문자열을 재배치하기가 어렵습니다. 주석으로 사용되는 클래스 / 파일 이름을 추가하지 않는 경우
Johan

이것이 정답입니다. Apple이 Swift 용으로 업데이트하면 Xcode는이 API를 새로운 Swift API로 자동 변환 할 수 있으며 다른 기능은 없습니다. 현재 Xcode의 Refractor 메뉴 (v 11.4.1)에서도 Wrap in NSLocalizedString텍스트를 강조 표시하고 마우스 오른쪽 단추를 클릭 한 후 메뉴 항목을 선택하여 작업을 훨씬 쉽게 수행 할 수 있는 옵션이 있습니다.
Ethan Allen

28

기존 답변의 변형 :

스위프트 5.1 :

extension String {

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

}

그런 다음 주석을 사용하거나 사용하지 않고 간단히 사용할 수 있습니다.

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

참고 사항genstrings 이 솔루션 작동하지 않습니다를.


14

이 방법을 사용하면 다른 유형 (예 : 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 :)")

이 답변은 놀랍고 더 많이 찬성해야합니다! 이것은 다른 라이브러리를 가져 오지 않으려는 경우 지금까지 찾은 가장 간단한 솔루션입니다. 이것은 좋은 기본 솔루션입니다.
cgossain

6

스위프트 3 버전 :) ...

import Foundation

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

6

실제로 두 단계를 사용하여 Swift 프로젝트에서 텍스트를 번역 할 수 있습니다.

1) 첫 번째 단계는 이전 방법을 사용하여 번역 가능한 모든 문자열을 만드는 것입니다.

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

1.1) 그런 다음 Genstring을 사용하여 Localizable.strings를 생성해야합니다.

$ genstrings *swift

2) 나중에이 답변을 사용해야합니다 .

2.1) 정규식에 따라 XCode "찾기 및 바꾸기"옵션을 사용하십시오. 주어진 예 (주석이없는 경우)의 정규 표현식은 다음과 같습니다.

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

그리고 그것을 대체하십시오

$1.localized

또는 (의견이있는 경우)

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

그리고 그것을 대체하십시오

$1.localizedWithComment(comment: $2)

원하는대로 정규식과 다른 확장 조합을 자유롭게 사용할 수 있습니다. 일반적인 방법은 전체 프로세스를 두 단계로 나누는 것입니다. 희망이 도움이됩니다.


1
죄송합니다. 여기에서 많은 답변을 얻지 못했습니다. 사용하는 방법의 장점은 무엇입니까 NSLocalizedString("Cancel", comment: "Cancel button title")?
LShi

1
@LShi 일부 사람들은 NSLocalizedStringSwiftier가 덜 보이는 것처럼 보일 것입니다. String.localized다른 한편으로는 더 깔끔해 보이지만 gesntrings국제화 작업을 쉽게하기 위해 일반적으로 사용되는 유틸리티 를 사용할 수 없습니다 . 내 요점은 두 가지 접근법을 혼합하는 것이 매우 쉽다는 것입니다. 따라서 주로 가독성 문제입니다.
GYFK

다른 라운드를 수행해야하는 경우 어떻게됩니까 genstrings? 당신은 모두에 .localized의해 다시 대체 NSLocalizedString합니까?
Cristik

5

"코멘트"가 항상 무시되는 경우에 대한 작은 도우미 메소드를 작성했습니다. 적은 코드는 읽기 쉽다 :

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

클래스 외부의 아무 곳에 나 넣으면 Xcode 가이 전역 메서드를 찾습니다.


12
이것은 나쁜 습관입니다. 모든 번역을 직접 수행하지 않는 한 주석이 권장되고 유용합니다.
예레미아

자신을 번역하더라도 주석은 특히 큰 프로젝트에서 도움이 될 것입니다.
shim

4

아마도 가장 좋은 방법은이 방법 일 입니다.

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는 여전히 작동합니다
  • 보기 컨트롤러 당 하나씩 확장 기능을 추가하여 깔끔하게 유지

3
설명 된 방식으로 정의 된 문자열은 정적 문자열입니다. iOS 설정 앱에서 언어를 변경 한 후 앱을 다시 시작해야합니다. 그렇지 않은 경우 변경 사항을 보려면 직접 다시 시작하십시오. 필요한 시간이 아니라 모든 문자열을 한 번에 초기화하기 때문에 메모리 오버 헤드가있을 수도 있습니다.
iDevAmit

2
나는 이런 식으로, 여기에 계산 된 속성을 사용하는 것이 더 좋다고 생각한다static var Hello: String = { return NSLocalizedString("Hello") }
예술의이 - 꿈

는 스위프트의 수행하지 않기 때문에을 downvoted 명명 지침을
Cristik

3

SDK를 개발할 때 추가 작업이 필요합니다.

1) YourLocalizeDemoSDK에서 평소와 같이 Localizable.string 을 만듭니다 .

2) YourLocalizeDemo 에서 동일한 Localizable.string 을 만듭니다 .

3) YourLocalizeDemoSDK 의 번들 경로 를 찾으십시오 .

스위프트 4 :

// 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대신 사용 하면 잘못된 값을 얻습니다 (사실 키와 동일한 문자열이됩니다).

그러나 당신이 언급 문자열 확장 사용하려면 박사의 OX를 . 좀 더해야 해요 원점 확장은 다음과 같습니다.

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

아시다시피, 우리는 SDK를 개발 중이며 Bundle.mainYourLocalizeDemo 번들 번들을 얻게됩니다. 그것은 우리가 원하는 것이 아닙니다. YourLocalizeDemoSDK에 번들이 필요합니다. 이것은 빨리 찾는 요령입니다.

YourLocalizeDemoSDK의 NSObject 인스턴스에서 아래 코드를 실행하십시오. 그리고 YourLocalizeDemoSDK의 URL을 얻게됩니다.

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

두 URL을 모두 인쇄하면 mainBundleURL에 bundleURL ofSDK 기반을 빌드 할 수 있습니다. 이 경우 다음과 같습니다.

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

도움이 되길 바랍니다.


2

사용자 정의 번역 함수를 사용하여 문자열을 추출하기위한 고유 한 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

모든 신속한 파일을 구문 분석하고 코드의 문자열과 주석을 .strings 파일로 내 보냅니다.

아마도 가장 쉬운 방법은 아니지만 가능합니다.


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 명령입니다

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

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

1
주석을 남기지 않는 것이 좋지 않습니다.
José

@ José 귀하의 의견에 감사드립니다. 코드는 복사하여 붙여 넣기를위한 템플릿이 아니라 아이디어로 사용되었습니다. 그러나 당신이 원한다면 의견을 추가하는 옵션을 추가했습니다;)
GatoCurioso

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

0

구문이 같은 영어에서 다른 언어 (성, 동사 활용 또는 기울기 때문에)가 다른 언어로 번역 할 때 Swift에서 가장 간단한 NSString 형식은 모든 경우에 작동하는 세 가지 인수입니다. . 예를 들어, "previous was"라는 영어 문구는 "weight"( " предыдущ ий был")와 "waist"( " предыдущ ая был а ") 의 경우 러시아어로 다르게 번역 됩니다.

이 경우 하나의 소스에 대해 두 개의 다른 번역이 필요합니다 (WWDC 2018에서 권장되는 XLIFF 도구 측면에서). 두 개의 인수 NSLocalizedString을 사용하여이를 달성 할 수 없습니다. 여기서 "이전"은 "키"와 영어 번역 (예 : 값) 모두에서 동일합니다. 유일한 방법은 세 가지 인수 형식을 사용하는 것입니다

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

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

여기서 키 ( "previousWasFeminine"및 "previousWasMasculine")가 다릅니다.

나는 일반적인 조언이 문구 전체를 번역하는 것이지만 때로는 너무 시간이 걸리고 불편하다는 것을 알고 있습니다.


-1

기본 언어로 현지화 :

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: "")
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.