1概要

多くのソフトウェア開発者は、職業上、多言語システムやアプリケーションを開発する機会に直面しています。これらは通常、さまざまな地域やさまざまな言語領域のエンドユーザーを対象としています。

これらのアプリケーションを維持および拡張することは常に困難です。さまざまなローカリゼーション固有のデータを同時に操作する機能は通常非常に重要です。アプリケーションデータの変更は、再コンパイルを必要とせずにできるだけ単純にする必要があります。そのため、ラベルやボタンの名前をハードコーディングしないようにしています。

幸いなことに、このクラスを提供するJavaを利用することで、上記の問題をすべて解決することができます。

簡単に言うと、

ResourceBundle

を使用すると、アプリケーションはロケール固有のデータを含む個別のファイルからデータをロードできます。


1.1.

リソースバンドル


最初に知っておくべきことは、1つのリソースバンドル内のすべてのファイルは同じパッケージ/ディレクトリにあり、共通のベース名を持つ必要があるということです。言語、国、またはプラットフォームを示すロケール固有のサフィックスがアンダースコア記号で区切られている場合があります。

言語コードがすでにある場合は国コードを、言語コードと国コードがある場合はプラットフォームを追加することが重要です。

ファイル名の例を見てみましょう。


  • ExampleResource


  • ExampleResource

    ja__


  • ExampleResource

    en

    US


  • ExampleResource

    en

    US

    UNIX__

各データバンドルのデフォルトファイルは、サフィックスのない

ExampleResource

です。

ResourceBundle

には2つのサブクラスがあります。


  • PropertyResourceBundle





    ListResourceBundle

    ** では、javaファイルと同様にプロパティファイルにもデータを入れ替えて保存できます。

各ファイルは

ロケール固有の名前と適切なファイル拡張子

を持つ必要があります。たとえば、

ExampleResource

en

US.properties

または

Example

en.java__などです。


1.2. プロパティファイル –

PropertyResourceBundle


プロパティファイルは__PropertyResourceBundleで表されます。これらのファイルは大文字と小文字を区別するキーと値のペアの形式でデータを格納します。

サンプルのプロパティファイルを分析しましょう。

# Buttons
continueButton continue
cancelButton=cancel

! Labels
helloLabel:hello

ご覧のとおり、キーと値のペアを定義する方法は3つあります。

それらはすべて同等ですが、最初のものはおそらく

Java

プログラマーの間で最も人気があります。プロパティファイルにもコメントを入れることができます。コメントは常に



または



で始まります。


1.3. Javaファイル –

ListResourceBundle


まず、言語固有のデータを格納するために、

ListResourceBundle

を拡張して

getContents()

メソッドをオーバーライドするクラスを作成する必要があります。クラス名の規則はプロパティファイルと同じです。


Localeごとに、

別々のJavaクラスを作成する必要があります。

これがサンプルクラスです。

public class ExampleResource__pl__PL extends ListResourceBundle {

    @Override
    protected Object[][]getContents() {
        return new Object[][]{
          {"currency", "polish zloty"},
          {"toUsdRate", new BigDecimal("3.401")},
          {"cities", new String[]{ "Warsaw", "Cracow" }}
        };
    }
}

Javaファイルは、

Strings.

だけでなく、プロパティファイルよりも1つ大きな利点があります。

一方、新しいロケール固有のJavaクラスを変更または導入するたびに、アプリケーションを再コンパイルする必要がありますが、プロパティファイルは追加の作業なしで拡張できます。


2リソースバンドルを使用する

リソースバンドルの定義方法はすでにわかっているので、使用する準備が整いました。

短いコードスニペットを考えてみましょう。

Locale locale = new Locale("pl", "PL");
ResourceBundle exampleBundle = ResourceBundle.getBundle("package.ExampleResource", locale);

assertEquals(exampleBundle.getString("currency"), "polish zloty");
assertEquals(exampleBundle.getObject("toUsdRate"), new BigDecimal("3.401"));
assertArrayEquals(exampleBundle.getStringArray("cities"), new String[]{"Warsaw", "Cracow"});

まず、デフォルトのものを使用したくない場合を除き、

Locale

を定義できます。

その後、静的ファクトリメソッド

ResourceBundle

を呼び出します。

バンドル名とそのパッケージ/ディレクトリ

およびロケールをパラメータとして渡す必要があります。

デフォルトのロケールが問題ない場合にのみバンドル名を必要とするファクトリメソッドもあります。オブジェクトが完成したらすぐに、それらのキーで値を取得できます。

さらに、この例では、

getString(String key)



getObject(String key)、

、および

getStringArray(String key)

を使用して必要な値を取得できることを示しています。


3適切なバンドルリソースの選択

  • バンドルリソースを使いたい場合は、

    Java

    がどのようにバンドルファイルを選択するかを知っておくことが重要です。

ポーランド語のラベルが必要なアプリケーションで作業しているのに、デフォルトの

JVM

ロケールが

Locale.US

であるとします。

最初に、アプリケーションはあなたが要求するロケールに適したクラスパスでファイルを探します。最も具体的な名前、つまりプラットフォーム、国、および言語を含む名前で始まります。

それから、それはより一般的に行きます。一致しない場合は、今回はプラットフォームチェックなしでデフォルトロケールにフォールバックします。

  • 一致しない場合は、デフォルトのバンドルを読み込もうとします。


  • Label

    pl

    PL

    UNIX__


  • Label

    pl

    PL


  • Label

    pl__


  • Label

    ja

    JP


  • Label

    ja__


  • ラベル

各名前は

.java

ファイルと

.properties

ファイルの両方を表すことに注意してください。ただし、前者が後者よりも優先されます。

適切なファイルがない場合は、

MissingResourceException

がスローされます。


4継承

リソースバンドルの概念のもう1つの利点は、プロパティの継承です。つまり、特定性の低いファイルに含まれるキーと値のペアは、継承ツリーの上位にあるファイルによって継承されます。

3つのプロパティファイルがあるとしましょう。

#resource.properties
cancelButton = cancel

#resource__pl.properties
continueButton = dalej

#resource__pl__PL.properties
backButton = cofnij


Locale(“ pl”、“ PL”)

に対して取得されたリソースバンドルは、結果に含まれる3つのキー/値すべてを返します。言及する価値があります、

プロパティの継承が考慮される限り、デフォルトのロケールバンドルにフォールバックすることはありません

さらに、**

ListResourceBundles



PropertyResourceBundles

は同じ階層にはありません。

そのため、プロパティファイルがクラスパスで見つかった場合、キーと値のペアはプロパティファイルからのみ継承されます。同じ規則がJavaファイルにも適用されます。


5カスタマイズ

これまでに学んだことは、

ResourceBundle

のデフォルト実装に関することだけでした。ただし、その動作を変更する方法はあります。

これを行うには、

ResourceBoundle.Control

を拡張し、そのメソッドをオーバーライドします。

たとえば、値をキャッシュに保持する時間を変更したり、キャッシュをリロードする必要があるときの条件を決定したりできます。

理解を深めるために、例として短い方法を用意しましょう。

public class ExampleControl extends ResourceBundle.Control {

    @Override
    public List<Locale> getCandidateLocales(String s, Locale locale) {
        return Arrays.asList(new Locale("pl", "PL"));
    }
}

この方法の目的は、クラスパスでファイルを選択する方法を変更することです。ご覧のとおり、

ExampleControl

は、デフォルトまたは定義された

Locale

が何であっても、ポーランド語の

Locale

のみを返します。


6. UTF-8


JDK 8以前のバージョンを使用しているアプリケーションはまだたくさんあるので、

Java

9以前の**

ListResourceBundles

は、

PropertyResourceBundles

よりももう1つの利点があることを知っておく価値があります。 JavaファイルはStringオブジェクトを格納できるため、

UTF-16__エンコーディングでサポートされている任意の文字を保持できます。

反対に、

PropertyResourceBundle

はデフォルトで

ISO 8859-1

エンコーディングを使ってファイルをロードします。


UTF-8

を超えた文字を保存するために、

Native-to-ASCII

コンバーター –

native2ascii

を使用することができます。 ISO 8859-1に準拠していないすべての文字を

\ uxxxx

表記にエンコードして変換します。

これがコマンドの例です。

native2ascii -encoding UTF-8 utf8.properties nonUtf8.properties

それでは、エンコーディングの変更前後のプロパティの様子を見てみましょう。

#Before
polishHello=cześć

#After
polishHello=cze\u015b\u0107

幸い、この不便さはJava 9にはもう存在しません。

JVM



UTF-8

エンコーディングでプロパティファイルを読み込み、ラテン文字以外の文字を使用しても問題はありません。


7. 結論


BundleResource

には、多言語アプリケーションを開発するために必要なものの多くが含まれています。ここで取り上げた機能により、さまざまなロケールの操作がかなり簡単になります。

また、ハードコーディングの値を避け、新しい

Locale

ファイルを追加するだけで、サポートされている

Locales

を拡張して、アプリケーションをスムーズに変更および維持できるようにします。

いつものように、サンプルコードはhttps://github.com/eugenp/tutorials/tree/master/core-java/src/main/java/com/baeldung/resourcebundle[GitHubで入手]で入手できます。