iOS Localizable with Code

iOS/Tip 2022. 11. 2. 00:25
반응형

iOS Localizable with Code

iOS 앱을 개발하면서 다국어 지원을 해야하는 경우가 있습니다.

Swift Code로 이를 지원하기 위해서 우선 Localizable.strings 파일을 만들어야 합니다.

Xcode [File] - [New] - [File…]를 선택하고,

Resource에 있는 Strings File을 선택하고 [Next]를 누릅니다.

파일명은 변경하지 않고 Localizable.strings 그대로 [Create]를 누릅니다.

Localizable.strings을 선택하고 Inspectors의 File영역에서 [Localize…] 버튼을 누릅니다.

다음과 같이 기본으로 English가 체크될 것입니다.

이제 프로젝트에서 언어를 추가해줍니다.
[PROJECT]의 [Info] 탭에서 Localizations 항목의 하단에 있는 + 버튼을 누릅니다.

추가하고자 하는 언어를 선택해 줍니다. (예, Korean)

각각 스토리 보드에도 언어를 추가 할수 있지만 Localizable.strings 파일에만 추가하고 [Finish] 버튼을 누릅니다. (Storybarod으로 작업하실꺼면 선택해야 합니다.)

Localizations Localizable.strings 파일에 언어가 추가된것을 확인할 수 있습니다.

이제 각 Localizable.strings에서 다국어 지원할 문자열을 추가합니다.
key = "value"; 형식으로 작성해 주면 됩니다.

코드로 사용할때에는 NSLocalizedString함수를 사용하면 됩니다.

grettingsLabel.text = NSLocalizedString("Grettings", comment: "인사말입니다")

Xcode에서 언어 변경으로 테스트 하려면 [Edit Scheme..]에서

[Run] 항목의 [Options] 탭의 [App Language] 영역에서 원하는 언어를 선택하고 앱을 실행해 보면 됩니다.

한국어로 설정하고 실행

영어로 설정하고 실행

NSLocalizedString 함수를 사용할때 오타가 입력할 수도 있기에 좀 더 우아하게(?) 사용하기 위해 구조체나 열거형에 미리 정의해서 사용하기도 합니다.
(주로 I18N.swift 파일 구조체에 static 변수를 만들어 사용합니다.)

개인적으로는 문자열 열거형 변수를 만들어 사용하고 있는데 각자 스타일데로 스크립트 내용을 변경해서 사용하면 됩니다.

Xcode의 Run Script를 사용합니다.

[TARGETS] - [Build Phases]탭에서 [+]버튼을 눌러서 [New Run Script Phase]를 선택합니다.

[Shell] 영역에 다음을 입력해 주세요.

# Type a script or drag a script file from your workspace to insert its path.
echo "generating Localized.swift"

touch tempLocalized.swift
echo "enum Localized: String {" >> tempLocalized.swift

inputfile=${SRCROOT}/${PROJECT}/en.lproj/Localizable.strings
while IFS= read -r line

do
echo $line
pattern='^[a-zA-Z]+(.*)[\\s]*=[\\s]*(.*);$'

if [[ $line =~ $pattern ]]
then
    echo "Yes👌"
    variableName=$(echo ${line%%=*})
    echo $variableName
    if [ "$variableName" != "" ]; then
        echo "    case $variableName" >> tempLocalized.swift
    fi
else
    echo "No👎"
fi
done <"$inputfile"
echo "\n    var value: String { rawValue.localized }" >> tempLocalized.swift
echo "    @discardableResult\n    func value(_ arguments: CVarArg...) -> String { value.localized(arguments) }" >> tempLocalized.swift
echo "}" >> tempLocalized.swift
cat tempLocalized.swift > ${SRCROOT}/${PROJECT}/Localized.swift
rm tempLocalized.swift

echo "-------------"
cat $inputfile
cat ${SRCROOT}/${PROJECT}/Localized.swift
echo "-------------"

그리고 나서 빌드하면 프로젝트 폴더내에 Localized.swift 파일이 생성되고 해당 파일을 프로젝트에 추가해주면 됩니다.

파일에는 자동으로 다음과 같이 enum 형으로 선언되어 있습니다.

enum Localized: String {
    case Grettings

    var value: String { rawValue.localized }
    @discardableResult
    func value(_ arguments: CVarArg...) -> String { value.localized(arguments) }
}

그리고 문자열 확장을 추가해줍니다.

extension String {
    /// 다국어 처리 문자열
    var localized: String {
        NSLocalizedString(self, comment: "")
    }
    
    /**
     인자값이 존재하는 다국어 처리
     
     ```
     // how to use
     "TestArgument".localized("123")
     ```
     
     - Parameter arguments: 인자목록
     - Returns: 다국어 처리 결과 문자열
     */
    func localized(_ arguments: CVarArg...) -> String {
        String(format: localized, arguments: arguments)
    }
}

그외에 코드가 아닌 스토리 보드에서 직접 사용하기 위해서 UI Control 코드를 추가하면 편합니다. (단, 현재 설정된 언어로만 가능합니다)

extension UIBarButtonItem {
    @IBInspectable var localizedText: String? {
        get { return title }
        set(value) { title = value?.localized }
    }
}

extension UINavigationItem {
    @IBInspectable var localizedText: String? {
        get { return title }
        set(value) { title = value?.localized }
    }
}

extension UILabel {
    @IBInspectable var localizedText: String? {
        get { return text }
        set(value) { text = value?.localized }
    }
}

extension UIButton {
    @IBInspectable var localizedText: String? {
        get { return title(for: .normal) }
        set(value) { setTitle(value?.localized, for: .normal) }
    }
}

extension UITextView {
    @IBInspectable var localizedText: String? {
        get { return text }
        set(value) { text = value?.localized }
    }
}

extension UITextField {
    @IBInspectable var localizedText: String? {
        get { return placeholder }
        set(value) { placeholder = value?.localized }
    }
}

이제 다음과 같이 사용할 수가 있습니다.

// AS-IS
grettingsLabel.text = NSLocalizedString("Grettings", comment: "인사말입니다")

// TO-BE
grettingsLabel.text = Localized.Grettings.value

 

샘플 프로젝트 :

TestLocalizable.zip
0.04MB

반응형
Posted by 까칠코더
,