diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/LocalizedException.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/LocalizedException.java new file mode 100644 index 0000000000..c3f9980b99 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/LocalizedException.java @@ -0,0 +1,47 @@ +package com.baeldung.exceptions.localization; + +import java.util.Locale; + +public class LocalizedException extends Exception { + + private static final long serialVersionUID = 1L; + + 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; + } + + /** + * @return a localized message based on the messageKey provided at instantiation. + */ + public String getMessage() { + + /* + * This is a deliberate role reversal of the default implementation of getLocalizedMessage. + * some logging frameworks like Log4J 1 & 2 and Logback will use getMessage instead of + * getLocalizedMessage when logging Throwables. If we want to use these frameworks in client + * applications to log localized messages, then we'll need to override getMessage in a + * similar fashion to return the appropriate content. Or, you can call getLocalizedMessage + * on your own to create the log content. + */ + return getLocalizedMessage(); + } + + /** + * @return a localized message based on the messageKey provided at instantiation. + */ + public String getLocalizedMessage() { + + /* + * java.util.logging uses getLocalizedMessage when logging Throwables. + */ + return Messages.getMessageForLocale(messageKey, locale); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/Messages.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/Messages.java new file mode 100644 index 0000000000..1079bedd1a --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/Messages.java @@ -0,0 +1,27 @@ +package com.baeldung.exceptions.localization; + +import java.util.Locale; +import java.util.ResourceBundle; + +public class Messages { + + /** + * Retrieves the value for the messageKey from the locale-specific messages.properties, or from + * the base messages.properties for unsupported locales. + * + * @param messageKey The key for the message in the messages.properties ResourceBundle. + * @param locale The locale to search the message key. + * @return The value defined for the messageKey in the provided locale. + */ + public static String getMessageForLocale(String messageKey, Locale locale) { + + /* + * For more complex implementations, you will want a var-args parameter for MessageFormat + * substitutions. Then we can read the value from the bundle and pass the value with the + * substitutions to MessageFormat to create the final message value. + */ + return ResourceBundle.getBundle("messages", locale) + .getString(messageKey); + } + +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/resources/messages.properties b/core-java-modules/core-java-exceptions-3/src/main/resources/messages.properties new file mode 100644 index 0000000000..b6122d7f21 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/resources/messages.properties @@ -0,0 +1 @@ +message.exception = I am an exception. \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/main/resources/messages_fr.properties b/core-java-modules/core-java-exceptions-3/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..f28e0d54ff --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/resources/messages_fr.properties @@ -0,0 +1 @@ +message.exception = Je suis une exception. \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/LocalizedExceptionUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/LocalizedExceptionUnitTest.java new file mode 100644 index 0000000000..a46ca05d23 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/LocalizedExceptionUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.exceptions.localization; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LocalizedExceptionUnitTest { + + private Locale originalDefaultLocale; + + @Before + public void saveOriginalDefaultLocale() { + originalDefaultLocale = Locale.getDefault(); + } + + @After + public void restoreOriginalDefaultLocale() { + Locale.setDefault(originalDefaultLocale); + } + + @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."); + } + + @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."); + } + +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/MessagesUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/MessagesUnitTest.java new file mode 100644 index 0000000000..7a6cb8ed32 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/MessagesUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.exceptions.localization; + +import org.junit.Test; + +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MessagesUnitTest { + + @Test + public void givenUsEnglishLocale_whenRetrievingMessage_thenEnglishTranslationIsReturned() { + String translatedMessage = Messages.getMessageForLocale("message.exception", Locale.US); + + assertThat(translatedMessage).isEqualTo("I am an exception."); + } + + @Test + public void givenFranceFrenchLocale_whenRetrievingMessage_thenFrenchTranslationIsReturned() { + String translatedMessage = Messages.getMessageForLocale("message.exception", Locale.FRANCE); + + assertThat(translatedMessage).isEqualTo("Je suis une exception."); + } + +}