(Localization) SwiftUI에서 Localization 사용하기 (feat: NSLocalizedString)

SteadySlower·2024년 1월 31일
0

SwiftUI

목록 보기
61/64
post-custom-banner

지난 번 포스팅에서 String File과 String Catalog를 활용해서 Localization을 세팅하는 법을 알아보았다. 이번에는 SwiftUI에 실제로 적용해보자.

직접 String을 넣으면 자동으로 적용

일단 시뮬레이터의 언어를 한국어와 일본어로 각각 세팅을 하고 아래 코드를 실행해보자. Text (혹은 Text Field에) 직접 String을 넣는 경우에는 자동으로 Localization 처리가 된 것을 볼 수 있다.

import SwiftUI

struct LocalizedView: View {
    
    @State var user: String = ""
    
    var body: some View {
        VStack {
            Text("Hello \(user)")
            Text("Good to see you!")
            TextField("your name", text: $user)
        }
        .padding(.horizontal, 20)
    }
}

Untitled

Untitled

변수로 넣으면 적용이 안됨

그렇다면 Text를 다른 View로 한번 감싸고 parameter로 넣는 아래와 같은 뷰를 생각해보자. 하나는 같은 구조체 내부에서 다른 하나는 외부에서 View를 만들고 진행해보자. 이를 실행해보면 parameter로 String을 넣으면 Localization이 되지 않는 것을 볼 수 있다. 또한 String Catalog에서 자동으로 Localization이 필요한 문자열을 불러올 때도 불러오지 못하는 것을 볼 수 있다.

import SwiftUI

struct LocalizedView: View {
    
    @State var user: String = ""
    
    var body: some View {
        VStack {
            Text("Hello \(user)")
            textView("Hello \(user)")
            SubTextView("Hello \(user)")
            Text("Good to see you!")
            TextField("your name", text: $user)
        }
        .padding(.horizontal, 20)
    }
}

extension LocalizedView {
    func textView(_ text: String) -> some View {
        Text(text)
    }
}

struct SubTextView: View {
    let text: String
    
    init(_ text: String) {
        self.text = text
    }
    
    var body: some View {
        Text(text)
    }
}

Untitled

Untitled

다른 케이스로 아래와 같은 케이스도 생각해볼 수 있다. Text를 다른 View로 감싸지 않고 그대로 사용하는 대신 String만 변수에 할당하는 케이스이다.

마찬가지로 Localization 되지 않는다. 생각해보면 이는 SwiftUI입장에서는 당연한 것이다. Localization의 대상은 불변의 String이어야 한다. 하지만 String을 변수로 할당하게 되면 SwiftUI 입장에서는 이 String이 불변하는 상수인지 변할 수 있는 변수인지 알 수가 없다. 만약에 변수로 할당을 해도 Localization이 된다면 사용자가 키보드로 입력한 문자열이 갑자기 Localization이 된다던가 하는 버그가 발생할 수 있다.

import SwiftUI

enum Greeting {
    case firstMet
    
    var message: String {
        switch self {
        case .firstMet: "Good to see you!"
        }
    }
}

struct LocalizedView: View {
    
    @State var user: String = ""
    
    var body: some View {
        VStack {
            Text("Hello \(user)")
            Text("Good to see you!")
            Text(Greeting.firstMet.message)
            TextField("your name", text: $user)
        }
        .padding(.horizontal, 20)
    }
}

Untitled

Untitled

NSLocalizedString 활용하기

그렇다면 위와 같은 케이스는 어떻게 Localization을 적용할 수 있을까? 가장 간단한 방법은 NSLocalizedString을 사용하는 것이다. NSLocalizedString을 활용하면 self (String)을 Key로 하는 Localized String을 구할 수 있다.

extension String {
    func localize() -> String {
        NSLocalizedString(self, comment: "")
    }
}

위 메소드는 아래와 같이 활용할 수 있다.

extension LocalizedView {
    func textView(_ text: String) -> some View {
        // ✅ localize 적용
        Text(text.localize())
    }
}

struct SubTextView: View {
    let text: String
    
    init(_ text: String) {
        self.text = text
    }
    
    var body: some View {
        // ✅ localize 적용
        Text(text.localize())
    }
}
enum Greeting {
    case firstMet
    
    var message: String {
        switch self {
        // ✅ localize 적용
        case .firstMet: "Good to see you!".localize()
        }
    }
}
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.
post-custom-banner

0개의 댓글