はじめに
全世界に広がるインターネットでは、世界中どこでも使えるソフトウェアが必要になります。 つまり、ユーザーの国や言語を意識しないで開発でき、さまざまな国や地域に合わせてローカライズできるソフトウェアです。Java プラットフォームでは、グローバルアプリケーションを開発するための豊富な API 群が提供されています。このような国際化のための API は、Unicode 標準に基づいており、テキスト、数値、日付、通貨、およびユーザー定義のオブジェクトを任意の国の慣習に合わせる機能を備えています。
このドキュメントでは、Java Platform Standard Edition の国際化に関する API と機能の概要を説明します。コーディング例と詳しい手順の説明については、『Java チュートリアル』を参照してください。API の詳細については、「Java Platform Standard Edition の API 仕様」を参照してください。
さらに詳しい情報については、Java 国際化のホームページを参照してください。
テキストの表現
Java プログラミング言語は Unicode 文字セットをベースにしており、いくつかのライブラリでは Unicode 標準が実装されています。Unicode は、世界の主要な書記法すべてに加えて、基本的な学術記号をサポートしています。Unicode 仕様では最初、各文字を 16 ビット固定長の実体として定義していましたが、その後、16 ビットより長い表現を必要とする文字も取り扱えるように Unicode 標準が変更されました。有効なコードポイントの範囲は現在、U+0000 ~ U+10FFFF です。UTF-16 標準により定義されるエンコーディングでは、すべての Unicode コードポイントを、1 つまたは 2 つの 16 ビット単位を使用して表現できます。
Java プログラミング言語の基本データ型 char は、符号なしの 16 ビット整数なので、U+0000 ~ U+FFFF の範囲の Unicode コードポイントや、UTF-16 のコード単位を表現できます。 Java プラットフォームで文字シーケンスを表現する各種の型およびクラスは、UTF-16 のシーケンスです。そのような型およびクラスとしては、char[]、java.lang.CharSequence の実装 (たとえば String クラス)、java.text.CharacterIterator の実装などがあります。 ほとんどの Java コードは、7 ビット文字エンコーディングの ASCII または 8 ビット文字エンコーディングの ISO-8859-1 で記述されますが、処理の前に UTF-16 に変換されます。
Character クラスは、char プリミティブ型のオブジェクトラッパーとしての役割を果たします。Character クラスには、isLowerCase() や isDigit() など、文字のプロパティーを判別するための static メソッドも含まれています。J2SE 5.0 からは、これらのメソッドは、char (U+0000~U+FFFF の範囲の Unicode コードポイントを表現できる) または int (すべての Unicode コードポイントを表現できる) のいずれかを受け付けるようにオーバーロードされています。
ロケールの識別とローカリゼーション
ロケール
Java プラットフォームでは、ロケールは、言語と地域の特定の組み合わせに対する単なる識別子です。ロケール固有の属性の集合ではありません。ロケール固有の情報は、ロケールの影響を受けるクラスがそれぞれ独自に保持しています。このような設計のため、ロケール固有のリソースを保持する方法に関し、ユーザーオブジェクトとシステムオブジェクトで違いはありません。どちらも、標準のローカリゼーション機構を使います。
Java プログラムには、単一のグローバルロケールは割り当てられていません。ロケールに依存するすべての操作には、引数として明示的にロケールを渡すことができます。これにより、多言語プログラムが非常に簡単になります。グローバルロケールが強制的に使われることはありませんが、ロケールを明示的に管理する必要のないプログラムでは、デフォルトのロケールを利用できます。デフォルトロケールを使うと、全体的な表示形式を一度の選択で変えることができます。
Java のロケールは、別のオブジェクトから出される、ある動作に対する要求として機能します。たとえば、カレンダオブジェクトにフランス語系カナダ用ロケールを渡すと、ケベック州の慣習に従って正しく動作するようカレンダに要求したことになります。ロケールを受け取ったオブジェクトは、適切な処理を行わなければなりません。オブジェクトが特定のロケールに対してローカライズされていない場合、オブジェクトは、ローカライズされているロケールでよく似たものを探します。たとえば、カレンダオブジェクトがフランス語系カナダのロケール用にローカライズされていなくても、一般的なフランス語についてはローカライズされている場合は、代わりにフランス語のローカライズ版を使います。
Locale クラス
Locale オブジェクトは、地理的、政治的、または文化的に特定の地域を表しています。動作するためにロケールを必要とする操作のことを、ロケール依存操作と呼びます。ロケール依存操作は、Locale オブジェクトを使って、ユーザーに合うように情報を加工します。たとえば、数値の表示はロケールに依存する操作です。数値の書式は、ユーザーに固有の国、地域、文化などの慣習やきまりに従って設定する必要があります。
サポートされているロケール
Java プラットフォームでは、クラスごとに独自のローカライズ版が保持されるので、サポートされるロケールの集合は 1 種類だけでなくてもかまいません。ただし、Java プラットフォームのクラスとしては、一貫性のあるローカリゼーションをサポートしています。Java プラットフォームのほかの実装では、異なるロケールをサポートする場合があります。Sun の Java SE Runtime Environments がサポートするロケールの一覧は、「サポートされているロケール」を参照してください。
ローカライズされたリソース
すべてのロケール依存クラスは、サポートするロケール用にカスタマイズされたリソースにアクセスできなければなりません。ローカリゼーションの処理を容易にするには、ロケールごとにリソースをグループ化し、プログラムのロケールに依存しない部分から切り離すことが有用です。
ResourceBundle クラス
ResourceBundle クラスは、リソースのコンテナを表す抽象基底クラスです。プログラムでは、特定のロケールのためのリソースを含む ResourceBundle のサブクラスを作成します。使用するコードを変更しなくても、ResourceBundle のインスタンスに新しいリソースを追加したり、ResourceBundle の新しいインスタンスをシステムに追加したりできます。リソースをクラスとしてパッケージ化することで、Java のクラスローディング機構を利用してリソースを探すことができます。
リソースバンドルには、ロケール固有のオブジェクトが含まれています。String オブジェクトなど、ロケール固有のリソースが必要な場合は、現在のユーザーのロケールに適したリソースバンドルからリソースをロードします。このようにして、リソースのバンドルに含まれているロケール固有の情報のすべて、または少なくとも大部分を切り離し、ユーザーのロケールとの依存関係が弱いコードを作成できます。
そのため、次のような特徴を備えた Java コードを作成できます。
- 別の言語に簡単にローカライズつまり翻訳できる
- 複数のロケールを同時に扱うことができる
- あとから新しいロケールのサポートを簡単に追加できる
ResourceBundle.Control Class
ResourceBundle.Control は ResourceBundle の入れ子のクラスです。このクラスで、ResourceBundle.getBundle ファクトリメソッドから呼び出されるメソッドを定義すれば、リソースバンドルロード処理の動作を変更することができます。たとえば、XML などのアプリケーション固有のリソースバンドル形式は、メソッドをオーバーライドすることでサポート可能になります。
ListResourceBundle クラス
ListResourceBundle クラスは ResourceBundle クラスの抽象サブクラスで、便利で使いやすい一覧を利用して、ロケールのリソースを管理します。
PropertyResourceBundle クラス
PropertyResourceBundle クラスは ResourceBundle クラスを具体化したサブクラスで、プロパティーファイルから取り出した固定文字列群を利用して、ロケールのリソースを管理します。
日付と時刻の処理
java.util.Date クラスは、タイムゾーンやロケールとは関係なく、時間の特定の瞬間をミリ秒の精度で表します。
Date クラスには、日付を年、月、日、時、分、秒の値として解釈したり、日付の文字列の書式指定や構文解析を実行したりするメソッドがいくつか組み込まれています。これらのメソッドは国際化と互換性がないため、その大部分は使用が推奨されていません。これらのメソッドの代わりに、日付と時刻のフィールド間の変換には Calendar クラスを、また日付の文字列の書式指定と構文解析には DateFormat クラスを、それぞれ使う必要があります。
Calendar クラス
Calendar クラスは抽象基底クラスで、内部時間 (1970 年 1 月 1 日 00:00:00 GMT からの経過時間をミリ秒で表したもの) と、年、月、週などを表す整数値の間の変換を行うことができます。GregorianCalendar クラスは Calendar クラスを具体化したサブクラスで、グレゴリオ暦 (太陽暦) の規則に従ってこの処理を行います。
Calendar クラスとそのサブクラスは、時刻の値をさまざまな方法で操作するときに便利です。Calendar オブジェクトのフィールドと結果として得られた日付に対して、数値演算を行うことができます。Calendar オブジェクトでは、特定の言語とカレンダのスタイルに対する日付と時刻の書式指定を実装するために必要なすべての時刻フィールドの値を生成できます。詳細は「サポートされるカレンダ」 のドキュメントを参照してください。
TimeZone クラス
抽象クラスである TimeZone は、GMT (グリニッジ標準時) のタイムゾーンのオフセットと使用可能なサマータイムのオフセットをカプセル化しています。TimeZone.getTimeZone ファクトリメソッドを呼び出せば、タイムゾーン ID に対応する TimeZone インスタンスが得られます。TimeZone.getDefault ファクトリメソッドは、プラットフォームのタイムゾーンを自動的に検出し、そのプラットフォームに合った TimeZone インスタンスを返します。
Calendar クラスとそのサブクラスは、TimeZone クラスを使用して現地時刻と UTC との変換を行います。UTC は、Date オブジェクトが使用する内部表現です。ほとんどのプログラムでは、TimeZone オブジェクトを直接扱う必要はありません。
テキスト処理
書式指定
データを出力するときの書式指定には、多くの文化的な慣習が適用されます。数値、日付、時刻、およびメッセージのすべてについて、書式を指定してからでないと表示できない場合があります。Java プラットフォームでは、柔軟性のある書式指定クラス群が提供されており、ロケールの標準的な書式および独自に定義された書式の両方を扱うことができます。これらの書式指定クラスを使うと、書式を設定された文字列の構文を解析して、構成するオブジェクトに戻すこともできます。
Format クラス
Format クラスは、日付、時刻、メッセージ、数値など、ロケールに依存する情報に書式を指定する機能のための、抽象基底クラスです。主要なサブクラスとして、DateFormat、NumberFormat、および MessageFormat の 3 つが提供されています。これら 3 つのクラスでは、それぞれ独自のサブクラスが提供されています。
DateFormat クラス
日付と時刻は内部的にはロケールに依存しない方法で格納されますが、ロケールを反映した形式で表示できるよう書式を指定する必要があります。たとえば、次は同じ日付に対する異なる書式の例です。
- November 3, 1997 (英語)
- 3 novembre 1997 (フランス語)
DateFormat クラスは、ロケールに依存しない方法で日付と時刻の値の書式指定と構文解析を行うための、抽象基底クラスです。特定のロケールに対する時刻の標準書式を取得するための static ファクトリメソッドがいくつか用意されています。
DateFormat オブジェクトは、Calendar オブジェクトと TimeZone オブジェクトを使って、時刻の値を解釈します。デフォルトでは、特定のロケールに対する DateFormat オブジェクトは、そのロケールに対する適切な Calendar オブジェクトとシステムのデフォルトの TimeZone オブジェクトを使います。これらの設定は、必要に応じてオーバーライドできます。
SimpleDateFormat クラス
SimpleDateFormat クラスは具象クラスで、ロケールに依存した方法で日付と時刻の書式指定と構文解析を行います。このクラスを使うと、書式指定 (ミリ秒をテキストに)、構文解析 (テキストをミリ秒に)、および正規化を行うことができます。
DateFormatSymbols クラス
DateFormatSymbols クラスは、月の名前、曜日の名前、時刻、タイムゾーンのデータなど、日付と時刻の書式指定に関するローカライズ可能なデータをカプセル化するために使います。DateFormat クラスと SimpleDateFormat クラスはどちらも、DateFormatSymbols クラスを使ってこの情報をカプセル化します。
通常、プログラムで DateFormatSymbols クラスを直接使うことはありません。実際には、DateFormat クラスのファクトリメソッドで、書式指定の機能を実装します。
NumberFormat クラス
NumberFormat クラスは、数値データの書式指定と構文解析のための抽象基底クラスです。異なる種類のロケール固有の数値書式を取得するため、static ファクトリメソッドがいくつか用意されています。
NumberFormat クラスは、任意のロケールで数値の書式指定と構文解析を行うときに役に立ちます。このクラスを使うコードは、小数点、桁区切り、使われている特定の 10 進数字、または数値の書式が 10 進数かどうかなどに対するロケールの規則から、完全に独立しています。通常の 10 進数、通貨、パーセントなどで数値を表示することもできます。
- 1,234.5 (米国形式での 10 進数)
- $1,234.50 (米国形式での米国通貨)
- 1.234,50 € (ドイツ形式での欧州通貨)
- 123.450% (ドイツ形式でのパーセント)
DecimalFormat クラス
数値は、内部的にはロケールに依存しない方法で格納されていますが、ロケールを反映した形式で表示できるよう書式を指定する必要があります。たとえば、「#,###.00」というパターンを使うと、同じ数値でも次のように異なる書式になる場合があります。
- 1.234,56 (ドイツ語)
- 1,234.56 (英語)
DecimalFormat クラスは、NumberFormat クラスの具象サブクラスで、10 進数値の書式指定を行うことができます。通常、このクラスのインスタンスを直接生成することはありませんが、提供されているファクトリメソッドは使います。
DecimalFormat クラスには、数値の書式設定の方法を指定するパターン文字列を受け取る機能があります。パターンでは、数値の精度、先頭の 0 を表示するかどうか、使用する通貨記号などの属性を指定します。プログラムで独自の書式を作る必要がある場合は、パターン文字列を変更できます。
DecimalFormatSymbols クラス
DecimalFormatSymbols クラスは、数値の書式を指定するときに DecimalFormat が必要とする記号群 (小数点、グループ化区切り文字など) を表します。DecimalFormat クラスは、それ自体のために、ロケールデータから DecimalFormatSymbols クラスのインスタンスを生成します。これらの記号のどれかを変更する必要がある場合は、DecimalFormat オブジェクトから DecimalFormatSymbols オブジェクトを取得して修正できます。
ChoiceFormat クラス
ChoiceFormat クラスは、NumberFormat クラスの具象サブクラスです。ChoiceFormat クラスを使うと、ある範囲の数値に書式を設定できます。このクラスは、通常、MessageFormat オブジェクトの中で複数形を処理するときに使われます。詳細については、次の「MessageFormat クラス」を参照してください。
MessageFormat クラス
プログラムでは、一連の文字列、数値、およびほかのデータからメッセージを作らなければならない場合がよくあります。たとえば、ディスクドライブにあるファイルの数を表示するメッセージのテキストは、状況によって次のように変わります。
- The disk C contains 100 files.
- The disk D contains 1 file.
- The disk F contains 0 files.
一連の文字列と数値から組み立てるメッセージがハードコードされている場合は、ほかの言語に翻訳できません。たとえば、次の例で、パラメータの「3」と「G」の位置が違うことに注意してください。
- The disk G contains 3 files.(日本語)
- Il y a 3 fichiers sur le disque G. (フランス語)
MessageFormat クラスを使うと、言語に依存しない方法で、文字や数字を連結したメッセージを作成できます。MessageFormat オブジェクトは、複数のオブジェクトを受け取り、書式を設定して、パターンの適切な位置に書式を設定した文字列を挿入します。
ParsePosition クラス
ParsePosition クラスは、Format クラスとそのサブクラスによって使用され、構文解析を行なっている間の現在位置を記録します。Format クラスの parseObject() メソッドでは、引数として ParsePosition オブジェクトが必要です。
FieldPosition クラス
FieldPosition クラスは、Format クラスとそのサブクラスによって使用され、書式指定された出力のフィールドを識別します。Format クラスの format() メソッドの 1 つでは、引数として FieldPosition オブジェクトが必要です。
ロケールに依存する文字列の操作
プログラムでは、文字列の操作が頻繁に必要になります。文字列に対する共通の操作として、検索とソートがあります。文字列の照合やテキストのさまざまな境界の検出など、ある種の処理は、正確に行おうとすると非常に難しく、複数の言語を考慮する必要がある場合はさらに困難になります。Java プラットフォームでは、このような共通の文字列操作の多くをロケールに依存した方法で処理するためのクラス群が提供されています。
Collator クラス
Collator クラスでは、ロケールに依存した文字列の比較が行われます。自然言語テキストのための検索ルーチンおよびアルファベット順ソートルーチンを作るには、このクラスを使います。Collator は抽象基底クラスです。サブクラスでは、具体的な照合方法が実装されます。現在、Java プラットフォームでは 1 つのサブクラス RuleBasedCollator が提供されており、広範な言語群に適用できます。ほかのサブクラスを作成し、さらに特別なニーズを扱うことができます。
RuleBasedCollator クラス
RuleBasedCollator クラスは、Collator クラスの具象サブクラスで、データ駆動の簡単なテーブル照合機能を提供します。RuleBasedCollator クラスを利用し、目的に合わせてカスタマイズしたテーブルベースの照合機能を作成できます。たとえば、大文字、アクセント、および Unicode 複合文字を無視 (または意識) する照合機能を作ることができます。
CollationElementIterator クラス
CollationElementIterator クラスは、多国語文字列の各文字を処理するときの反復子として使われます。反復子は、位置付けされた文字の順序の優先順位を返すために使われます。文字の順序の優先順位つまりキーは、特定の Collator オブジェクトの中で文字を照合する方法を定義するものです。CollationElementIterator クラスは、RuleBasedCollator クラスの compare() メソッドで使われます。
CollationKey クラス
CollationKey オブジェクトは、特定の Collator オブジェクトの規則が適用された文字列を表します。2 つの CollationKey オブジェクトを比較すると、それらが表す文字列の相対的な順序が返されます。CollationKey オブジェクトを使って文字列を比較する方が、一般に、Collator.compare() メソッドを使うより高速です。したがって、文字列の一覧をソートするときのように、文字列を比較する回数が多い場合は、CollationKey オブジェクトを使う方が効率的です。
BreakIterator クラス
BreakIterator クラスは、テキスト文字列の中から次のような種類の境界の位置を見つけるためのメソッドを間接的に実装します。
- 潜在的な行ブレーク
- 文
- 語
- 文字
行、文、語、および文字を区切る場所の規則は、言語の種類により異なります。BreakIterator クラスはロケールに依存するので、テキストを操作するプログラムで使うことができます。たとえば、文字の強調表示、語の切り取り、次の文へのカーソルの移動、行末での折り返しなどが可能なワープロプログラムを考えます。このワープロプログラムは、ブレーク反復子を使ってテキストの論理的な境界を決定し、ロケールを意識した方法でテキストを操作できるようにします。
StringCharacterIterator クラス
StringCharacterIterator クラスは、Unicode 文字の文字列に対して双方向の反復処理を行う機能を提供します。このクラスは、カーソルを使ってある範囲のテキストの中を移動し、個別の文字または文字のインデックス値を返すことができます。StringCharacterIterator クラスは、CharacterIterator インタフェースの文字反復子機能を実装しています。
CharacterIterator インタフェース
CharacterIterator インタフェースは、Unicode 文字に対する双方向の反復処理のためのプロトコルを定義しています。ある範囲のテキストの中を移動し、個別の Unicode 文字またはそのインデックス値を返すクラスの場合、このインタフェースを実装する必要があります。CharacterIterator は、文字検索を行うときに役に立ちます。
Normalizer クラス
Normalizer クラスは、Unicode テキストを等価の形式に変換あるいは復元するメソッドを提供します。このクラスは、Unicode 標準によって定義された「Unicode Normalization Form」をサポートします。
ロケールに依存するサービスの SPI
java.text および java.util パッケージ内のクラスが提供する、ロケールに依存するサービスは、「ロケールに依存するサービスのSPI」を実装すれば、Java ランタイムがまだサポートしていないロケールにも拡張することができます。java.util パッケージに含まれる Currency、Locale、TimeZone の各クラスのローカライズされた記号や名前のほか、java.text パッケージに含まれる次のクラスの実装は、SPI とともにプラグインすることができます。
文字エンコーディングの変換
Java プラットフォームは、ネイティブの文字エンコーディングとして Unicode を使っていますが、Java プログラムの多くでは、まだ、ほかのエンコーディングのテキストデータを扱う必要があります。そのため、Java では、多くの標準的な文字エンコーディングと Unicode の間の変換を行うクラス群が提供されています。Unicode 以外のテキストデータを扱う必要がある Java プログラムでは、データをいったん Unicode に変換し、Unicode としてデータを処理してから、その結果を変換して外部の文字エンコーディングに戻します。InputStreamReader クラスと OutputStreamWriter クラスでは、ほかの文字エンコーディングと Unicode の間の変換を行うメソッドが提供されています。
サポートされているエンコーディング
サポートされているエンコーディング InputStreamReader、OutputStreamWriter、String の各クラスでは、Unicode と「サポートされているエンコーディング」の一覧に示されている文字エンコーディングの間での変換が可能です。
ストリーム入出力
Java プラットフォームでは、文字データ処理機能を向上させるため、java.io パッケージに機能が追加されています。つまり、Reader クラスと Writer クラスの追加、および PrintStream クラスに対する拡張です。
Reader クラスと Writer クラス
Reader クラスと Writer クラスの階層は、文字ストリームで入出力操作を行う機能を提供します。これらの階層は、InputStream クラスと OutputStream クラスの階層と並列になっていますが、バイトのストリームではなく、文字のストリームを処理します。文字ストリームを使うと、特定の文字エンコーディングに依存しないプログラムを簡単に記述でき、したがって、国際化も簡単になります。Reader クラスと Writer クラスには、Unicode とほかの文字エンコーディングの間の変換を行う機能もあります。Reader クラスと Writer クラスの階層の詳細については、「文字ストリーム (JDK 1.1 から導入)」を参照してください。
PrintStream クラス
PrintStream クラスは、システムのデフォルトの文字エンコーディングと行末記号を使って出力を生成します。この変更により、System.out.println() などのメソッドは、ASCII 以外のデータをより適切に処理できます。
charset パッケージ
java.nio.charset パッケージは、文字エンコーディング変換のための土台を提供します。アプリケーションでは、このパッケージに含まれるクラスを使用して、組み込みの文字変換プログラムの動作を微調整できます。また、java.nio.charset.spi パッケージを使用すると、組み込みの文字変換プログラムでサポートされていない文字エンコーディング用のカスタム変換プログラムを作成することもできます。
テキスト入力
インプットメソッド
インプットメソッドは、キーボードによる単純入力以外の方法でテキストを入力するためのソフトウェアコンポーネントです。インプットメソッドは、多くの種類の文字が必要な日本語、中国語、または韓国語を、文字数よりはるかにキー数が少ないキーボードから入力する方式として普及しています。Java プラットフォームでは、この 3 言語以外のインプットメソッドもサポートされており、手書きや音声認識などの異なる入力機構にも使用できます。
また、Windows または Solaris などのホストオペレーティングシステムから提供されるネイティブインプットメソッドを使うことができるほか、Java プログラミング言語で記述されたインプットメソッドを実装して使うこともできます。
インプットメソッドという用語は、Java プログラミング言語のクラスメソッドを指しているのではありません。
Swing でのインプットメソッドのサポート
Swing テキストコンポーネントは、インプットメソッドを使ったテキスト入力のための統合ユーザーインタフェースを提供します。ロケールに応じて、オンザスポットまたはビロウザスポット入力方式が使用されます。ほとんどのロケールで使用されているオンザスポット (インライン) 入力の場合、インプットメソッドはテキストを入力している間テキストをテキストコンポーネントに直接挿入します。中国語圏のロケールで使用されているビロウザスポットテキスト入力の場合は、独立した変換ウィンドウが使用されます。このウィンドウは、確定したテキストの挿入位置の近くに自動的に配置されます。
Swing テキストコンポーネントを使用するアプリケーションでは、テキストコンポーネントとインプットメソッド間のやり取りを調整する必要はありません。ただし、ドキュメントを保存または印刷する場合など、すべてのテキストの確定が必要な場合は、