1. 概要

Javaの例外は、プログラムで問題が発生したことを通知するために使用されます。 例外をスローするだけでなく、メッセージを追加して追加情報を提供することもできます。

この記事では、 getLocalizedMessage メソッドを利用して、英語とフランス語の両方で例外メッセージを提供します。

2. リソースバンドル

messageKey を使用してメッセージを検索し、 Locale を使用して、messageKeyの値を提供する翻訳を特定する方法が必要です。 英語とフランス語のメッセージ翻訳を取得するためのResourceBundleへのアクセスを抽象化するための単純なクラスを作成します。

public class Messages {

    public static String getMessageForLocale(String messageKey, Locale locale) {
        return ResourceBundle.getBundle("messages", locale)
          .getString(messageKey);
    }

}

Messages クラスは、 ResourceBundle を使用して、クラスパスのルートにあるバンドルにプロパティファイルをロードします。 2つのファイルがあります。1つは英語のメッセージ用で、もう1つはフランス語のメッセージ用です。

# messages.properties
message.exception = I am an exception.
# messages_fr.properties
message.exception = Je suis une exception.

3. ローカライズされた例外クラス

Exception サブクラスは、デフォルトの Locale を使用して、メッセージに使用する翻訳を決定します。 Locale#getDefault を使用して、デフォルトのLocaleを取得します。

アプリケーションがサーバーで実行されている場合、デフォルトを設定する代わりに、HTTPリクエストヘッダーを使用して使用するロケールを識別します。この目的のために、を受け入れるコンストラクターを作成します。ロケール。

Exceptionサブクラスを作成しましょう。 このために、RuntimeExceptionまたはExceptionのいずれかを拡張できます。 Exception を拡張し、getLocalizedMessageをオーバーライドしてみましょう。

public class LocalizedException extends Exception {

    private final String messageKey;
    private final Locale locale;

    public LocalizedException(String messageKey) {
        this(messageKey, Locale.getDefault());
    }

    public LocalizedException(String messageKey, Locale locale) {
        this.messageKey = messageKey;
        this.locale = locale;
    }

    public String getLocalizedMessage() {
        return Messages.getMessageForLocale(messageKey, locale);
    }
}

4. すべてを一緒に入れて

すべてが機能することを確認するために、いくつかの単体テストを作成しましょう。 英語とフランス語の翻訳のテストを作成して、構築中にカスタムLocaleが例外に渡されることを確認します。

@Test
public void givenUsEnglishProvidedLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessage() {
    LocalizedException localizedException = new LocalizedException("message.exception", Locale.US);
    String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception.");
}

@Test
public void givenFranceFrenchProvidedLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() {
    LocalizedException localizedException = new LocalizedException("message.exception", Locale.FRANCE);
    String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception.");
}

例外では、デフォルトのLocaleも使用できます。 デフォルトのLocale機能が機能することを確認するために、さらに2つのテストを作成しましょう。

@Test
public void givenUsEnglishDefaultLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessages() {
    Locale.setDefault(Locale.US);

    LocalizedException localizedException = new LocalizedException("message.exception");
    String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception.");
}

@Test
public void givenFranceFrenchDefaultLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() {
    Locale.setDefault(Locale.FRANCE);

    LocalizedException localizedException = new LocalizedException("message.exception");
    String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage();

    assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception.");
}

5. 警告

5.1. スローアブルのロギング

Exceptionインスタンスをログに送信するために使用しているロギングフレームワークを覚えておく必要があります。

Log4J、Log4J2、およびLogbackは、 getMessage を使用してメッセージを取得し、ログアペンダーに書き込みます。 java.util.logging を使用する場合、コンテンツはgetLocalizedMessageから取得されます。

getMessageをオーバーライドしてgetLocalizedMessageを呼び出すことを検討すると、どのログ実装が使用されているかを気にする必要がなくなります。

5.2. サーバーサイドアプリケーション

クライアントアプリケーションの例外メッセージをローカライズする場合、1つのシステムの現在のLocaleについてのみ心配する必要があります。 ただし、サーバー側アプリケーションで例外メッセージをローカライズする場合は、デフォルトのロケールを切り替えると、アプリケーションサーバー内のすべてのリクエストに影響することに注意してください。

例外メッセージをローカライズすることにした場合は、Localeを受け入れるように例外にコンストラクターを作成します。 これにより、デフォルトのLocaleを更新せずにメッセージをローカライズすることができます。

6. 概要

例外メッセージのローカライズはかなり簡単です。 メッセージ用にResourceBundleを作成し、ExceptionサブクラスにgetLocalizedMessageを実装するだけです。

いつものように、例はGitHubから入手できます。