2014-05-07 47 views
2

簡短的問題是:有沒有一種方法在播放前提取ACCEPT_LANGUAGE請求頭以確定i18n語言?Scala的2.2版 - 使用ScalaInterceptors修改AcceptLanguage HTTP請求頭

我認爲這可以通過覆蓋路由請求來完成(參見http://www.playframework.com/documentation/2.2.0/ScalaInterceptors)。

但它似乎沒有工作。 這是我的「測試」的代碼,看到同樣在https://gist.github.com/mcallisto/3f428fad87f7a7759519

import play.api._ 
import play.api.mvc._ 
import play.api.http.HeaderNames 

object Global extends GlobalSettings { 

    override def onRouteRequest(rh: RequestHeader): Option[Handler] = { 
    Logger.info("Request: " + rh.toString) 
    Logger.info("Accepted languages : " + rh.acceptLanguages.mkString(", ")) 

    val newLang = "it" 

    val newHeaders = new Headers { val data = (rh.headers.toMap 
     + (HeaderNames.ACCEPT_LANGUAGE -> Seq(newLang))).toList } 

    val newRequestHeader = rh.copy(headers = newHeaders) 
    Logger.info("New accepted languages : " + newRequestHeader.acceptLanguages.mkString(", ")) 

    super.onRouteRequest(newRequestHeader) 
    } 

} 

沒有這個代碼,國際化功能根據影響AcceptLanguage標頭的瀏覽器設置工作。

有了它,即使標題顯然改爲意大利語(「it」)語言(請參閱記錄器),但i18n仍由瀏覽器語言提供。

在哪一點播放提取頭?

有沒有其他方法可以實現相同的目標?我只是想達到一個基本的步驟,其中請求子域(如it.example.com)普遍存在對瀏覽器的設置,以確定國際化

預先感謝您爲您提示

回答

1

注意,在onRouteRequest你將重寫行爲找到將處理您的請求的處理程序,而不是對處理程序本身的調用。

onRouteRequestonRequestReceived稱爲:

def onRequestReceived(request: RequestHeader): (RequestHeader, Handler) = { 
    val (routedRequest, handler) = onRouteRequest(request) map { 
     case handler: RequestTaggingHandler => (handler.tagRequest(request), handler) 
     case otherHandler => (request, otherHandler) 
    } getOrElse { 
     (request, Action.async(BodyParsers.parse.empty)(_ => this.onHandlerNotFound(request))) 
    } 

    (routedRequest, doFilter(rh => handler)(routedRequest)) 
    } 

注意如何(RequestHeader, Handler)類型的返回元組使用原始request。基本上,由於使用原始請求並將其應用於找到的處理函數,所以在onRouteRequest中執行的對請求的所有更改都將被完全忽略。

爲您的使用情況下,過濾器可能是一個更好的選擇:

object ItalianLanguage extends Filter { 
    def apply(next: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = { 
    // your code to set the italian language in request 
    next(request) 
    } 
} 
+0

還有一個道理:這是通過全球最好的方法嗎?我想知道性能是否明智,因爲它會在需要資產時修改標題,也許沒有必要這樣做。這可以做到更進一步,也許作爲一個行動生成器,可用於幾個控制器? – user2364174

+0

是的,你也可以使用動作組合。過濾器更有趣,可以添加會影響很多請求的行爲。如果只是少數,那麼行動會更好。 – vptheron

+0

理論上我想影響所有的行爲,但不是所有的請求。我會嘗試與行動組成。 也不是修改觸發Play i18n邏輯的AcceptLanguage標題,而不是修改Play邏輯本身的另一個選項?哪裏? – user2364174

2

由於@vptheron,這是工作

import play.api._ 
import play.api.mvc._ 
import play.api.http.HeaderNames 
import scala.concurrent.Future 

object LangFromSubdomain extends Filter { 
    def apply(next: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = { 

    val subdomainLanguage = request.domain.toString.substring(0, 3) match { 
     case "it." => "it" 
     case "es." => "es" 
     case _ => "en" 
    } 

    val newHeaders = new Headers { val data = (request.headers.toMap 
     + (HeaderNames.ACCEPT_LANGUAGE -> Seq(subdomainLanguage))).toList } 

    val newRequestHeader = request.copy(headers = newHeaders) 

    next(newRequestHeader) 
    } 
} 

object Global extends WithFilters(LangFromSubdomain) 
0

你可以試試這個:

import play.api._ 
import play.api.mvc._ 
import play.api.http.HeaderNames 
import scala.concurrent.Future 

object LangFromSubdomain extends Filter { 
    def apply(next: (RequestHeader) => Future[SimpleResult])(requestHeader: RequestHeader): Future[SimpleResult] = { 

    val subdomainLanguage = requestHeader.domain.toString.substring(0, 3) match { 
     case "it." => "it" 
     case "es." => "es" 
     case _ => "en" 
    } 
    next(requestHeader.copy(headers = requestHeader.headers.add(HeaderNames.ACCEPT_LANGUAGE -> subdomainLanguage))) 
    } 
} 

object Global extends WithFilters(LangFromSubdomain)