### Default Babel Setup (sbt) Source: https://taig.github.io/babel/installation This configuration provides a default setup commonly used in Babel documentation, combining Circe for serialization, generic codecs for data mapping, and the HOCON loader for translation resources. ```sbt "io.taig" %%% "babel-circe" % "0.5.3" "io.taig" %%% "babel-generic" % "0.5.3" "io.taig" %%% "babel-loader" % "0.5.3" ``` -------------------------------- ### Install Babel Core Module (sbt) Source: https://taig.github.io/babel/installation This dependency includes the dependency-free core module, containing all data class definitions, type classes, and pre-defined locales for Babel. ```sbt "io.taig" %%% "babel-core" % "0.5.3" ``` -------------------------------- ### Install Babel HOCON Loader (sbt) Source: https://taig.github.io/babel/installation This dependency enables reading HOCON translation definitions directly from resources, simplifying the process of loading translations in your application. ```sbt "io.taig" %%% "babel-loader" % "0.5.3" ``` -------------------------------- ### Install Babel Cats Integration (sbt) Source: https://taig.github.io/babel/installation This dependency provides Cats type class instances for Babel, enabling integration with the Cats functional programming library. ```sbt "io.taig" %%% "babel-cats" % "0.5.3" ``` -------------------------------- ### Install Babel Circe Serialization (sbt) Source: https://taig.github.io/babel/installation This dependency adds support for serialization formats using Circe, a popular JSON library for Scala, allowing Babel translations to be handled via Circe. ```sbt "io.taig" %%% "babel-circe" % "0.5.3" ``` -------------------------------- ### Install Babel Generic Codecs (sbt) Source: https://taig.github.io/babel/installation This dependency provides codecs to populate custom data classes from translation objects, offering flexibility in how translation data is mapped. ```sbt "io.taig" %%% "babel-generic" % "0.5.3" ``` -------------------------------- ### Babel Translation Configuration Source: https://taig.github.io/babel/guide-arguments Shows example configuration files for English and German locales, demonstrating how parameterized strings are defined using `StringFormat2`. The example highlights how parameter order can differ between languages. ```conf en.conf: copysourceweather = "The temperature in {0} is {1} degrees Celsius." de.conf: copysourceweather = "Es sind {1} Grad Celsius in {0}." ``` -------------------------------- ### Plural Ranges Configuration Source: https://taig.github.io/babel/guide-plurals Configuration example for defining plural ranges using a key-value format. Supports exact matches, numerical ranges, and a fallback wildcard. ```Conf copysourceranges = { 1 = "Exact" "10-20" = "Range 10 to 20" "*" = "Fallback" } ``` -------------------------------- ### Scala Example: Loading and Using Plural Ranges Source: https://taig.github.io/babel/guide-plurals Demonstrates loading translations with plural ranges in Scala using Babel. It shows how to define a case class for translations, load them, and apply fallback mechanisms. ```Scala import cats.effect._ import cats.effect.unsafe.implicits.global import cats.syntax.all._ import io.taig.babel._ import io.taig.babel.generic.auto._ final case class I18n(ranges: Quantities[String]) val i18n = Loader .default[IO] .load("plurals-ranges", Set(Locales.en)) .map(Decoder[I18n].decodeAll) .rethrow .map(_.withFallback(Locales.en)) .flatMap(_.liftTo[IO](new IllegalStateException("Translations for en missing"))) .map(_.apply(Locales.en)) .unsafeRunSync() // i18n: I18n = I18n({1: "Exact", 10-20: "Range 10 to 20", *: "Fallback"}) ``` ```Scala REPL i18n.ranges(0) // res8: String = "Fallback" i18n.ranges(1) // res9: String = "Exact" i18n.ranges(9) // res10: String = "Fallback" i18n.ranges(10) // res11: String = "Range 10 to 20" i18n.ranges(11) // res12: String = "Range 10 to 20" i18n.ranges(20) // res13: String = "Range 10 to 20" i18n.ranges(21) // res14: String = "Fallback" ``` -------------------------------- ### Babel Use Translations with Arguments (Scala) Source: https://taig.github.io/babel/guide-arguments Provides examples of how to use the loaded and decoded translations with `StringFormat2`. It shows calling the `weather` field with the correct number and type of string arguments for both English and German locales. ```scala i18ns(Locales.en).weather("Cape Town", "26") // res0: String = "The temperature in Cape Town is 26 degrees Celsius." i18ns(Locales.de).weather("Frankfurt am Main", "18") // res1: String = "Es sind 18 Grad Celsius in Frankfurt am Main." ``` -------------------------------- ### Babel Compile-Time Error for Missing Arguments (Scala) Source: https://taig.github.io/babel/guide-arguments Illustrates Babel's compile-time guarantee by showing an example where `StringFormat2` is called with only one argument instead of the required two. This results in a compile-time error, preventing runtime issues. ```scala i18ns(Locales.en).weather("Stockholm") // error: // missing argument for parameter v1 of method apply in class StringFormat2: (v0: String, v1: String): String ``` -------------------------------- ### Run Sample Backend Source: https://taig.github.io/babel/sample Command to run the sample backend application using sbt. ```shell > sbt sampleBackend/run ``` -------------------------------- ### Babel: Basic Plural Handling with Quantities in Scala Source: https://taig.github.io/babel/guide-plurals Demonstrates how to define and use plural translations using Babel's `Quantities` class. It shows loading translations from a configuration file and accessing them based on quantity values. ```hocon copysourcebicycles = { 0 = "There are no bicycles in Beijing" 1 = "There is one bicycle in Beijing" "*" = "There are 9 million bicycles in Beijing" } ``` ```scala import cats.effect._ import cats.effect.unsafe.implicits.global import cats.syntax.all._ import io.taig.babel._ import io.taig.babel.generic.auto._ final case class I18n(bicycles: Quantities[String]) val i18n = Loader .default[IO] .load("plurals", Set(Locales.en)) .map(Decoder[I18n].decodeAll) .rethrow .map(_.withFallback(Locales.en)) .flatMap(_.liftTo[IO](new IllegalStateException("Translations for en missing"))) .map(_.apply(Locales.en)) .unsafeRunSync() // i18n: I18n = I18n( // bicycles = Quantities( // default = "There are 9 million bicycles in Beijing", // quantities = List( // Element( // quantity = Exact(value = 0), // value = "There are no bicycles in Beijing" // ), // Element( // quantity = Exact(value = 1), // value = "There is one bicycle in Beijing" // ) // ) // ) // ) i18n.bicycles(0) // res0: String = "There are no bicycles in Beijing" i18n.bicycles(1) // res1: String = "There is one bicycle in Beijing" i18n.bicycles(100) // res2: String = "There are 9 million bicycles in Beijing" ``` -------------------------------- ### Working with ADTs for i18n lookups Source: https://taig.github.io/babel/cookbook Shows how to add helper methods to data classes for easier use with Babel, particularly for ADT lookups in internationalization. It includes defining ADTs, loading translations, and accessing them via ADT instances. ```Scala import cats.effect._ import cats.effect.unsafe.implicits.global import cats.syntax.all._ import io.taig.babel._ import io.taig.babel.generic.auto._ sealed abstract class Country extends Product with Serializable object Country { case object France extends Country case object Italy extends Country } final case class CountryI18n(france: String, italy: String) { def apply(country: Country): String = country match { case Country.France => france case Country.Italy => italy } } final case class I18n(country: CountryI18n) val i18ns = Loader .default[IO] .load("cookbook-country", Set(Locales.en, Locales.de)) .map(Decoder[I18n].decodeAll) .rethrow .map(_.withFallback(Locales.en)) .flatMap(_.liftTo[IO](new IllegalStateException("Translations for en missing"))) .unsafeRunSync() // i18ns: NonEmptyTranslations[I18n] = NonEmptyTranslations(en -> I18n(CountryI18n(France,Italy)),Translations(Map(de -> I18n(CountryI18n(Frankreich,Italien))))) ``` ```Scala i18ns(Locales.en).country(Country.Italy) // res0: String = "Italy" ``` ```Scala i18ns(Locales.de).country(Country.France) // res1: String = "Frankreich" ``` -------------------------------- ### Babel Load and Decode Translations (Scala) Source: https://taig.github.io/babel/guide-arguments Demonstrates loading translations from files for specified locales and decoding them into a case class using Babel's `Loader` and `Decoder`. It includes error handling for missing translations and applies a fallback to English. ```scala import cats.effect._ import cats.effect.unsafe.implicits.global import cats.syntax.all._ import io.taig.babel._ import io.taig.babel.generic.auto._ final case class I18n(weather: StringFormat2) val i18ns = Loader .default[IO] .load("arguments", Set(Locales.en, Locales.de)) .map(Decoder[I18n].decodeAll) .rethrow .map(_.withFallback(Locales.en)) .flatMap(_.liftTo[IO](new IllegalStateException("Translations for en missing"))) .unsafeRunSync() // i18ns: NonEmptyTranslations[I18n] = NonEmptyTranslations(en -> I18n(The temperature in {0} is {1} degrees Celsius.),Translations(Map(de -> I18n(Es sind {1} Grad Celsius in {0}.)))) ``` -------------------------------- ### Babel Decode with Optional Arguments (Scala) Source: https://taig.github.io/babel/guide-arguments Demonstrates decoding a `StringFormat2` with a translation string that only uses one placeholder (`{0}`). This shows that not all defined placeholders need to be present in the translation string, and the `apply` method can still be used with the available arguments. ```scala Decoder[StringFormat2] .decode(Babel.text("It's always rainy in {0}")) .map(_.apply("London", "3")) // res3: Either[Error, String] = Right(value = "It's always rainy in London") ``` -------------------------------- ### http4s Middleware: Resolve Accept-Language Header Source: https://taig.github.io/babel/cookbook Creates an http4s middleware to parse the `Accept-Language` header. It leverages Java's `Locale.LanguageRange.parse` to order locales and matches them against application-supported `Locale`s. ```Scala import java.util.{Locale => JavaLocale} import scala.jdk.CollectionConverters._ import cats.Monad import io.taig.babel.Locale import org.http4s.HttpRoutes import org.http4s.headers.`Accept-Language` import org.http4s.implicits._ final class LocalesMiddleware[F[_]: Monad](locales: Set[Locale], fallback: Locale) { def apply(routes: Locale => HttpRoutes[F]): HttpRoutes[F] = HttpRoutes[F] { request => val locale = request.headers .get[`Accept-Language`] .map(_.value) .flatMap { value => JavaLocale.LanguageRange .parse(value) .asScala .sortWith(_.getWeight > _.getWeight) .map(language => JavaLocale.forLanguageTag(language.getRange)) .flatMap(Locale.fromJavaLocale) .find(locales.contains) } .getOrElse(fallback) routes(locale).run(request) } } ``` -------------------------------- ### Load Translations with Babel Loader Source: https://taig.github.io/babel/guide-loading Loads translation files from a specified directory into a Babel instance using Cats Effect. It requires specifying the directory name and a set of locales to load. ```scala import cats.effect._ import cats.effect.unsafe.implicits.global import io.taig.babel._ val babels = Loader.default[IO] .load("babel", Set(Locales.en, Locales.de, Locales.de_AT)) .unsafeRunSync() // babels: Translations[Babel] = Translations(Map(en -> Object(Map(greeting -> Value(Good afternoon))), de -> Object(Map(greeting -> Value(Guten Tag))), de-AT -> Object(Map(greeting -> Value(Grüß Gott))))) ``` -------------------------------- ### Babel StringFormat Placeholders Source: https://taig.github.io/babel/guide-arguments Defines how parameters are encoded in translation strings using `java.text.MessageFormat` style placeholders (e.g., `{0}`, `{1}`). It outlines rules such as unique placeholder usage, variable order across languages, and arity limits for `StringFormatN` helpers. ```APIDOC Babel StringFormat Rules: - Parameter placeholders are encoded in the style of `java.text.MessageFormat`, starting at index `0` (e.g. `{0}`, `{1}`, …). - Each placeholder index may be used at most once (e.g. `"lorem {0} dolar {0}"` is not allowed). - The order of the placeholders may vary across translations (e.g. `"The {0} {1} is fast"` and `"El {1} {0} es rapido"`). - There can not be more placeholders than arguments (e.g. `StringFormat1` can not be decoded when there is `{0}` and `{1}` as there is only 1 parameter). - It is a decoding error to define placeholder indices that exceed the `StringFormatN` arity (e.g. `StringFormat2` may only use `{0}` and `{1}`, but not `{2}`). - Not all placeholders must be used (e.g. `"Good afternoon, {0}. Today it's {1} degrees."` and `"Guten Tag, sehr geehrte Damen und Herren. Heute sind es {1} Grad."`). ``` -------------------------------- ### Babel: Plural Handling with Arguments and StringFormat in Scala Source: https://taig.github.io/babel/guide-plurals Illustrates advanced plural translation handling by combining `Quantities` with `StringFormat` to include dynamic arguments within pluralized strings. This allows for more complex and user-friendly translations. ```hocon copysourcebicycles = { 0 = "There are no bicycles in Beijing" 1 = "There is one bicycle in Beijing" "*" = "There are {0} bicycles in Beijing" } ``` ```scala import cats.effect._ import cats.effect.unsafe.implicits.global import cats.syntax.all._ import io.taig.babel._ import io.taig.babel.generic.auto._ final case class I18n(bicycles: Quantities[StringFormat1]) val i18n = Loader .default[IO] .load("plurals-arguments", Set(Locales.en)) .map(Decoder[I18n].decodeAll) .rethrow .map(_.withFallback(Locales.en)) .flatMap(_.liftTo[IO](new IllegalStateException("Translations for en missing"))) .map(_.apply(Locales.en)) .unsafeRunSync() // i18n: I18n = I18n({0: "There are no bicycles in Beijing", 1: "There is one bicycle in Beijing", *: "There are {0} bicycles in Beijing"}) i18n.bicycles(0) // res4: StringFormat1 = There are no bicycles in Beijing i18n.bicycles(100)("100") // res5: String = "There are 100 bicycles in Beijing" i18n.bicycles(9000000)("9 million") // res6: String = "There are 9 million bicycles in Beijing" ``` -------------------------------- ### HOCON Translation Files Source: https://taig.github.io/babel/guide-loading Defines translation strings for different locales in HOCON format. Each file corresponds to a locale and contains key-value pairs for translations. ```hocon copysourcegreeting = "Good afternoon" ``` ```hocon copysourcegreeting = "Guten Tag" ``` ```hocon copysourcegreeting = "Grüß Gott" ``` -------------------------------- ### Accessing Translated Strings Source: https://taig.github.io/babel/guide-loading Demonstrates how to access specific translated strings from the decoded data class for different locales. It shows behavior with existing and non-existing locales, including fallback. ```scala i18ns(Locales.de).greeting // res0: String = "Guten Tag" ``` ```scala i18ns(Locales.de_AT).greeting // res1: String = "Grüß Gott" ``` ```scala i18ns(Locales.de_CH).greeting // res2: String = "Guten Tag" ``` ```scala i18ns(Locales.fr).greeting // res3: String = "Good afternoon" ``` -------------------------------- ### Decode Babel Translations into Data Class Source: https://taig.github.io/babel/guide-loading Decodes the loaded Babel translations into a Scala data class using a generic decoder. It handles potential decoding errors and provides fallback mechanisms. ```scala import cats.syntax.all._ import io.taig.babel.generic.auto._ final case class I18n(greeting: String) object I18n { implicit val decoder: Decoder[I18n] = deriveDecoder[I18n] } val i18ns = IO.fromEither(Decoder[I18n].decodeAll(babels)) .map(_.withFallback(Locales.en)) .flatMap(_.liftTo[IO](new IllegalStateException("Translations for en missing"))) .unsafeRunSync() // i18ns: NonEmptyTranslations[I18n] = NonEmptyTranslations(en -> I18n(Good afternoon),Translations(Map(de -> I18n(Guten Tag), de-AT -> I18n(Grüß Gott)))) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.