Created
January 20, 2012 11:49
-
-
Save BowlingX/1647010 to your computer and use it in GitHub Desktop.
Accept Language locale extraction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.scalatra.i18n | |
import org.scalatra.{CookieSupport, ScalatraKernel} | |
import java.util.Locale | |
import org.scalatra.i18n.Messages | |
object I18nSupport { | |
def localeKey = "locale" | |
def messagesKey = "messages" | |
} | |
trait I18nSupport { | |
this: ScalatraKernel with CookieSupport => | |
import I18nSupport._ | |
var locale: Locale = _ | |
var messages: Messages = _ | |
var userLocales: Array[Locale] = _ | |
before() { | |
locale = resolveLocale | |
messages = new Messages(locale) | |
} | |
/* | |
* Resolve Locale based on HTTP request parameter or Cookie | |
*/ | |
private def resolveLocale: Locale = { | |
resolveHttpLocale.map(localeFromObject(_)) getOrElse defaultLocale | |
} | |
/* | |
* Get locale string either from HTTP param or Cookie. | |
* | |
* If locale string is found in HTTP param, it will be set | |
* in cookie. | |
* | |
* If it's not found, then look at Accept-Language header. | |
* | |
*/ | |
private def resolveHttpLocale: Option[Any] = { | |
params.get(localeKey) match { | |
case Some(localeValue) => | |
cookies.set(localeKey, localeValue) | |
Some(localeValue) | |
case _ => cookies.get(localeKey) 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.getHeader("Accept-Language") match { | |
case s: String => { | |
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 | |
userLocales = locales | |
// We assume that all accept-languages are stored in order of quality | |
// (so first language is preferred) | |
Some(locales.head) | |
} | |
// Its possible that "Accept-Language" header is not set | |
case _ => None | |
} | |
} | |
/** | |
* Reads a locale from any object | |
* @param in could be a string or Locale | |
*/ | |
private def localeFromObject(in: Any): Locale = { | |
if (in.isInstanceOf[String]) { | |
val token = in.asInstanceOf[String].split("_") | |
new Locale(token.head, token.last) | |
} else { | |
in.asInstanceOf[Locale] | |
} | |
} | |
private def defaultLocale: Locale = { | |
Locale.getDefault | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment