make perf keys translatable; only rapid & classical for now
parent
ad13414fbe
commit
5b006658da
|
@ -20,7 +20,7 @@ final class Challenge(
|
|||
def all = Auth { implicit ctx => me =>
|
||||
XhrOrRedirectHome {
|
||||
api allFor me.id map { all =>
|
||||
Ok(env.challenge.jsonView(all, ctx.lang)) as JSON
|
||||
Ok(env.challenge.jsonView(all)) as JSON
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ final class Challenge(
|
|||
}
|
||||
|
||||
def apiCreate(userId: String) = ScopedBody(_.Challenge.Write, _.Bot.Play) { implicit req => me =>
|
||||
implicit val lang = lila.i18n.I18nLangPicker(req, me.some)
|
||||
implicit val lang = lila.i18n.I18nLangPicker(req, me.lang)
|
||||
env.setup.forms.api.bindFromRequest.fold(
|
||||
jsonFormErrorDefaultLang,
|
||||
config =>
|
||||
|
|
|
@ -471,7 +471,7 @@ abstract private[controllers] class LilaController(val env: Env)
|
|||
}
|
||||
|
||||
private def getAndSaveLang(req: RequestHeader, user: Option[UserModel]): Lang = {
|
||||
val lang = lila.i18n.I18nLangPicker(req, user)
|
||||
val lang = lila.i18n.I18nLangPicker(req, user.flatMap(_.lang))
|
||||
user.filter(_.lang.fold(true)(_ != lang.code)) foreach { env.user.repo.setLang(_, lang) }
|
||||
lang
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ abstract private[controllers] class LilaController(val env: Env)
|
|||
jsonFormError(err)(lila.i18n.defaultLang)
|
||||
|
||||
protected def jsonFormErrorFor(err: Form[_], req: RequestHeader, user: Option[UserModel]) =
|
||||
jsonFormError(err)(lila.i18n.I18nLangPicker(req, user))
|
||||
jsonFormError(err)(lila.i18n.I18nLangPicker(req, user.flatMap(_.lang)))
|
||||
|
||||
protected def pageHit(req: RequestHeader): Unit =
|
||||
if (HTTPRequest isHuman req) lila.mon.http.path(req.path).increment()
|
||||
|
|
|
@ -5,6 +5,7 @@ import controllers.routes
|
|||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.tournament.{ Schedule, Tournament }
|
||||
import lila.user.User
|
||||
import lila.rating.PerfType
|
||||
|
||||
import play.api.libs.json.Json
|
||||
|
||||
|
@ -46,11 +47,12 @@ trait TournamentHelper { self: I18nHelper with DateHelper with UserHelper =>
|
|||
private val replacements = List(
|
||||
"Lichess " -> "",
|
||||
"Marathon" -> icon('\\'),
|
||||
"HyperBullet" -> s"H${icon(lila.rating.PerfType.Bullet.iconChar)}",
|
||||
"SuperBlitz" -> s"S${icon(lila.rating.PerfType.Blitz.iconChar)}"
|
||||
) ::: lila.rating.PerfType.leaderboardable.map { pt =>
|
||||
"HyperBullet" -> s"H${icon(PerfType.Bullet.iconChar)}",
|
||||
"SuperBlitz" -> s"S${icon(PerfType.Blitz.iconChar)}"
|
||||
) ::: PerfType.leaderboardable.filterNot(PerfType.translated.contains).map { pt =>
|
||||
pt.name -> icon(pt.iconChar)
|
||||
}
|
||||
|
||||
def apply(name: String): Frag = raw {
|
||||
replacements.foldLeft(name) {
|
||||
case (n, (from, to)) => n.replace(from, to)
|
||||
|
|
|
@ -46,7 +46,7 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
|
|||
)
|
||||
|
||||
def showPerfRating(perfType: PerfType, perf: Perf)(implicit lang: Lang): Frag =
|
||||
showPerfRating(perf.intRating, perfType.name, perf.nb, perf.provisional, perfType.iconChar)
|
||||
showPerfRating(perf.intRating, perfType.trans, perf.nb, perf.provisional, perfType.iconChar)
|
||||
|
||||
def showPerfRating(u: User, perfType: PerfType)(implicit lang: Lang): Frag =
|
||||
showPerfRating(perfType, u perfs perfType)
|
||||
|
|
|
@ -90,7 +90,7 @@ object activity {
|
|||
iconTag(pt.iconChar),
|
||||
scoreFrag(score),
|
||||
div(
|
||||
trans.activity.playedNbGames.plural(score.size, score.size, pt.name),
|
||||
trans.activity.playedNbGames.plural(score.size, score.size, pt.trans),
|
||||
score.rp.filterNot(_.isEmpty).map(ratingProgFrag)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ object bits {
|
|||
if (c.variant.exotic)
|
||||
views.html.game.bits.variantLink(c.variant, variantName(c.variant))
|
||||
else
|
||||
c.perfType.name,
|
||||
c.perfType.trans,
|
||||
br,
|
||||
span(cls := "clock")(
|
||||
c.daysPerTurn map { days =>
|
||||
|
|
|
@ -101,7 +101,7 @@ object teacherDashboard {
|
|||
a(
|
||||
cls := progress.perfType.key.active(pt.key),
|
||||
href := routes.Clas.progress(c.id.value, pt.key, progress.days)
|
||||
)(pt.name),
|
||||
)(pt.trans),
|
||||
}
|
||||
)
|
||||
),
|
||||
|
@ -122,7 +122,7 @@ object teacherDashboard {
|
|||
thead(
|
||||
tr(
|
||||
th(attr("data-sort-default") := "1")(
|
||||
trans.clas.variantXOverLastY(progress.perfType.name, trans.nbDays.txt(progress.days)),
|
||||
trans.clas.variantXOverLastY(progress.perfType.trans, trans.nbDays.txt(progress.days)),
|
||||
sortNumberTh(trans.rating()),
|
||||
sortNumberTh(trans.clas.progress()),
|
||||
sortNumberTh(if (progress.isPuzzle) trans.puzzles() else trans.games()),
|
||||
|
|
|
@ -159,7 +159,7 @@ object forms {
|
|||
raw(s"""<strong data-icon="${perfType.iconChar}">${me
|
||||
.perfs(perfType.key)
|
||||
.map(_.intRating)
|
||||
.getOrElse("?")}</strong> ${perfType.name}""")
|
||||
.getOrElse("?")}</strong> ${perfType.trans}""")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ object variant {
|
|||
cls := List("text" -> true, "active" -> active.has(pt)),
|
||||
href := routes.Page.variant(pt.key),
|
||||
dataIcon := pt.iconChar
|
||||
)(pt.name)
|
||||
)(pt.trans)
|
||||
}
|
||||
),
|
||||
div(cls := s"page-menu__content box $klass")(body)
|
||||
|
|
|
@ -15,7 +15,7 @@ object ratingDistribution {
|
|||
|
||||
def apply(perfType: PerfType, data: List[Int])(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
title = trans.weeklyPerfTypeRatingDistribution.txt(perfType.name),
|
||||
title = trans.weeklyPerfTypeRatingDistribution.txt(perfType.trans),
|
||||
moreCss = cssTag("user.rating.stats"),
|
||||
wrapClass = "full-screen-force",
|
||||
moreJs = frag(
|
||||
|
@ -36,13 +36,13 @@ object ratingDistribution {
|
|||
trans.weeklyPerfTypeRatingDistribution(
|
||||
views.html.base.bits.mselect(
|
||||
"variant-stats",
|
||||
span(perfType.name),
|
||||
span(perfType.trans),
|
||||
PerfType.leaderboardable map { pt =>
|
||||
a(
|
||||
dataIcon := pt.iconChar,
|
||||
cls := (perfType == pt).option("current"),
|
||||
href := routes.Stat.ratingDistribution(pt.key)
|
||||
)(pt.name)
|
||||
)(pt.trans)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -53,21 +53,21 @@ object ratingDistribution {
|
|||
case (under, sum) =>
|
||||
div(
|
||||
trans
|
||||
.nbPerfTypePlayersThisWeek(raw(s"""<strong>${sum.localize}</strong>"""), perfType.name),
|
||||
.nbPerfTypePlayersThisWeek(strong(sum.localize), perfType.trans),
|
||||
br,
|
||||
trans.yourPerfTypeRatingIsRating(perfType.name, raw(s"""<strong>$rating</strong>""")),
|
||||
trans.yourPerfTypeRatingIsRating(perfType.trans, strong(rating)),
|
||||
br,
|
||||
trans.youAreBetterThanPercentOfPerfTypePlayers(
|
||||
raw(s"""<strong>${(under * 100.0 / sum).round}%</strong>"""),
|
||||
perfType.name
|
||||
strong((under * 100.0 / sum).round),
|
||||
perfType.trans
|
||||
)
|
||||
)
|
||||
}
|
||||
} getOrElse div(
|
||||
trans.nbPerfTypePlayersThisWeek
|
||||
.plural(data.sum, raw(s"""<strong>${data.sum.localize}</strong>"""), perfType.name),
|
||||
.plural(data.sum, strong(data.sum.localize), perfType.trans),
|
||||
br,
|
||||
trans.youDoNotHaveAnEstablishedPerfTypeRating(perfType.name)
|
||||
trans.youDoNotHaveAnEstablishedPerfTypeRating(perfType.trans)
|
||||
)
|
||||
),
|
||||
div(id := "rating_distribution_chart")(spinner)
|
||||
|
|
|
@ -86,7 +86,7 @@ object list {
|
|||
private def userTopPerf(users: List[User.LightPerf], perfType: PerfType)(implicit lang: Lang) =
|
||||
st.section(cls := "user-top")(
|
||||
h2(cls := "text", dataIcon := perfType.iconChar)(
|
||||
a(href := routes.User.topNb(200, perfType.key))(perfType.name)
|
||||
a(href := routes.User.topNb(200, perfType.key))(perfType.trans)
|
||||
),
|
||||
ol(users map { l =>
|
||||
li(
|
||||
|
|
|
@ -24,14 +24,14 @@ object perfStat {
|
|||
ratingChart: Option[String]
|
||||
)(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
title = s"${u.username} ${perfStats.txt(perfType.name)} stats",
|
||||
title = s"${u.username} - ${perfStats.txt(perfType.trans)}",
|
||||
robots = false,
|
||||
moreJs = frag(
|
||||
jsAt("compiled/user.js"),
|
||||
ratingChart.map { rc =>
|
||||
frag(
|
||||
jsTag("chart/ratingHistory.js"),
|
||||
embedJsUnsafe(s"lichess.ratingHistoryChart($rc,'${perfType.name}');")
|
||||
embedJsUnsafe(s"lichess.ratingHistoryChart($rc,'${perfType.trans}');")
|
||||
)
|
||||
}
|
||||
),
|
||||
|
@ -43,7 +43,7 @@ object perfStat {
|
|||
div(cls := "box__top")(
|
||||
h1(
|
||||
a(href := routes.User.show(u.username))(u.username),
|
||||
span(perfStats(perfType.name))
|
||||
span(perfStats(perfType.trans))
|
||||
),
|
||||
div(cls := "box__top__actions")(
|
||||
u.perfs(perfType).nb > 0 option a(
|
||||
|
@ -86,7 +86,7 @@ object perfStat {
|
|||
span(cls := "details")(
|
||||
trans.youAreBetterThanPercentOfPerfTypePlayers(
|
||||
a(href := routes.Stat.ratingDistribution(perfType.key))(strong(percentile, "%")),
|
||||
a(href := routes.Stat.ratingDistribution(perfType.key))(perfType.name)
|
||||
a(href := routes.Stat.ratingDistribution(perfType.key))(perfType.trans)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ object side {
|
|||
def showNonEmptyPerf(perf: lila.rating.Perf, perfType: PerfType) =
|
||||
perf.nonEmpty option showPerf(perf, perfType)
|
||||
|
||||
def showPerf(perf: lila.rating.Perf, perfType: PerfType, name: Option[String] = none) = {
|
||||
def showPerf(perf: lila.rating.Perf, perfType: PerfType) = {
|
||||
val isGame = lila.rating.PerfType.isGame(perfType)
|
||||
a(
|
||||
dataIcon := perfType.iconChar,
|
||||
|
@ -31,7 +31,7 @@ object side {
|
|||
),
|
||||
href := isGame option routes.User.perfStat(u.username, perfType.key).url,
|
||||
span(
|
||||
h3(name.getOrElse(perfType.name).toUpperCase),
|
||||
h3(perfType.trans),
|
||||
st.rating(
|
||||
strong(
|
||||
perf.glicko.intRating,
|
||||
|
|
|
@ -12,16 +12,16 @@ object top {
|
|||
|
||||
def apply(perfType: lila.rating.PerfType, users: List[User.LightPerf])(implicit ctx: Context) = {
|
||||
|
||||
val title = s"${perfType.name} top 200"
|
||||
val title = s"${perfType.trans} top 200"
|
||||
|
||||
views.html.base.layout(
|
||||
title = title,
|
||||
moreCss = cssTag("slist"),
|
||||
openGraph = lila.app.ui
|
||||
.OpenGraph(
|
||||
title = s"Leaderboard of ${perfType.name}",
|
||||
title = s"Leaderboard of ${perfType.trans}",
|
||||
url = s"$netBaseUrl${routes.User.topNb(200, perfType.key).url}",
|
||||
description = s"The 200 best chess players in ${perfType.name}, sorted by rating"
|
||||
description = s"The 200 best chess players in ${perfType.trans}, sorted by rating"
|
||||
)
|
||||
.some
|
||||
)(
|
||||
|
|
|
@ -41,7 +41,7 @@ object chart {
|
|||
data.perfResults.map {
|
||||
case (pt, res) => {
|
||||
tr(
|
||||
th(iconTag(pt.iconChar, pt.name)),
|
||||
th(iconTag(pt.iconChar, pt.trans)),
|
||||
td(res.nb.localize),
|
||||
td(res.points.median.map(_.toInt)),
|
||||
td(res.points.sum.localize),
|
||||
|
|
|
@ -69,7 +69,7 @@ lazy val api = module("api",
|
|||
) aggregate (moduleRefs: _*)
|
||||
|
||||
lazy val i18n = module("i18n",
|
||||
Seq(common, db, user, hub),
|
||||
Seq(common, db, hub),
|
||||
Seq(scalatags)
|
||||
).settings(
|
||||
sourceGenerators in Compile += Def.task {
|
||||
|
@ -129,7 +129,7 @@ lazy val common = module("common",
|
|||
)
|
||||
|
||||
lazy val rating = module("rating",
|
||||
Seq(common, db, memo),
|
||||
Seq(common, db, memo, i18n),
|
||||
reactivemongo.bundle
|
||||
)
|
||||
|
||||
|
@ -174,7 +174,7 @@ lazy val timeline = module("timeline",
|
|||
)
|
||||
|
||||
lazy val event = module("event",
|
||||
Seq(common, db, memo, i18n),
|
||||
Seq(common, db, memo, i18n, user),
|
||||
Seq(scalatags) ++ reactivemongo.bundle
|
||||
)
|
||||
|
||||
|
|
|
@ -97,6 +97,6 @@ final class EventStream(
|
|||
)
|
||||
private def toJson(c: Challenge) = Json.obj(
|
||||
"type" -> "challenge",
|
||||
"challenge" -> challengeJsonView(none)(c)
|
||||
"challenge" -> challengeJsonView(none)(c)(lila.i18n.defaultLang)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import play.api.libs.json.{ JsArray, JsObject, Json }
|
|||
|
||||
import lila.game.Pov
|
||||
import lila.lobby.SeekApi
|
||||
import lila.pool.JsonView.poolConfigJsonWriter
|
||||
import lila.pool.PoolConfig.poolConfigJsonWriter
|
||||
import lila.setup.FilterConfig
|
||||
import lila.user.UserContext
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ final class ChallengeApi(
|
|||
_ flatMap lila.i18n.I18nLangPicker.byStr getOrElse lila.i18n.defaultLang
|
||||
}
|
||||
} yield Bus.publish(
|
||||
SendTo(userId, lila.socket.Socket.makeMessage("challenges", jsonView(all, lang))),
|
||||
SendTo(userId, lila.socket.Socket.makeMessage("challenges", jsonView(all)(lang))),
|
||||
"socketUsers"
|
||||
)
|
||||
|
||||
|
|
|
@ -30,18 +30,20 @@ final class JsonView(
|
|||
.add("lag" -> UserLagCache.getLagRating(r.id))
|
||||
}
|
||||
|
||||
def apply(a: AllChallenges, lang: Lang): JsObject = Json.obj(
|
||||
def apply(a: AllChallenges)(implicit lang: Lang): JsObject = Json.obj(
|
||||
"in" -> a.in.map(apply(Direction.In.some)),
|
||||
"out" -> a.out.map(apply(Direction.Out.some)),
|
||||
"i18n" -> lila.i18n.JsDump.keysToObject(i18nKeys, lang)
|
||||
)
|
||||
|
||||
def show(challenge: Challenge, socketVersion: SocketVersion, direction: Option[Direction]) = Json.obj(
|
||||
def show(challenge: Challenge, socketVersion: SocketVersion, direction: Option[Direction])(
|
||||
implicit lang: Lang
|
||||
) = Json.obj(
|
||||
"challenge" -> apply(direction)(challenge),
|
||||
"socketVersion" -> socketVersion
|
||||
)
|
||||
|
||||
def apply(direction: Option[Direction])(c: Challenge): JsObject =
|
||||
def apply(direction: Option[Direction])(c: Challenge)(implicit lang: Lang): JsObject =
|
||||
Json
|
||||
.obj(
|
||||
"id" -> c.id,
|
||||
|
@ -69,7 +71,7 @@ final class JsonView(
|
|||
"color" -> c.colorChoice.toString.toLowerCase,
|
||||
"perf" -> Json.obj(
|
||||
"icon" -> iconChar(c).toString,
|
||||
"name" -> c.perfType.name
|
||||
"name" -> c.perfType.trans
|
||||
)
|
||||
)
|
||||
.add("direction" -> direction.map(_.name))
|
||||
|
|
|
@ -691,6 +691,8 @@ val `agreementAccount` = new I18nKey("agreementAccount")
|
|||
val `agreementPolicy` = new I18nKey("agreementPolicy")
|
||||
val `searchOrStartNewDiscussion` = new I18nKey("searchOrStartNewDiscussion")
|
||||
val `edit` = new I18nKey("edit")
|
||||
val `rapid` = new I18nKey("rapid")
|
||||
val `classical` = new I18nKey("classical")
|
||||
val `opponentLeftCounter` = new I18nKey("opponentLeftCounter")
|
||||
val `mateInXHalfMoves` = new I18nKey("mateInXHalfMoves")
|
||||
val `nextCaptureOrPawnMoveInXHalfMoves` = new I18nKey("nextCaptureOrPawnMoveInXHalfMoves")
|
||||
|
|
|
@ -3,13 +3,10 @@ package lila.i18n
|
|||
import play.api.mvc.RequestHeader
|
||||
import play.api.i18n.Lang
|
||||
|
||||
import lila.user.User
|
||||
|
||||
object I18nLangPicker {
|
||||
|
||||
def apply(req: RequestHeader, user: Option[User]): Lang =
|
||||
user
|
||||
.flatMap(_.lang)
|
||||
def apply(req: RequestHeader, userLang: Option[String]): Lang =
|
||||
userLang
|
||||
.orElse(req.session get "lang")
|
||||
.flatMap(Lang.get)
|
||||
.flatMap(findCloser)
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package lila.pool
|
||||
|
||||
import play.api.libs.json._
|
||||
|
||||
object JsonView {
|
||||
|
||||
implicit val poolConfigJsonWriter = OWrites[PoolConfig] { p =>
|
||||
Json.obj(
|
||||
"id" -> p.id.value,
|
||||
"lim" -> p.clock.limitInMinutes,
|
||||
"inc" -> p.clock.incrementSeconds,
|
||||
"perf" -> p.perfType.name
|
||||
)
|
||||
}
|
||||
}
|
|
@ -22,4 +22,14 @@ object PoolConfig {
|
|||
case class Wave(every: FiniteDuration, players: NbPlayers)
|
||||
|
||||
def clockToId(clock: chess.Clock.Config) = Id(clock.show)
|
||||
|
||||
import play.api.libs.json._
|
||||
implicit val poolConfigJsonWriter = OWrites[PoolConfig] { p =>
|
||||
Json.obj(
|
||||
"id" -> p.id.value,
|
||||
"lim" -> p.clock.limitInMinutes,
|
||||
"inc" -> p.clock.incrementSeconds,
|
||||
"perf" -> p.perfType.name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package lila.rating
|
||||
|
||||
import chess.Centis
|
||||
|
||||
import chess.Speed
|
||||
import play.api.i18n.Lang
|
||||
|
||||
sealed abstract class PerfType(
|
||||
val id: Perf.ID,
|
||||
|
@ -15,6 +15,8 @@ sealed abstract class PerfType(
|
|||
def shortName = name
|
||||
|
||||
def iconString = iconChar.toString
|
||||
|
||||
def trans(implicit lang: Lang): String = PerfType.trans(this)
|
||||
}
|
||||
|
||||
object PerfType {
|
||||
|
@ -283,4 +285,14 @@ object PerfType {
|
|||
|
||||
def iconByVariant(variant: chess.variant.Variant): Char =
|
||||
byVariant(variant).fold('C')(_.iconChar)
|
||||
|
||||
import lila.i18n.I18nKeys
|
||||
def trans(pt: PerfType)(implicit lang: Lang): String = pt match {
|
||||
case PerfType.Rapid => I18nKeys.rapid.txt()
|
||||
case PerfType.Classical => I18nKeys.classical.txt()
|
||||
case PerfType.Puzzle => I18nKeys.puzzles.txt()
|
||||
case pt => pt.name
|
||||
}
|
||||
|
||||
val translated: Set[PerfType] = Set(PerfType.Rapid, PerfType.Classical, PerfType.Puzzle)
|
||||
}
|
||||
|
|
|
@ -840,4 +840,6 @@ computer analysis, game chat and shareable URL.</string>
|
|||
<string name="agreementPolicy">I agree that I will follow all Lichess policies.</string>
|
||||
<string name="searchOrStartNewDiscussion">Search or start new conversation</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="rapid">Rapid</string>
|
||||
<string name="classical">Classical</string>
|
||||
</resources>
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
h3 {
|
||||
@extend %roboto;
|
||||
font-size: 1.1em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .05em;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
|
|
Loading…
Reference in New Issue