Xcodeのローカライゼーションファイルへのアクセスを超楽にするxcmultilingualを作成しました!

Xcodeのローカライゼーションファイルへのアクセスを超楽にするxcmultilingualを作成しました!

xcmultilingualとは

作成したローカライズファイルのキーへのアクセスを簡単にします。

例えば、AnimalテーブルのDOGキーにある文言を出力したい場合、

Multilingual.Animal.DOG.string()

とすれば、出力されます。AnimalもDOGもそれぞれきちんと補完がでてきます。詳しくは、Youtube動画を御覧ください。

NSLocalizedStringの問題

普段、Xcodeでローカライゼーションファイルにアクセスする場合、このように書くと思います。

NSLocalizedString("DOG", comment: "")

さらに、テーブルを指定したりするとこのようになります。

NSLocalizedString("DOG", tableName: "Animal", bundle: NSBundle.mainBundle(), value: "", comment: "")

キーは文字列なので、そのキーが翻訳ファイルにあるのかどうかもわかりません。

このようにローカライゼーションファイルにアクセスするには以下のような問題がありました。

  1. NSLocalizedString...メソッドが長い。
  2. どのキーの翻訳があって、どのキーの翻訳がないのかがパッとわからない。
  3. .stringsファイルを書くのが面倒くさい。

長いメソッドに関してはエイリアスを書けば良いかもしれないのですが、それだけではどのキーの翻訳があるかわかりません。

xcmultilingualは上記上から2つの問題を解決します。コマンドを実行すると、xcodeのプロジェクトファイルからローカライズファイルを探し出し、使いやすい形に成形したメソッドを生成します。

使い方

詳しくは、READMEを見ていただければと思いますが、簡単に解説します。

1. gemとしてインストールする

gem install xcmultilingual、または、Gemfileにgem 'xcmultilingual'と書いてインストールします。

2. Xcodeのファイルの一番上の階層に、結果を出力するための空の.swiftファイルを作成する

.
├── DemoApp
│   ├── AppDelegate.swift
│   ├── Base.lproj
│   ├── Images.xcassets
│   ├── Info.plist
│   ├── Loalizations
│   ├── Multilingual.swift

3. 先ほどのファイルを指定してupdateコマンドを実行する

$ xcmultingual update ./DemoApp/Multilingual.swift

すると、Multiingual.swiftに下記のようなstructが生成されます。

例:

import Foundation

struct Multilingual {
    enum Localizable: String {
        case HELLO = "HELLO"
        case GOODMORNING = "GOODMORNING"
        case GOODEVENING = "GOODEVENING"

        func string() -> String {
            return NSLocalizedString(rawValue, tableName: "Localizable", bundle: NSBundle.mainBundle(), value: "(rawValue)", comment: "")
        }

        static func keys() -> [String] {
            return ["HELLO", "GOODMORNING", "GOODEVENING"]
        }

        static func localizations() -> [String] {
            return Localizable.keys().map { Localizable(rawValue: $0)!.string() }
        }
    }

    enum Animal: String {
        case CAT = "CAT"
        case DOG = "DOG"
        case BEAR = "BEAR"
        case DEER = "DEER"

        func string() -> String {
            return NSLocalizedString(rawValue, tableName: "Animal", bundle: NSBundle.mainBundle(), value: "(rawValue)", comment: "")
        }

        static func keys() -> [String] {
            return ["CAT", "DOG", "BEAR", "DEER"]
        }

        static func localizations() -> [String] {
            return Animal.keys().map { Animal(rawValue: $0)!.string() }
        }
    }

    private static func bundle(relativePath: String) -> NSBundle {
        var components = (__FILE__ as String).pathComponents
        components.removeLast()
        let bundlePath = join("/", components) + "/" + relativePath
        return NSBundle(path: bundlePath) ?? NSBundle.mainBundle()
    }
}

4. 気持ちいい補完とともに使う

これでローカライズファイルに簡単にアクセスできるようになります。Multilingualと打つとプロジェクト内の全てのテーブルが補完候補としてでてきます。

Multilingual.Localizable
Multilingual.Animal

ここで、Animalを選択すると、Animalテーブルの中のキーが補完候補としてでてきます。

Multilingual.Animal.CAT
Multilingual.Animal.DOG
Multilingual.Animal.BEAR
Multilingual.Animal.DEER

すごい!翻訳結果を出力するにはenumのstring()コマンドを打ちます。

Multilingual.Animal.DOG.string()

簡単です!

RubyGemsで配布しています

そもそものローカライゼーションファイルを作るにはLinguanが便利かも

このライブラリのサンプルを作ってテストするときに、Linguanを使いました。ローカライゼーションが普通に書くよりは簡単に書けます。

後記

RubyのGemをはいふするのははじめての経験です。Rubyに慣れているわけでもなく、ファイルの探索など思うように進まず疲れました。開発中は、RubyとSwiftを半分づつ書いていました。やりたいことはわかっているのですが、うまく表現できずという感じでした。

ローカライズファイルに簡単にアクセスしたいなともう2年くらい前から思っていました。ただ、今回Swiftで強化されたenumを使うことで補完がスムーズにできることを感じ、xcmultilingualを形にしようと思いました。

2年間やりたいと思っていたことがとりあえずできてよかったです。

今の段階ではまだ、メインのプロジェクトのローカライズファイルしか対象にしないように限定していますが、バージョンアップでたのバンドルのローカライズファイルも扱えるようにしたいと思っています。

あと、慣れないRubyで書いたので、おかしな記述やバグなどもあると思いますので少しずつ直していきたいです。

Pocket
LINEで送る

You may also like...