Original Link
by Victor Pavlychko
translated Korean by pilgwon
格好いいアプリには格好いいローカライゼーションが必要であります。そしてユーザーは自分が好きなアプリが自分の言語で利用できるオプションがあるのに喜ぶでしょう。開発初期段階だとしてもインターフェースのローカライゼーションをサポートすることにおいて開発者は異論がないでしょう。特にそれがやりやすいのであれば最もやるべき作業ではないでしょうか。
私はデザインをInterface Builderでやることが好きです。この記事にはローカライゼーションをどのようにアクセスするかを共有するつもりです。
普通、XIBファイルかStoryBoardをローカライゼーションする時、 ファイルかStoryBoardをローカライゼーションする時、Xcodeは気持ちよくリソースをコピーするし、貴方は重複されたView Layoutに打つかるでしょう。orz..DRY方法論をやろうとするとそれはいい選択と言えないでしょう。 😕
そうする代わりにInterface Builderのローカライゼーション用語に “@”-prefixを付けておいて viewDidLoad
か awakeFromNib
のようなメソッドで各自に合うローカライゼーションされた値で変更してあげることを提案します。以下がInterface Builderで見た時どう見られるのかのサンプルです:
ローカライジェーションの対象に @
prefixを利用して必要であれば他の実際の値と混ぜ合わせるようにします。追加で、@@
prefixはローカライジェーションしなくてもいいのに@
が含まれている場合に@
の代わりに利用します。
Swiftによくあるように先にプロトコルから始めます:
public protocol Localizable {
func localize()
}
次は文字列をローカライジェーションして属性にローカライジェーションされた値を適用するのに役に立つヘルパー達を含めているExtensionです:
public extension Localizable {
public func localize(_ string: String?) -> String? {
guard let term = string, term.hasPrefix("@") else {
return string
}
guard !term.hasPrefix("@@") else {
return term.substring(from: term.index(after: term.startIndex))
}
return NSLocalizedString(term.substring(from: term.index(after: term.startIndex)), comment: "")
}
public func localize(_ string: String?, _ setter: (String?) -> Void) {
setter(localize(string))
}
public func localize(_ getter: (UIControlState) -> String?, _ setter: (String?, UIControlState) -> Void) {
setter(localize(getter(.normal)), .normal)
setter(localize(getter(.selected)), .selected)
setter(localize(getter(.highlighted)), .highlighted)
setter(localize(getter(.disabled)), .disabled)
}
}
参考: 2番目のローカライジェーションヘルパーはSwift 4では KeyPath Syntaxアップグレードが必要になります。
今まではいいです。これからいくつかのローカライジェーションを実装してみましょう。その過程自体はコンテナーがその子供に自分をローカライジェーションさせる作業のため明白的に再帰的です:
extension UIView: Localizable {
public func localize() {
subviews.forEach { $0.localize() }
}
}
この実現には大体のアプリで必要にする共通コントロールに関するローカライジェーションサポートを追加してみます。実装方法は簡単です:
public extension UILabel {
public override func localize() {
super.localize()
localize(text) { text = $0 }
}
}
public extension UIButton {
public override func localize() {
super.localize()
localize(title(for:), setTitle(_:for:))
}
}
UIButtonのタイトルを設定することは可能な限り全てのコントロール状態に対するローカライジェーションを適用する他のヘルパーを利用することを覚えておきましょう。
View
のみがInterface Builder
で設定できるオブジェクトではありません。
次に出るオブジェクトも設定が可能なので覚えておきましょう:
-
UIBarItem
とそのサブクラス :UIBarButtonItem
そしてUITabBarItem
UINavigationItem
- あなたのアプリで利用すると決めた全てのオブジェクト
extension UIBarItem: Localizable {
public func localize() {
localize(title) { title = $0 }
}
}
public extension UIBarButtonItem {
public override func localize() {
super.localize()
customView?.localize()
}
}
extension UINavigationItem: Localizable {
public func localize() {
localize(title) { title = $0 }
localize(prompt) { prompt = $0 }
titleView?.localize()
leftBarButtonItems?.forEach { $0.localize() }
rightBarButtonItems?.forEach { $0.localize() }
}
}
最後に、ローカライジェーションフローをどこかでは始めないといけません。そのためには主に次のイベントをよく使います:
-
UIViewController
のサブクラスviewDidLoad
メソッドの中でtitle
,navigationItem
,tabBarItem
そしてview
をローカライジェーションします。 -
awakeFromNib
メソッドの中でUITableViewCell
のコンテンツとUICollectionViewCell
のサブクラスをローカライジェーションします。
コンテンツ、ナビゲーションそしてタブバーをローカライジェーションする時に使うUIViewController
のためのヘルパーは以下となります:
extension UIViewController: Localizable {
public func localize() {
localize(title) { title = $0 }
navigationItem.localize()
tabBarItem?.localize()
view.localize()
}
}
最後まで読んでいただきましてありがとうございました。これからあなたのプロジェクトに適用してみましょう。 😉. 記事の内容が良かったり、直接プロジェクトに適用してみたとしたら 👏 の押下のこと宜しくお願い致しますね。(本文記事にあります。)