go-i18nで必要なjsonをgoのソースコードから生成するgoi18n-parser
モチベーションとして、
- 多言語対応をしたい
- goのソースコードから自動で翻訳ファイルを作成したい
- シンプルでいい(複雑な機能は要らない)
があり、最小限で作ってみたので紹介します。
goi18n-parser
goi18n-parser
ではソースコードの解析に go/ast
を使用しています。
go/ast
を使うと、goのソースコードを抽象構文木にして中身を解析することが出来ます。
今回解析したい内容は、
- 翻訳関数の使われている部分
となります(この「翻訳関数」とは便宜的に書いてるだけです)。 goのソースコード内に翻訳関数が使われていて、その翻訳関数の引数が翻訳対象となるメッセージのIDとして記憶されていきます。
具体的には次のようなコードです:
... fmt.Println(SomeStruct.T("server_error_something")) return fmt.Error(T("server_error_invalid_user_session")) ...
上記の例だと翻訳関数は T
になります。この T
を go/ast
を使って見つけていきます。
今回作成したパッケージ goi18np
を使って取得する場合は次のように書けます:
a := goi18np.Analyzer{} a.AnalyzeFromFile("/path/to/code.go") a.SaveJSON("/path/to/translate.json")
また、複数ファイルも同時に解析できます:
a.AnalyzeFromFiles([]string{"/path/to/code.go", "/path/to/code2.go"})
入力と出力の例を以下に紹介します。
package sample import ( "fmt" "github.com/nicksnyder/go-i18n/i18n" ) type A struct { T i18n.TranslateFunc } func SampleCaller() { T, _ := i18n.Tfunc("eu-US") fmt.Println(T("sample_uniq_key")) for i := 0; i > 100; i++ { if i%10 == 0 { fmt.Println(T("sample_uniq_key_2")) x := T("sample_uniq_key_3") fmt.Println(x) } } T2, _ := i18n.Tfunc("en-US") a := A{T: T2} fmt.Println(a.T("sample_uniq_key_4")) fmt.Printf("%s,%s,%s", a.T("sample_uniq_key_4"), T("sample_uniq_key_5"), T("sample_uniq_key_2")) return }
このソースコードを解析した結果が次のようになります:
[ { "id": "sample_uniq_key", "translation": "" }, { "id": "sample_uniq_key_2", "translation": "" }, { "id": "sample_uniq_key_3", "translation": "" }, { "id": "sample_uniq_key_4", "translation": "" }, { "id": "sample_uniq_key_5", "translation": "" } ]
翻訳内容の部分を one
または other
をつけて、単数形と複数形の文章に分ける処理はしていません。
そこまでの自動化はせずに、必要になったときに人の手で追加する感じになると思います。
また、実際にjsonで保存するときは go1.8
で出てきた sort.Slice
を使うなどして、ID順にソートして差分が少なくなるように工夫が必要かと思います。