~jan0sch/smederee
Showing details for patch fe612691c2401e3626b15556fc8529509dcabaa9.
diff -rN -u old-smederee/build.sbt new-smederee/build.sbt --- old-smederee/build.sbt 2025-02-02 17:06:46.912340192 +0000 +++ new-smederee/build.sbt 2025-02-02 17:06:46.916340200 +0000 @@ -263,6 +263,7 @@ name := "i18n", version := "0.1.0-SNAPSHOT", libraryDependencies ++= Seq( + library.logback, library.munit % Test, library.munitDiscipline % Test, library.munitScalaCheck % Test, diff -rN -u old-smederee/modules/i18n/src/main/scala/de/smederee/i18n/Messages.scala new-smederee/modules/i18n/src/main/scala/de/smederee/i18n/Messages.scala --- old-smederee/modules/i18n/src/main/scala/de/smederee/i18n/Messages.scala 2025-02-02 17:06:46.912340192 +0000 +++ new-smederee/modules/i18n/src/main/scala/de/smederee/i18n/Messages.scala 2025-02-02 17:06:46.916340200 +0000 @@ -13,10 +13,42 @@ import java.util.ResourceBundle import java.text.MessageFormat +import org.slf4j.LoggerFactory + +import scala.util.{ Failure, Success, Try } + object Messages { + private val log = LoggerFactory.getLogger(getClass) + val DefaultLocale: Locale = Locale.ENGLISH val Filename: String = "messages" + /** Provide a way to simply write `Messages("my.key", foo, bar)` to translate stuff. This function will + * catch possible exceptions underneath and in case of an error will log an error message and the + * underlying exception and will return the given message string instead a translation! + * + * @param message + * The message to be translated, which should be a valid property key. + * @param args + * A list of arguments which will be used in the [[java.text.MessageFormat]] to fill in placeholders. + * @param locale + * The implicitly provided locale which determines which resource bundle will be used. + * @return + * The translated and formatted (placeholders filled in) string. + */ + def apply(message: String, args: Any*)(using locale: Locale): String = + Try { + val usedLocale = + Option(locale).getOrElse(DefaultLocale) // Fallback to default locale if provided one is null. + val formatter = new MessageFormat(getProperty(usedLocale)(message), usedLocale) + formatter.format(args.toArray) + } match { + case Failure(error) => + log.error(s"Error during translation of '$message' for locale $locale!", error) + message + case Success(translation) => translation + } + /** Provide a way to simply write `Messages("my.key", foo, bar)` to translate stuff. * * @param message @@ -29,7 +61,7 @@ * The translated and formatted (placeholders filled in) string. */ @throws[java.util.MissingResourceException]("if the message key cannot be found in the resource bundle") - def apply(message: String, args: Any*)(using locale: Locale): String = { + def unsafeApply(message: String, args: Any*)(using locale: Locale): String = { val usedLocale = Option(locale).getOrElse(DefaultLocale) // Fallback to default locale if provided one is null. val formatter = new MessageFormat(getProperty(usedLocale)(message), usedLocale) diff -rN -u old-smederee/modules/i18n/src/test/resources/logback-test.xml new-smederee/modules/i18n/src/test/resources/logback-test.xml --- old-smederee/modules/i18n/src/test/resources/logback-test.xml 1970-01-01 00:00:00.000000000 +0000 +++ new-smederee/modules/i18n/src/test/resources/logback-test.xml 2025-02-02 17:06:46.916340200 +0000 @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration debug="false"> + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>WARN</level> + </filter> + <encoder> + <pattern>%date %highlight(%-5level) %cyan(%logger{0}) - %msg%n</pattern> + </encoder> + </appender> + + <appender name="async-console" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="console"/> + <queueSize>5000</queueSize> + <discardingThreshold>0</discardingThreshold> + </appender> + + <logger name="de.smederee.i18n" level="OFF" additivity="false"> + <appender-ref ref="console"/> + </logger> + + <root> + <appender-ref ref="console"/> + </root> +</configuration> diff -rN -u old-smederee/modules/i18n/src/test/scala/de/smederee/i18n/MessagesTest.scala new-smederee/modules/i18n/src/test/scala/de/smederee/i18n/MessagesTest.scala --- old-smederee/modules/i18n/src/test/scala/de/smederee/i18n/MessagesTest.scala 2025-02-02 17:06:46.916340200 +0000 +++ new-smederee/modules/i18n/src/test/scala/de/smederee/i18n/MessagesTest.scala 2025-02-02 17:06:46.916340200 +0000 @@ -29,11 +29,21 @@ } } - property("Messages must fail with MissingResourceException if key is not defined in resource bundle") { + property("Messages must return the given key if it is not defined in the resource bundle") { + forAll { (message: String) => + given Locale = Messages.DefaultLocale + val translation = Messages(message) + assertEquals(translation, message) + } + } + + property( + "Messages.unsafeApply must fail with MissingResourceException if key is not defined in the resource bundle" + ) { forAll { (message: String) => given Locale = Messages.DefaultLocale intercept[MissingResourceException] { - Messages(message) + Messages.unsafeApply(message) } assert(true) // Workaround for the intercept part. }