在Java中本地化異常消息

1.概述

Java中的異常用於表示程序中出現了問題。除了引發異常外,我們甚至可以添加一條消息以提供其他信息。

在本文中,我們將利用getLocalizedMessage方法來提供英語和法語的異常消息。

2.資源包Resource Bundle

我們需要一種使用messageKey標識消息並使用Locale messageKey提供值的轉換的查找消息的方法。我們將創建一個簡單的類來抽象化對ResourceBundle訪問,以檢索英語和法語消息翻譯:

public class Messages {



 public static String getMessageForLocale(String messageKey, Locale locale) {

 return ResourceBundle.getBundle("messages", locale)

 .getString(messageKey);

 }



 }

我們的Messages類使用ResourceBundle將屬性文件加載到我們的包中,該包位於我們的類路徑的根目錄下。我們有兩個文件-一個用於英語消息,一個用於法語消息:

# messages.properties

 message.exception = I am an exception.
# messages_fr.properties

 message.exception = Je suis une exception.

3.本地化的異常類

我們的Exception子類將使用默認的Locale來確定要為我們的消息使用的翻譯。我們將使用Locale#getDefault獲得默認的Locale

如果我們的應用程序在服務器上運行,我們將使用HTTP請求標頭來標識Locale ,而不是設置默認語言環境。為此,我們將創建一個構造函數以接受Locale.

讓我們創建我們的Exception子類。為此,我們可以擴展RuntimeExceptionException 。讓我們擴展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功能是否正常工作:

@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 服務器端應用程序

當我們為客戶端應用程序本地化異常消息時,我們只需要擔心一個系統的當前Locale 。但是,如果要在服務器端應用程序中本地化異常消息,則應記住,切換默認Locale將影響應用程序服務器內的所有請求。

如果我們決定本地化異常消息,我們將在異常上創建一個構造函數以接受Locale 。這將使我們能夠在不更新默認Locale的情況下本地化消息。

6.總結

本地化異常消息非常簡單。我們需要做的就是為我們的消息ResourceBundle ,然後在我們的Exception子類中getLocalizedMessage