本記事は下記のtweetから始まるスレッドに触発され、アイディアを拝借して書いた。
長い前置き
ソフトウェアのi18nは難しい。自文化では当たり前と思っていてハードコードしてしまった仮定が崩れて、大幅な再設計を余儀なくされるからだ。気づいて再設計できればまだ良くて、気づかずに出荷してユーザビリティに深刻な問題を引き起こしたり、セキュリティ上の問題を生んだり、国際問題になったりする。
逆に、たとえ難しいi18n上の問題であっても自文化で見聞きしたことがあれば理解は容易だし、備えようという気にもなるし、ある程度勘も働くから変なバグを作り込みにくくなる。
例えば日本で暮らしていると文字エンコーディングとタイムゾーンの話が対照的だ。
最近でこそUTF-8が主流になったとは言え日本では長らくISO-2022-JPとEUC-JPとShift_JISとこれらの変種がそれぞれ使われており、「世の中にはエンコーディングというものが存在するし取り扱いを間違えると文字化けする」という程度のことは文字列処理を書く人ならみんな知っている。
一方日本に暮らして国内向けの製品を書いているとタイムゾーンとは向き合わなくても済むので、ついついタイムゾーン情報を捨てて時刻を操作するコードを書いたりしがちだ。私も随分そういうコードを書いた。
USの開発者は正反対の状況にいた。USには複数のタイムゾーンがあってユーザーの入力や期待される出力がどれになるかは分からないので、その処理には慣れている。でも、Ruby 1.8からRuby 1.9への以降の際にRubyの文字列オブジェクトはエンコーディングを持つようになったとき、このとき結構混乱したユーザーもいたようだった。今まで1byte=1charだと思って処理してきたし、何も考えずに文字列を結合できたのになんで突然Encoding::CompatibilityError
が出るようになったんだ?
ここから考えられるのは、もしあらゆる軸で最強に他国と互換性を欠く文化の国があったとすれば、その国出身の開発者は自然にi18nのあらゆる勘所を体得していて変な設計を無意識に避けていける最強のi18nエンジニアな訳だ。
それはどんな国だろう。
言語
- 国内に複数の言語がある
- インドとか。
- 国内市場向けなら言語を決め打ちできるという仮定が成立しない。
- 国内でも複数の言語をサポートする必要があるので、間違いなくエンドユーザー向けメッセージをソースコード内に埋め込む習慣はないだろう。最低でもGNU gettextのような仕組みでメッセージはカタログから引く仕組みを自然に書いている筈だ。
- 同じ開発チーム内でも話す言語が異なるのが普通なので自分の母語でコードにコメントを書く習慣はないだろう。主たる公用語で書くか、英語で書くと思われる。インドとかそんな風だと聞いたことがあるような。
- USの会社のi18nありがちな、英語版webページと多国語版webページでURL体系が異なるみたいなものもないだろう。
- 他国で使われている言語の方言が使われている
- ブラジル(pt-BR)とか。
- 言語と国が1:1に対応しないのをよく知っているので、UI言語の選択肢を国旗で表現する悪習は身につけていないだろう。
- ISO 639-1だけでは言語を表現しきれないのを知っていて、 IETF language tagをちゃんと処理する習慣を持っているだろう。
- 敬称が複雑に変化
- 英語とか。相手の性や既婚・未婚により敬称が変化する。
- 相手の属性を知らなければ相手を呼べないので、単純な文字列置き換えによる多言語対応が無理なのを知っている筈だ。他言語対応では、究極的には言語依存のview helperを持たなければ単純なplain textすら生成できないことを認識している。
- 単数, 複数, 双数
- 数が0個, 1個, 2個, 3個以上の場合でそれぞれ名詞の形や対応する形容詞・動詞の形が変化するので、単純に
"%d個の商品があります"
のようなformat tempalteを書くことはないだろう。自然にview helperで文字列を生成するようになるだろう。
- 数が0個, 1個, 2個, 3個以上の場合でそれぞれ名詞の形や対応する形容詞・動詞の形が変化するので、単純に
- 動詞の屈折 * 主語の性や数により動詞が変化するので、view tempalte1つ書くのも容易ではない。helper関数を呼び出して、最低でもセンテンス単位で文字列を生成することになるだろう。
- 相対敬語を持つ
- 聞き手が誰であるかに依存して、特定の主語に対する敬語の使い方が変化する。このため、コピペで似たメッセージ文を使い回す習慣がなくなるだろう。
文字と組版
- 1バイト文字での代替表記が困難
- 日本語とか。
- 1バイトずつ読めば1文字ずつ処理できるという古いコードにありがちな仮定が成立しない。
- 歴史的にISO-2022ベースの文字コードとUnicodeと独自エンコーディングが混在
- Unicodeは基本として、まず現存するデータが単一の文字エンコーディングになっているという仮定が崩壊する。
- ISO-2022でまず文字列処理がstatefulになる。「特定の文字を表すバイト列を読めば、それが何の文字か分かる」という仮定が崩壊するので、文字列先頭から丁寧に処理するアルゴリズムを書くようになるだろう。
- 更に独自エンコーディングがあって、他の規格と異なる固有のエンコーディング処理実装を併存させる必要がある。Shift_JISの5C問題のようにセキュリティホールを作ることもある。文字列処理はセキュリティホールになりえるという基本的認識が身につくだろう。
- Unicode未収録文字
- 知らないと「面倒くさいからUnicodeで良いのでは?」と思うかもしれない。住基ネットのようにUnicode未収録文字を扱っていると、人は結局は用途に応じた文字集合やエンコーディングの使い分けに向き合わなければならないことを知るだろう。Rubyならできるよ。
- 特殊な組版規則
- 日本語とか。
- 日本語組版の要件にまとまっているように、フリガナやら縦中横やらがあると「文章の表示とは文字を横に並べることである」「スタイル情報がない限り文字のサイズは一定で良い」という仮定が崩壊する。特にフリガナは日本語組版の要件 図3.70にあるように振られた範囲がややこしいこともあるので、単純にカッコ書きで代替はできない。日本語に関して言えば禁則処理やら更にいろいろな話題がある
- この文化出身だと、組版というのはすごく専門的で難しいものだという認識を自然に持つだろう。
- 分かち書きしない表記法
- 日本語とか。分かち書きしないので「空白文字のところを改行候補として字間を調整する」アルゴリズムが機能せず、自然に組版処理が難しい分野だと言うことを認識するはずだ。
- 「空白文字区切りで単語を識別できる」という仮定が成立しないので、ごく簡単な文字列処理をするだけでも形態素解析というジャンルを知ることかできる。
- 右書き、左書き、縦書きを併用する
- アラビア語が右から左なのは有名
- 日本語や中国語は上から下にも書く
- 右書き、左書き、縦書きが全部混在する言語があるという話は聞いたことがない。日本語の縦書きの本でアラビア語に言及すると少しはそういうこともあるけれど、日常的ではない。古代言語では牛耕式や下から上の書き方もあったそうだが、現存しないので現代のi18nとしては一般的な要件ではないだろう。
- 左右書きを併用する文化出身だと、画面デザインの際に左右反転しても見やすいかどうかを自然に気に掛けるようになるだろう。(アラビア語に対応しようとして左右反転デザインにすると画像の配置のバランスが悪くなったり、想定していなくて画面が崩壊するのはありがちなミス)
- 縦書きを併用する文化出身だと、文字レンダリングの際に画面を最初に行分割してから割り付ける方式以外も気に掛けるだろう。
-
リガチャ
- ヨーロッパ諸語とか
- Fontには文字単位でグリフを収録すれば良いという仮定が崩壊する
- 一文字ずつ見て順番にレンダリング/印字すれば良いという仮定が崩壊する
- たぶんUnicodeに合成済みの文字も採録されていて、Unicode正規化を自然に意識するようになるかもしれない。
- 他国語と字形の異なる文字を同じコードポイントで共有
- 日本語と中国語とか。CJK統合漢字は日中韓に共通する漢字をどの言語でも同じコードポイントで表現することを意図しているが、あいにくとこれらの言語では漢字のグリフがかなり異なる場合がある。
- 「文字とフォントが定まればグリフが定まる」という仮定が崩壊するので、自然と文字列や文書に言語タグ情報をメタデータとして付ける習慣を身につけるだろう。
暦法と時間
- 独自の太陰暦
- グレゴリオ暦とはどんどん年がずれていくので、日付換算が複雑になる。単純にYYYY-mm-ddみたいな文字列に当てはめれば日付表記を生成できるという仮定から自由になれる。
- 20世紀以降に暦法を変更した
- 比較的最近の日付でもX年のY月Z日が(X-1)年Y月Z日の1年後とは限らない。このため、きちんと日付表記を暦法データベースと照合して解析し、正しく処理する習慣が身につくことだろう。
- 国内に複数のタイムゾーンがある
- ユーザープロファイルに必ずタイムゾーンを記録するようにして、時刻入力を受け付けるときには入力者のプロファイルと見比べたり、別途タイムゾーンを入力させたりするUIを作るようになるだろう。
- UTCからのオフセットが12時間以上
- うっかりするとタイムゾーンはUTC-12からUTC+12だと誤解しそうだが、キリバスなどの例を正しく処理するコードが書けるようになる
- UTCからのオフセットが1時間未満の端数を持つ
- うっかりするとタイムゾーンのオフセットは1時間が最小単位だと思い込みがちだが、ネパールなどのタイムゾーンを正しく処理するコードが書けるようになる。
- サマータイムが途中から導入された
- 季節によってタイムゾーン変化がするため、地域ごとにタイムゾーンを固定するようなコードを書かなくなる。
- また過去にはサマータイムが適用されなかった年が存在するので、季節だけでなく年も含めて正しくデータベースを引いてタイムゾーンを選択するコードを書けるようになる。
地理
- 街区方式と道路方式の住所システムが混在
- 日本とかイギリスとか。
- 地域によって「X丁目Y番Z号」方式の表記と「X通りY番」方式や「寺町通御池上る」のような道路方式が混在しているので、住所表記解析器を書くときに異なる実装を使い分けることを想定できる
- 隣国との係争領域がある
- 自国版の地名表記のまま輸出したりwebサイトを提供したりすると炎上するので、機器が利用されている地点やアクセス元IPに応じて地名データベースを使い分ける習慣が身につく
- 首都領域が法定行政区画としては存在しない。
- 日本の首都は「東京」「京都」「未規定」など諸説あるが、仮に「東京」だとしても「東京」が意味するものは謎だ。東京都では広すぎるし東京市は既に存在せず、適当な行政区画がない。シドニーも同様である。このため、国から首都への対応関係を保持するRDBテーブルにおいて、行政区画テーブルの主キーを参照しようとするとまずいことになる。
- こういう文化出身だと、行政区画と都市を区別してモデリングする習慣が付く。
- 用途によってはIATA都市コードが比較的近いのだが、これが振られていない都市もあるので難しい。
- 非法人地域を持つ
- 比較的歴史の長い国家では領土内の任意の地点が何らかの自治体に属するが、USなどではそうではない。こういった文化出身の場合、住所をグルーピングする目的で安易に自治体名を使うようなコードは書かないだろう。
- 選挙区や学区が住所体系や行政区画と直交
- 広告ターゲティング目的ではこういった体系が住所や行政区画より便利なことがあると聞いたことがあるような気がする。
- こういう文化出身だと、マーケティングや広告向けのシステムを書くときには住所以外の体系をサポートするのを忘れないようになるだろう。
その他
- 華氏とヤードポンド法
- 世界的には摂氏とメートル法が主流なのに自国はそうではないせいで、温度、距離、重量の単位を切り替える機能を忘れずに付けられるようになる。USの製品にはよくある機能。
- 小数点がカンマ, 桁区切りがピリオド
- 日本では12,345.67のように書くが、こちらでは12.345,67と書く。
- 数値を整形するときに、固定テンプレートを使ったり言語組み込みのデバッグ目的の簡易文字列化メソッドを読んだりするのではなく、Locale依存のテンプレートを利用するのを忘れないようになる
- 姓を持たない氏族がいる
- 姓名入力欄を作るの際に姓を必須にするミスをしなくなる
- 任意個の父称やミドルネームを名乗る氏族がいる
- 姓名入力欄を作る際に半端な文字数制限を実装してしまうミスを避けられる
- 姓名の変更が届け出制
- ユーザーが自分で姓・名を変更できるUIを付けるのを忘れなくなる。
- 東南アジアにそんな例があったと思うんだけど、届け出制なため、中二病に掛かると3回ぐらい格好いい名前に変更するとか聞いたような気がする。姓名の変更が稀だと安易に仮定してUIを付けないでおくと、ユーザーサポートがパンクする
- 性別の変更手続きが存在する
- ユーザーが自分で性別を変更するUIを付けるのを忘れなくなる
- 性別が原則的に変わらないと仮定してUIを付けなかったり使いもしないのに性別情報を収集すると、ユーザーサポートに無駄な負荷が掛かる
- Excelの関数名がローカライズされている
- 例はフランスだったかな?
- Excelの関数名が英語版とは異なるので、Excelファイル生成時には固定のひな形ファイルを利用できない。
言い訳とお願い
i18nがすごく専門的で難しい分野なのは知っていて、自分がそれに精通しているという認識はない。
本稿は業務上実際に悩まされた問題と、私が本で読んだことがある知識と、どこかで聞いたことがある話題が混在しており、情報精度にはばらつきがある。
このため、間違いを見つけたら是非とも編集リクエストをいただけるとありがたい。