Categories: iOS

まだStoryboardの多言語対応で消耗してるの?ローカライズの最強ベストプラクティス対応法

こんにちは。もぐめっとです。 先日、大先輩のfmtonakai大師匠からすごい目からウロコのstoryboardのローカライズ対応について教えてもらいました。

storyboardにローカライズのキーを指定できるようにする

extension UILabel {
    @IBInspectable
    private var localizedKey: String? {
        get { fatalError("only set this value") }
        set {
            if let newValue = newValue {
                text = newValue.localized()
            }
        }
    }
}
extension String {
    func localized() -> String? {
        return NSLocalizedString(self, comment: "")
    }
}
こう書いておくだけで、Android Studioのようにstoryboardからキーを設定してローカライズすることができるようになります。
すごい!画期的!!

ローカライズのキーtypoを防ぐ その1

このままだと、typoとかしたときにローカライズのキーがそのまま表示されてしまうのでローカライズ漏れに気づけるように改良してみました。
extension String {
    private static let localizedEmptyKey = "##not exists##"
    func localized() -> String {
        let string = NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: String.localizedEmptyKey, comment: "")
        if string == String.localizedEmptyKey {
            fatalError("not exists localized key")
        }
        return string
    }
}
キーが無かった場合には強制的にアプリを落としてしまうことによってキーの漏れに気づけるようになりました。

ローカライズのキーtypoを防ぐ その2

その1の対応だと、画面を表示したときでないとtypoに気づけません。 そこで、ビルド時にキーのチェックをしてtypoに気づけるようにさらに改良してみました。 Build Phasesに下記スクリプトを追加するだけ!
#!/bin/bash

for file in `\find . -name \*.storyboard`; do
    IFS=$'\n'
    for xmlKey in `\grep 'keyPath="localizedKey"' ${file}`; do
        localizedKey=`echo $xmlKey | sed -e 's/.* keyPath="localizedKey" value="\([0-9a-zA-Z_-]*\)".*/\1/g'`
        for localizedStringFile in `\find ${SRCROOT} -name Localizable.strings`; do
            grep "\"${localizedKey}\" =" $localizedStringFile > /dev/null 2>&1
            if [ $? != 0 ]; then
                echo "not exists key '${localizedKey}' in ${localizedStringFile}"
                exit 1
            fi
        done
    done
done
storyboardで設定されているlocalizedKeyをひっぱてきてLocalizable.stringsのファイルと突き合わせて存在しなければエラーを吐き出します。

まとめ

Android Studioに比べるとxcodeで至らぬところというのはまだまだありますが、今回の対応でLocalizable.stringsに文言を集約することができるようになり、よりローカライズがしやすくなってとってもウロコな方法でした。 storyboardでのローカライズはこの方法でやって、コードでの動的なローカライズについてはR.swiftやswiftgenなどで対応していって適材適所に使ってローカライズしていけるといいと思います。 今回の検証コードはこちらにおいてあります。 Special Thanks fmtonakai
mogmet

View Comments