こんにちは。LINEでAndroid Clientを開発しているMasakuniです。 これはLINE Advent Calendar 2016の4日目の記事となります。 LINEのアプリ・サービスは多くの国で使われているため、国際化や多言語化はサービス開発時における重大なテーマの一つです。 今回は、その中でも「大文字・小文字変換」について話をします。 Javaにおける String#toLowerCase() / toUpperCase() の挙動 まずは一つ、問題を出してみましょう。 Q. 以下のJavaテストコードは常にpassすることが保証されているでしょうか? A. No. 一見単純なテストコードですが、これはJavaの実行環境によっては失敗することがあります。何故かと言うと、 "I".toLowerCase() は "I".toLowerCase(Locale.getDefault()) と等価であり、実行環境のデフォルトロケールによって動作が変わるからです。 具体的には、ロケールがトルコ語(“tr”)のときに上記のテストは失敗します。トルコ語ではドット付きのIとドット無しのIが区別されており、”I”に対応する小文字は “ı” (U+0131, LATIN SMALL LETTER DOTLESS I) で、”i”に対応する大文字は “İ” (U+0130, LATIN CAPITAL LETTER I WITH DOT ABOVE) となります。 つまり、Javaのテストコードで書くと以下のようになるわけです。 別の例を挙げましょう。Grave accentが付いている “Ì” (U+00CC, LATIN CAPITAL LETTER I WITH GRAVE) に対応する小文字は、多くのロケールにおいては “ì” (U+00EC, LATIN SMALL LETTER I WITH GRAVE) になります。しかしリトアニア語(“lt”)においては、”i” (U+0069, LATIN SMALL LETTER I, 普通のi) に結合文字 U+0307 (COMBINING DOT ABOVE) と U+0300 (COMBINING GRAVE ACCENT) が続いた “i̇̀” (U+0069 U+0307 U+0300) となります。つまり、Javaテストコードでは以下のようになります。 このようにUnicodeでのキャラクター数が増加する変換は他にもあります。たとえば、ドイツ語の ß (U+00DF, LATIN SMALL LETTER SHARP S) いわゆるエスツェット(Eszett)は大文字に変換すると “SS” になります。 もっと厄介な例としては、ギリシア文字の小文字シグマがあります。これは通常 σ (U+03C3, GREEK SMALL LETTER SIGMA) で表されますが、単語の末尾では字形が変化した ς (U+03C2, GREEK SMALL LETTER FINAL (…)
↧