replace play.api.i18n.Lang with lila.common.Lang

as to make sure their default implicit doesn't sneak
where it shouldn't.
Using a default lang is now made explicit by
lila.i18n.defaultLang
fullDuct^2
Thibault Duplessis 2018-12-05 17:42:39 +07:00
parent ce487f5ce0
commit 4a2ee05e02
39 changed files with 100 additions and 77 deletions

View File

@ -34,7 +34,7 @@ object Bot extends LilaController {
}
case Array("game", id, "chat") => WithBot(me) {
Env.bot.form.chat.bindFromRequest.fold(
jsonFormError,
jsonFormErrorDefaultLang,
res => WithMyBotGame(id, me) { pov =>
Env.bot.player.chat(pov.gameId, me, res) inject jsonOkResult
}

View File

@ -11,7 +11,7 @@ import scalatags.Text.{ TypedTag, Frag }
import lila.api.{ PageData, Context, HeaderContext, BodyContext }
import lila.app._
import lila.common.{ LilaCookie, HTTPRequest, ApiVersion, Nonce }
import lila.common.{ LilaCookie, HTTPRequest, ApiVersion, Nonce, Lang }
import lila.notify.Notification.Notifies
import lila.oauth.{ OAuthScope, OAuthServer }
import lila.security.{ Permission, Granter, FingerprintedUser }
@ -476,7 +476,7 @@ private[controllers] trait LilaController
) andThen (__ \ "").json.prune
}
protected def errorsAsJson(form: Form[_])(implicit lang: play.api.i18n.Lang): JsObject = {
protected def errorsAsJson(form: Form[_])(implicit lang: Lang): JsObject = {
val json = JsObject(
form.errors.groupBy(_.key).mapValues { errors =>
JsArray {
@ -489,9 +489,12 @@ private[controllers] trait LilaController
json validate jsonGlobalErrorRenamer getOrElse json
}
protected def jsonFormError(err: Form[_])(implicit lang: play.api.i18n.Lang) =
protected def jsonFormError(err: Form[_])(implicit lang: Lang) =
fuccess(BadRequest(ridiculousBackwardCompatibleJsonError(errorsAsJson(err))))
protected def jsonFormErrorDefaultLang(err: Form[_]) =
jsonFormError(err)(lila.i18n.defaultLang)
protected def pageHit(implicit ctx: lila.api.Context) =
if (HTTPRequest isHuman ctx.req) lila.mon.http.request.path(ctx.req.path)()

View File

@ -247,7 +247,7 @@ object Tournament extends LilaController {
private def doApiCreate(me: lila.user.User)(implicit req: Request[_]): Fu[Result] =
env.forms(me).bindFromRequest.fold(
jsonFormError,
jsonFormErrorDefaultLang,
setup => teamsIBelongTo(me) flatMap { teams =>
env.api.createTournament(setup, me, teams, getUserTeamIds) flatMap { tour =>
Env.tournament.jsonView(tour, none, none, getUserTeamIds, none, none, partial = false, lila.i18n.defaultLang)

View File

@ -325,7 +325,7 @@ object User extends LilaController {
def apiWriteNote(username: String) = ScopedBody() { implicit req => me =>
doWriteNote(username, me)(
err = err => _ => jsonFormError(err),
err = err => _ => jsonFormErrorDefaultLang(err),
suc = jsonOkResult
)
}

View File

@ -31,21 +31,21 @@ trait DateHelper { self: I18nHelper =>
private def dateTimeFormatter(ctx: Context): DateTimeFormatter =
dateTimeFormatters.getOrElseUpdate(
lang(ctx).code,
DateTimeFormat forStyle dateTimeStyle withLocale lang(ctx).toLocale
ctx.lang.code,
DateTimeFormat forStyle dateTimeStyle withLocale ctx.lang.toLocale
)
private def dateFormatter(ctx: Context): DateTimeFormatter =
dateFormatters.getOrElseUpdate(
lang(ctx).code,
DateTimeFormat forStyle dateStyle withLocale lang(ctx).toLocale
ctx.lang.code,
DateTimeFormat forStyle dateStyle withLocale ctx.lang.toLocale
)
private def periodFormatter(ctx: Context): PeriodFormatter =
periodFormatters.getOrElseUpdate(
lang(ctx).code, {
ctx.lang.code, {
Locale setDefault Locale.ENGLISH
PeriodFormat wordBased lang(ctx).toLocale
PeriodFormat wordBased ctx.lang.toLocale
}
)

View File

@ -1,16 +1,16 @@
package lila.app
package templating
import play.api.i18n.Lang
import play.api.libs.json.JsObject
import play.twirl.api.Html
import lila.common.Lang
import lila.i18n.{ LangList, I18nKey, Translator, JsQuantity, I18nDb, JsDump, TimeagoLocales }
import lila.user.UserContext
trait I18nHelper {
implicit def lang(implicit ctx: UserContext) = ctx.lang
implicit def ctxLang(implicit ctx: UserContext): Lang = ctx.lang
def transKey(key: String, db: I18nDb.Ref, args: Seq[Any] = Nil)(implicit lang: Lang): Html =
Translator.html.literal(key, db, args, lang)

View File

@ -13,11 +13,11 @@ trait NumberHelper { self: I18nHelper =>
private def formatter(implicit ctx: UserContext): NumberFormat =
formatters.getOrElseUpdate(
lang(ctx).language,
NumberFormat getInstance new Locale(lang(ctx).language)
ctx.lang.language,
NumberFormat getInstance new Locale(ctx.lang.language)
)
def showMillis(millis: Int)(implicit ctx: UserContext) = formatter format ((millis / 100).toDouble / 10)
def showMillis(millis: Int)(implicit ctx: UserContext) = formatter.format((millis / 100).toDouble / 10)
implicit def richInt(number: Int) = new {
def localize(implicit ctx: UserContext): String = formatter format number

View File

@ -53,8 +53,6 @@ trait ScalatagsTemplate extends Styles
with ScalatagsPrefix {
val trans = lila.i18n.I18nKeys
implicit def lang(implicit ctx: lila.user.UserContext) = ctx.lang
}
object ScalatagsTemplate extends ScalatagsTemplate

View File

@ -3,7 +3,7 @@
@title = @{ s"${playerText(pov.game.whitePlayer)} vs ${playerText(pov.game.blackPlayer)} in ${pov.gameId} : ${pov.game.opening.fold(trans.analysis.txt())(_.opening.ecoName)}" }
<!doctype html>
<html lang="@lang.language">
<html lang="@ctx.lang.language">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="@defaultCsp">

View File

@ -29,7 +29,7 @@ object bits {
"duration" -> ctx.pref.animationFactor * animationDuration.toMillis
),
"is3d" -> ctx.pref.is3d,
"i18n" -> i18nJsObject(translations)
"i18n" -> i18nJsObject(translations)(ctxLang(ctx))
)
def domPreload(pov: Option[lila.game.Pov])(implicit ctx: Context) = {

View File

@ -1,7 +1,7 @@
@(daily: lila.puzzle.DailyPuzzle)(implicit ctx: Context)
<!doctype html>
<html lang="@lang.language">
<html lang="@ctx.lang.language">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="@defaultCsp">

View File

@ -1,9 +1,8 @@
package lila.api
import play.api.mvc.RequestHeader
import play.api.i18n.Lang
import lila.common.{ HTTPRequest, Nonce }
import lila.common.{ HTTPRequest, Nonce, Lang }
import lila.pref.Pref
import lila.relation.actorApi.OnlineFriends
import lila.user.{ UserContext, HeaderUserContext, BodyUserContext }

View File

@ -1,11 +1,11 @@
package lila.challenge
import play.api.i18n.Lang
import play.api.libs.json._
import lila.common.Lang
import lila.i18n.{ I18nKeys => trans }
import lila.socket.UserLagCache
import lila.socket.Socket.SocketVersion
import lila.socket.UserLagCache
final class JsonView(
getLightUser: lila.common.LightUser.GetterSync,

View File

@ -1,6 +1,5 @@
package lila.common
import play.api.i18n.Lang
import play.api.libs.json._
import play.api.libs.ws.WS
import play.api.Play.current
@ -18,8 +17,10 @@ final class DetectLanguage(url: String, key: String) {
private val messageMaxLength = 2000
private val defaultLang = Lang("en")
def apply(message: String): Fu[Option[Lang]] =
if (key.isEmpty) fuccess(Lang("en").some)
if (key.isEmpty) fuccess(defaultLang.some)
else WS.url(url).post(Map(
"key" -> Seq(key),
"q" -> Seq(message take messageMaxLength)
@ -35,7 +36,7 @@ final class DetectLanguage(url: String, key: String) {
} recover {
case e: Exception =>
lila.log("DetectLanguage").warn(e.getMessage, e)
Lang("en").some
defaultLang.some
}
}

View File

@ -0,0 +1,24 @@
package lila.common
import play.api.i18n.{ Lang => PlayLang }
/* Play has an implicit Lang that is made available every-fucking-where
* by the fact that it comes from its companion object.
* Therefore we can't trust any implicit Lang value.
* This type works around that */
case class Lang(value: PlayLang) extends AnyVal {
def language = value.language
def code = value.code
def toLocale = value.toLocale
def is(other: Lang) = other.code == code
}
object Lang {
def apply(language: String): Lang = Lang(PlayLang(language))
def apply(language: String, country: String): Lang = Lang(PlayLang(language, country))
def get(code: String): Option[Lang] = PlayLang get code map apply
}

View File

@ -2,7 +2,6 @@ package lila.common
import com.typesafe.config.Config
import org.joda.time.{ DateTime, Period }
import play.api.i18n.Lang
import play.api.{ Play, Application, Mode }
import scala.collection.JavaConversions._
@ -30,8 +29,6 @@ object PlayApp {
play.api.libs.concurrent.Akka.system
}
lazy val langs = loadConfig.getStringList("play.i18n.langs").map(Lang.apply)(scala.collection.breakOut)
private def enableScheduler = !(loadConfig getBoolean "app.scheduler.disabled")
lazy val scheduler = new Scheduler(

View File

@ -1,8 +1,8 @@
package lila.event
import reactivemongo.bson._
import play.api.i18n.Lang
import lila.common.Lang
import lila.db.dsl._
private[event] object BsonHandlers {

View File

@ -1,7 +1,8 @@
package lila.event
import org.joda.time.DateTime
import play.api.i18n.Lang
import lila.common.Lang
case class Event(
_id: String,

View File

@ -4,9 +4,9 @@ import org.joda.time.DateTime
import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints._
import play.api.i18n.Lang
import lila.i18n.LangList
import lila.common.Lang
object EventForm {

View File

@ -1,5 +1,7 @@
package lila.i18n
import lila.common.Lang
object I18nDb {
sealed trait Ref
@ -26,5 +28,5 @@ object I18nDb {
case Coordinates => coordinates
}
val langs = site.keySet
val langs: Set[Lang] = site.keys.map(Lang.apply)(scala.collection.breakOut)
}

View File

@ -1,8 +1,9 @@
package lila.i18n
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.user.UserContext
import lila.common.Lang
sealed trait I18nKey {

View File

@ -1,8 +1,8 @@
package lila.i18n
import play.api.i18n.Lang
import play.api.mvc.RequestHeader
import lila.common.Lang
import lila.user.User
object I18nLangPicker {
@ -18,12 +18,12 @@ object I18nLangPicker {
def bestFromRequestHeaders(req: RequestHeader): Option[Lang] =
req.acceptLanguages.foldLeft(none[Lang]) {
case (None, lang) => findCloser(lang)
case (None, lang) => findCloser(Lang(lang))
case (found, _) => found
}
def allFromRequestHeaders(req: RequestHeader): List[Lang] =
req.acceptLanguages.flatMap(findCloser).distinct.toList
req.acceptLanguages.flatMap(l => findCloser(Lang(l))).distinct.toList
def byStr(str: String): Option[Lang] =
Lang get str flatMap findCloser

View File

@ -1,6 +1,6 @@
package lila.i18n
import play.api.i18n.Lang
import lila.common.Lang
private sealed trait I18nQuantity

View File

@ -3,10 +3,10 @@ package lila.i18n
import java.io._
import scala.concurrent.Future
import scala.collection.JavaConversions._
import play.api.i18n.Lang
import play.api.libs.json.{ JsString, JsObject }
import lila.common.Lang
private[i18n] final class JsDump(path: String) {
def apply: Funit = Future {
@ -30,7 +30,7 @@ private[i18n] final class JsDump(path: String) {
)
private def writeFullJson = I18nDb.langs foreach { lang =>
val code = dumpFromKey(asScalaSet(I18nDb.site(defaultLang).keySet).toSet, lang)
val code = dumpFromKey(asScalaSet(I18nDb.site(defaultLang.value).keySet).toSet, lang)
val file = new File("%s/%s.all.json".format(pathFile.getCanonicalPath, lang.code))
writeFile(new File("%s/%s.all.json".format(pathFile.getCanonicalPath, lang.code)), code)
}
@ -74,9 +74,9 @@ object JsDump {
val emptyMessages: MessageMap = new java.util.HashMap()
def dbToObject(ref: I18nDb.Ref, lang: Lang): JsObject =
I18nDb(ref).get(defaultLang) ?? { defaultMsgs =>
I18nDb(ref).get(defaultLang.value) ?? { defaultMsgs =>
JsObject {
val msgs = I18nDb(ref).get(lang) | emptyMessages
val msgs = I18nDb(ref).get(lang.value) | emptyMessages
defaultMsgs.flatMap {
case (k, v) => translatedJs(k, msgs.getOrDefault(k, v), lang)
}

View File

@ -1,6 +1,6 @@
package lila.i18n
import play.api.i18n.Lang
import lila.common.Lang
object JsQuantity {
private def body(lang: Lang): String = lang.language match {

View File

@ -1,6 +1,6 @@
package lila.i18n
import play.api.i18n.Lang
import lila.common.Lang
object LangList {
@ -8,11 +8,11 @@ object LangList {
def nameByStr(str: String): String = I18nLangPicker.byStr(str).fold(str)(name)
lazy val choices = all.toList.map {
case (Lang(language, _), name) => language -> name
lazy val choices: List[(String, String)] = all.toList.map {
case (l, name) => l.language -> name
}.sortBy(_._1)
val all = Map(
private[i18n] val all = Map(
Lang("en", "GB") -> "English",
Lang("af", "ZA") -> "Afrikaans",
Lang("ar", "SA") -> "العربية",

View File

@ -1,8 +1,8 @@
package lila.i18n
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.common.Lang
import lila.common.String.html.escapeHtml
object Translator {
@ -69,6 +69,6 @@ object Translator {
}
private[i18n] def findTranslation(key: MessageKey, db: I18nDb.Ref, lang: Lang): Option[Translation] =
I18nDb(db).get(lang).flatMap(t => Option(t get key)) orElse
I18nDb(db).get(defaultLang).flatMap(t => Option(t get key))
I18nDb(db).get(lang.value).flatMap(t => Option(t get key)) orElse
I18nDb(db).get(defaultLang.value).flatMap(t => Option(t get key))
}

View File

@ -1,6 +1,6 @@
package lila
import play.api.i18n.Lang
import lila.common.Lang
package object i18n extends PackageObject {
@ -8,11 +8,11 @@ package object i18n extends PackageObject {
type MessageKey = String
/* Implemented by mutable.AnyRefMap.
* Of course we don't need/use the mutability;
* Of course we don't need or use the mutability;
* it's just that AnyRefMap is the fastest scala hashmap implementation
*/
private[i18n] type MessageMap = java.util.Map[MessageKey, Translation]
private[i18n] type Messages = Map[Lang, MessageMap]
private[i18n] type Messages = Map[play.api.i18n.Lang, MessageMap]
private[i18n] def logger = lila.log("i18n")

View File

@ -2,7 +2,8 @@ package lila.qa
import play.api.data._
import play.api.data.Forms._
import play.api.i18n.Lang
import lila.common.Lang
private[qa] final class DataForm(
val captcher: akka.actor.ActorSelection,
@ -65,8 +66,10 @@ private[qa] final class DataForm(
private val languageMessage = "I didn't understand that. Is it written in English?"
private val validLang = Lang("en")
private def validateLanguage(str: String) =
detectLanguage(str).awaitSeconds(5).??(_ == Lang("en"))
detectLanguage(str).awaitSeconds(5).??(validLang.is)
}
private[qa] case class QuestionData(

View File

@ -1,9 +1,8 @@
package lila.security
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.common.EmailAddress
import lila.common.{ Lang, EmailAddress }
import lila.common.String.html.nl2brUnsafe
import lila.user.{ User, UserRepo }

View File

@ -1,9 +1,8 @@
package lila.security
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.common.EmailAddress
import lila.common.{ Lang, EmailAddress }
import lila.user.{ User, UserRepo }
import lila.i18n.I18nKeys.{ emails => trans }

View File

@ -1,9 +1,8 @@
package lila.security
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.common.EmailAddress
import lila.common.{ Lang, EmailAddress }
import lila.i18n.I18nKeys.{ emails => trans }
import lila.user.{ User, UserRepo }

View File

@ -188,7 +188,8 @@ final class Env(
def cli = new Cli
system.lilaBus.subscribeFun('fishnet) {
case lila.hub.actorApi.fishnet.NewKey(userId, key) => automaticEmail.onFishnetKey(userId, key)
case lila.hub.actorApi.fishnet.NewKey(userId, key) =>
automaticEmail.onFishnetKey(userId, key)(lila.i18n.defaultLang)
}
private[security] lazy val storeColl = db(CollectionSecurity)

View File

@ -3,12 +3,11 @@ package lila.security
import scala.concurrent.duration._
import akka.actor.ActorSystem
import play.api.i18n.Lang
import play.api.libs.ws.{ WS, WSAuthScheme }
import play.api.Play.current
import play.twirl.api.Html
import lila.common.EmailAddress
import lila.common.{ Lang, EmailAddress }
import lila.common.String.html.escapeHtml
import lila.i18n.I18nKeys.{ emails => trans }

View File

@ -1,9 +1,8 @@
package lila.security
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.common.EmailAddress
import lila.common.{ Lang, EmailAddress }
import lila.user.{ User, UserRepo }
import lila.i18n.I18nKeys.{ emails => trans }

View File

@ -1,9 +1,8 @@
package lila.security
import play.api.i18n.Lang
import play.twirl.api.Html
import lila.common.EmailAddress
import lila.common.{ Lang, EmailAddress }
import lila.user.User
import lila.i18n.I18nKeys.{ emails => trans }

View File

@ -1,7 +1,6 @@
package lila.tournament
import play.api.i18n.Lang
import lila.common.Lang
import lila.hub.tournamentTeam._
import lila.i18n.I18nKeys
import lila.rating.BSONHandlers.perfTypeKeyHandler

View File

@ -2,11 +2,10 @@ package lila.tournament
import org.joda.time.DateTime
import org.joda.time.format.ISODateTimeFormat
import play.api.i18n.Lang
import play.api.libs.json._
import scala.concurrent.duration._
import lila.common.LightUser
import lila.common.{ Lang, LightUser }
import lila.game.{ GameRepo, LightPov, Game }
import lila.hub.tournamentTeam._
import lila.quote.Quote.quoteWriter

View File

@ -1,8 +1,9 @@
package lila.user
import play.api.i18n.Lang
import play.api.mvc.{ Request, RequestHeader }
import lila.common.Lang
sealed trait UserContext {
val req: RequestHeader