All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatra.i18n.I18nSupport.scala Maven / Gradle / Ivy

package org.scalatra
package i18n

import java.util.Locale
import org.scalatra.ServletCompat.http.HttpServletRequest

object I18nSupport {

  val LocaleKey: String = "org.scalatra.i18n.locale"

  val UserLocalesKey: String = "org.scalatra.i18n.userLocales"

  val MessagesKey: String = "messages"

}

trait I18nSupport { this: ScalatraBase =>

  import org.scalatra.i18n.I18nSupport._

  before() {
    if (!request.contains(LocaleKey)) {
      request(LocaleKey) = resolveLocale
    }
    if (!request.contains(MessagesKey)) {
      request(MessagesKey) = provideMessages(locale)
    }
  }

  def locale(implicit request: HttpServletRequest): Locale = {
    if (request == null) {
      throw new ScalatraException("There needs to be a request in scope to call locale")
    } else {
      request.get(LocaleKey).map(_.asInstanceOf[Locale]).orNull
    }
  }

  def userLocales(implicit request: HttpServletRequest): Array[Locale] = {
    if (request == null) {
      throw new ScalatraException("There needs to be a request in scope to call userLocales")
    } else {
      request.get(UserLocalesKey).map(_.asInstanceOf[Array[Locale]]).orNull
    }
  }

  def messages(key: String)(implicit request: HttpServletRequest): String = messages(request)(key)

  def messages(implicit request: HttpServletRequest): Messages = {
    if (request == null) {
      throw new ScalatraException("There needs to be a request in scope to call messages")
    } else {
      request.get(MessagesKey).map(_.asInstanceOf[Messages]).orNull
    }
  }

  /**
   * Provides a default Message resolver
   *
   * @param locale Locale used to create instance
   * @return a new instance of Messages, override to provide own implementation
   */
  def provideMessages(locale: Locale): Messages = Messages(locale)

  /*
  * Resolve Locale based on HTTP request parameter or Cookie
  */
  private def resolveLocale: Locale = resolveHttpLocale getOrElse defaultLocale

  /*
   * Get locale either from HTTP param, Cookie or Accept-Language header.
   *
   * If locale string is found in HTTP param, it will be set
   * in cookie. Later requests will read locale string directly from this
   *
   * If it's not found, then look at Accept-Language header.
   *
   * Locale strings are transformed to [[java.util.Locale]]
   *
   */
  private def resolveHttpLocale: Option[Locale] = {
    (params.get(LocaleKey) match {
      case Some(localeValue) =>
        cookies.set(LocaleKey, localeValue)
        Some(localeValue)
      case _ => cookies.get(LocaleKey)
    }).map(localeFromString(_)) orElse resolveHttpLocaleFromUserAgent
  }

  /**
   * Accept-Language header looks like "de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4"
   * Specification see [[http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html]]
   *
   * @return first preferred found locale or None
   */
  private def resolveHttpLocaleFromUserAgent: Option[Locale] = {
    request.headers.get("Accept-Language") map { s =>
      val locales = s.split(",").map(s => {
        def splitLanguageCountry(s: String): Locale = {
          val langCountry = s.split("-")
          if (langCountry.length > 1) {
            new Locale(langCountry.head, langCountry.last)
          } else {
            new Locale(langCountry.head)
          }
        }
        // If this language has a quality index:
        if (s.indexOf(";") > 0) {
          val qualityLocale = s.split(";")
          splitLanguageCountry(qualityLocale.head)
        } else {
          splitLanguageCountry(s)
        }
      })
      // save all found locales for later user
      request.setAttribute(UserLocalesKey, locales)
      // We assume that all accept-languages are stored in order of quality
      // (so first language is preferred)
      locales.head
    }
  }

  /**
   * Reads a locale from a String
   * @param in a string like en_GB or de_DE
   */
  private def localeFromString(in: String): Locale = {
    val token = in.split("_")
    new Locale(token.head, token.last)
  }

  private def defaultLocale: Locale = Locale.getDefault

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy