翻訳エンジンによる多言語対応

はじめに

翻訳エンジン、は、正直まだそれほど調べていないけど、文脈を解析するタイプ(多分Exciteとか)と、もっとも長い文脈に一致したものを機械的に当てはめるタイプ(Googleとか)に分別できるとして、ここでいうのは後者の方。

リソースファイルによる多言語対応について

さて、長い間ベトナムにいたこともあっても、多言語対応のソフトウェアってのもよく作る機会がある。


多言語対応と一言で言ってもいろいろある。
Shift_JISEUCといった文字コードを使わずにとりあえずUTF-8使いましょうってのがひとつ。DBをそうすることで、ユーザ投稿コンテンツに想定外の言語が混ざったとしてもそれなりに安心。テンプレートファイルなんかをUTF-8で扱っておくことで、内部リソースを翻訳しやすくなったりもする。
こういうのは文字コード対応といったりする。


んで、まあそういう技術的な方式以外の一般的な翻訳の翻訳方法もいろいろあって、よくあるのがこういうやり方。

echo $resource->get('Hello World');

ここでリソースファイルと呼ばれる言語を定義されているファイルからメッセージを持ってきてるんだけど、リソースファイルの中身はこんなの。

English,日本語,Tieng Viet
Hello World,こんにちは世界,Xin chao moi nguoi

左から英語、日本語、ベトナム語
これを現在の言語設定に基づいた「Hello World」を返すクラスを作って、そのクラスを通してあらゆるメッセージを出力したりする、と。


このやり方主流なんだけど、作る側としては大変面倒。たとえばこんなん。

  1. ソースコードの可読性が著しく落ちる
  2. メッセージひとつ追加するのが面倒くさい
  3. 文法違うので部分部分の置換が大変
  4. WebだとJavaScript、エラーメッセージ、テンプレート、DBと4通りの多言語化が必要


長々と個々の事例について説明書いてたんだけど、なんか長くなるのでやめて、まあそういう問題があるよということで。

翻訳エンジン方法による考察

通常のコードがこれで、

echo 'Hello World';

リソース使う場合のコードがこれだとして、

echo $resource->get('Hello World');

ほんとにこの二つしかないのかねっていうのを考えてみると、もう一つあった。
翻訳エンジンによる機械翻訳だ。
上記のコードは両方とも画面に「Hello World」と出力するだけで、このソースコード部分を翻訳する必要なんてものはない。
あくまで翻訳するのはHello Worldなので、その出力部分をエンジンにかけて翻訳すればいい。


で、通常の翻訳エンジンだと、そのクォリティは悲惨なものになるけど、そのシステム専用の翻訳エンジンを作ったらどうかな、と。


特に最長一致で翻訳するものは、たとえば「Hello」と「World」を登録しておけば「こんにちは」と「世界」があり、「こんにちは世界」が出力結果になる。
こんな直訳じゃなくて、日本語版では「ようこそ世界」と表示したいなら、「Hello World」をHello、Worldと別に登録しておけば、Hello Worldが「ようこそ世界」に、別の場所で「Hello Mr. tsuge」とかあったら「こんにちは Mr. tsuge」になる。


汎用翻訳エンジンではできないけど、専用の翻訳エンジンであれば意訳も容易になり、クォリティを格段にあげられるだろうと。


このやり方のいいところは、元のソースコードを一切変える必要がないということ、それがDBだとかテンプレートだとかエラーメッセージとか考える必要がないということ、翻訳エンジンとソースコードを完全に分離できるということ。
難点は出力結果を事前に知らないので、実行速度がどうしても遅くなるということ。
技術的な障壁は、パラメータ付きのものの正確な判定とかがある。
あと、別枠として画像の扱いってのもあるけど。

実用に向けて

んー、ソースコードは母国語でなんの制約もなしにがりがりかけるし、マスタデータが入っているテーブルの翻訳もせんでいいし、翻訳部隊を別途走らせておけるしで、いいこと尽くめに見えるから実用したいなぁと最近思ってたんだけど、やっぱり実用に際してそれなりに課題はある。

速度の問題。

最長一致は言語解析に比べて実行速度は早いとはいっても、1リクエストごとに行うんじゃどうしても支障が出る。
ということで、最初に導入するとすればユーザ絶対数の少ない社内向けアプリで、まずは速度を気にしないでやる必要があるかなとは思っていた。
速度の解消についてはキャッシュしかないかな。

パラメータ付きの値について

「これは1円です」と「これは1000円です」は「これはN円です」であるべきなのだが、このパラメータ部分をNと正確に判定するのは大分難しい。
時として「これは1円です」は「これは1円です」でよくても、「これは1000円です」は「これは千円です」であるべきかもしれないし、カンマの区切り位置も違うかもしれない。


パラメータは、大体3種類。
数値と、日付と、名前。
数値と日付は、まあ機械判定できるだろうと。
名前は大分厄介。正確に判別する方法は限りなく不可能に近い。


多分、HTMLの出力結果をパラメータに関しては例外的に出力自体を変えないと難しくなる。
でも出力結果の変更は「原則として元のプログラムをいじる必要がない」という前提から外れるので多用は厳禁であるべきで、自然に解析できるならそれがいいんだけど、まあ無理だろうねとは思う。
こんな感じにするしかないかなと。

<s:告原豊和>
<d:2012年12月29日>
<n:29>

順番としてはサーバプログラム→翻訳エンジン→Webブラウザ→ユーザだから、翻訳エンジン抜いても動作するようにするならこの形だけど、

<!--<s:-->告原豊和<!-->-->
<!--<d:-->2012年12月29日<!-->-->
<!--<n:-->29<!-->-->

こうなっちゃうのは可読性の問題から避けたい。


だから上のような例で実装をした上で、翻訳エンジンがない場合にはそれを取り除くって形で動がすのがベターなんではないかなと。

適合箇所の問題

極端な例だけど、ログイン画面で言う「Submit」と編集画面で言う「Submit」を翻訳する場合、ログイン画面の方は「ログイン」であるべきで、編集画面の方は「保存」であるべきかもしれない。
同じ文字列であっても、場面によって異なることが多い。


これは汎用の翻訳エンジンだと駄目な理由と同じで、場面ごとの意訳が必要になる可能性を考慮して、一応URLによる最長一致での優先リソース設定が可能なようにするべきだと思う。
一致方式は前方一致ではなく部分一致にして、「/login」だったり、「http://test.test/login」だったりはいずれも登録できるようにしつつ、基本的にはそれらを使用しない汎用のリソースを設けることで対応、がいいと思う。

HTMLタグによる分割

Webシステムへの適用の場合、よくこんなのがある。

こんにちは<span class="name">告原</span>さん <span style="font-size:80%">現在 <i>80pt</i></span>

翻訳エンジンが認識するべきテキスト的にはこうなんだけど、

こんにちは<s:告原>さん 現在80pt

HTMLの装飾要素が邪魔をしてくるパターン。


これはもう、HTML解析するしかない。こう認識させるべきならそう認識させるべき。

こんにちは<s:告原>さん 現在80pt

これをこう翻訳して、

Xin chao Ban <s:告原> Bay gio con 80 diem

最終的にはこうせにゃならん。

Xin chao Ban <span class="name">告原</span> <span style="font-size:80%">Bay gio con <i>80 diem</i></span>

結構面倒。

JavaScript

あとJavaScriptの問題もあって、こういうの。

alert(name+"さんは"+action+"しました");


これは正直、きつい。
こう認識しないといけない。

<s:name>さんは<s:?>しました

でも中身何入ってるかなんてわかんないんだよね。
だからもう、仕方ないので、JavaScriptの翻訳エンジンは別途用意した上で、個別対応していくしかない。
正直最初は個別対応で、後回しかなと思う。

翻訳エンジンを持つということ

翻訳エンジンを持つということはかなりのメリットがあって、リソースファイルはもうシステムごとに「ファイル」は「File」だよとか、「ログアウト」は「Logout」だよとか、ばかみたいな作業をシステム数分繰り返さないといけないんだけど、翻訳エンジンはそんなもの必要ない。


中身は汎用エンジンと完全に同じなので、特定システムに向けて動かしたいなら、そのシステムの出力時にエンジンを走らせるだけでいい。唯一の例外はパラメータを正確に認識させるために、翻訳エンジン向けの情報を付与した方がいいということだけど、それでさえ絶対ではない。


なので、経理システムをやれば同種の経理システムにそのまま使えるクラスのエンジンを保持できることになる。
しかも元のソースを変える必要もない。


一般的な多言語化はシステムごとだから、そのシステムに対する資産は残るけど、汎用的な資産としては残りにくく発展もしにくいけど、別で動かす翻訳エンジンなら翻訳エンジンだけ発展させることもできるし、別で開発して後から結合することも容易。


諸々、いいことづくめだと思うんだけどね。
今回ので上手くいったら、商売できないかなぁとは思ってる。