diff --git a/app/views/base/layout.scala b/app/views/base/layout.scala
index 09d9ae3df9..01d30cec98 100644
--- a/app/views/base/layout.scala
+++ b/app/views/base/layout.scala
@@ -91,7 +91,7 @@ object layout {
private def allNotifications(implicit ctx: Context) =
spaceless(s"""
-
diff --git a/app/views/challenge/mine.scala b/app/views/challenge/mine.scala
index ac383f8a9c..24c9635e0c 100644
--- a/app/views/challenge/mine.scala
+++ b/app/views/challenge/mine.scala
@@ -29,7 +29,7 @@ object mine {
c.status match {
case Status.Created | Status.Offline =>
div(id := "ping-challenge")(
- h1(if (c.isOpen) "Open challenge" else trans.challengeToPlay.txt()),
+ h1(if (c.isOpen) "Open challenge" else trans.challenge.challengeToPlay.txt()),
bits.details(c),
c.destUserId.map { destId =>
div(cls := "waiting")(
@@ -93,13 +93,13 @@ object mine {
)
case Status.Declined =>
div(cls := "follow-up")(
- h1(trans.challengeDeclined()),
+ h1(trans.challenge.challengeDeclined()),
bits.details(c),
a(cls := "button button-fat", href := routes.Lobby.home())(trans.newOpponent())
)
case Status.Accepted =>
div(cls := "follow-up")(
- h1(trans.challengeAccepted()),
+ h1(trans.challenge.challengeAccepted()),
bits.details(c),
a(id := "challenge-redirect", href := routes.Round.watcher(c.id, "white"), cls := "button-fat")(
trans.joinTheGame()
@@ -107,7 +107,7 @@ object mine {
)
case Status.Canceled =>
div(cls := "follow-up")(
- h1(trans.challengeCanceled()),
+ h1(trans.challenge.challengeCanceled()),
bits.details(c),
a(cls := "button button-fat", href := routes.Lobby.home())(trans.newOpponent())
)
diff --git a/app/views/challenge/theirs.scala b/app/views/challenge/theirs.scala
index ad5ced79d2..bf121871cb 100644
--- a/app/views/challenge/theirs.scala
+++ b/app/views/challenge/theirs.scala
@@ -73,13 +73,13 @@ object theirs {
)
case Status.Declined =>
div(cls := "follow-up")(
- h1(trans.challengeDeclined()),
+ h1(trans.challenge.challengeDeclined()),
bits.details(c),
a(cls := "button button-fat", href := routes.Lobby.home())(trans.newOpponent())
)
case Status.Accepted =>
div(cls := "follow-up")(
- h1(trans.challengeAccepted()),
+ h1(trans.challenge.challengeAccepted()),
bits.details(c),
a(
id := "challenge-redirect",
@@ -91,7 +91,7 @@ object theirs {
)
case Status.Canceled =>
div(cls := "follow-up")(
- h1(trans.challengeCanceled()),
+ h1(trans.challenge.challengeCanceled()),
bits.details(c),
a(cls := "button button-fat", href := routes.Lobby.home())(trans.newOpponent())
)
diff --git a/app/views/clas/studentDashboard.scala b/app/views/clas/studentDashboard.scala
index 6fabc8591c..bee9ec2e2f 100644
--- a/app/views/clas/studentDashboard.scala
+++ b/app/views/clas/studentDashboard.scala
@@ -107,7 +107,7 @@ object studentDashboard {
a(
dataIcon := "U",
cls := List("button button-empty text" -> true, "disabled" -> !online),
- title := trans.challengeToPlay.txt(),
+ title := trans.challenge.challengeToPlay.txt(),
href := online option s"${routes.Lobby.home()}?user=${user.username}#friend"
)(trans.play())
)
diff --git a/app/views/msg.scala b/app/views/msg.scala
index 6c9ddaa1a0..b2f9b7d8f5 100644
--- a/app/views/msg.scala
+++ b/app/views/msg.scala
@@ -32,7 +32,7 @@ object msg {
private val i18nKeys = List(
trans.inbox,
- trans.challengeToPlay,
+ trans.challenge.challengeToPlay,
trans.block,
trans.unblock,
trans.blocked,
diff --git a/app/views/relation/actions.scala b/app/views/relation/actions.scala
index 67cef408cd..8adef373f6 100644
--- a/app/views/relation/actions.scala
+++ b/app/views/relation/actions.scala
@@ -22,7 +22,7 @@ object actions {
(myId != userId) ?? frag(
!blocked option frag(
a(
- titleOrText(trans.challengeToPlay.txt()),
+ titleOrText(trans.challenge.challengeToPlay.txt()),
href := s"${routes.Lobby.home()}?user=$userId#friend",
cls := "btn-rack__btn",
dataIcon := "U"
diff --git a/app/views/setup/forms.scala b/app/views/setup/forms.scala
index 80f8adbad8..cc7c2e9486 100644
--- a/app/views/setup/forms.scala
+++ b/app/views/setup/forms.scala
@@ -94,7 +94,7 @@ object forms {
)(implicit ctx: Context) =
layout(
"friend",
- (if (user.isDefined) trans.challengeToPlay else trans.playWithAFriend)(),
+ (if (user.isDefined) trans.challenge.challengeToPlay else trans.playWithAFriend)(),
routes.Setup.friend(user map (_.id)),
error.map(e => raw(e.replace("{{user}}", userIdLink(user.map(_.id)).toString)))
)(
diff --git a/app/views/site/message.scala b/app/views/site/message.scala
index 0f42210cb5..e29c711989 100644
--- a/app/views/site/message.scala
+++ b/app/views/site/message.scala
@@ -73,7 +73,7 @@ object message {
def challengeDenied(msg: String)(implicit ctx: Context) =
apply(
- title = trans.challengeToPlay.txt(),
+ title = trans.challenge.challengeToPlay.txt(),
back = routes.Lobby.home().url.some
)(msg)
diff --git a/app/views/user/bots.scala b/app/views/user/bots.scala
index 2752fb500a..bf8ba28e52 100644
--- a/app/views/user/bots.scala
+++ b/app/views/user/bots.scala
@@ -80,7 +80,7 @@ object bots {
a(
dataIcon := "U",
cls := List("button button-empty text" -> true),
- st.title := trans.challengeToPlay.txt(),
+ st.title := trans.challenge.challengeToPlay.txt(),
href := s"${routes.Lobby.home()}?user=${u.username}#friend"
)(trans.play())
)
diff --git a/app/views/user/mini.scala b/app/views/user/mini.scala
index 63d50e90af..a737761b32 100644
--- a/app/views/user/mini.scala
+++ b/app/views/user/mini.scala
@@ -60,7 +60,7 @@ object mini {
a(
dataIcon := "U",
cls := "btn-rack__btn",
- title := trans.challengeToPlay.txt(),
+ title := trans.challenge.challengeToPlay.txt(),
href := s"${routes.Lobby.home()}?user=${u.username}#friend"
)
),
diff --git a/bin/trans-dump.js b/bin/trans-dump.js
index e53c65381b..23b5107151 100644
--- a/bin/trans-dump.js
+++ b/bin/trans-dump.js
@@ -2,7 +2,7 @@ const fs = require('fs').promises;
const parseString = require('xml2js').parseString;
const baseDir = 'translation/source';
-const dbs = 'site arena emails learn activity coordinates study clas contact patron coach broadcast streamer tfa settings preferences team perfStat search tourname faq lag swiss puzzle puzzleTheme'.split(' ');
+const dbs = 'site arena emails learn activity coordinates study clas contact patron coach broadcast streamer tfa settings preferences team perfStat search tourname faq lag swiss puzzle puzzleTheme challenge'.split(' ');
function ucfirst(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
diff --git a/build.sbt b/build.sbt
index db2a3422f6..71685e768f 100644
--- a/build.sbt
+++ b/build.sbt
@@ -60,7 +60,7 @@ lazy val i18n = smallModule("i18n",
MessageCompiler(
sourceDir = new File("translation/source"),
destDir = new File("translation/dest"),
- dbs = "site arena emails learn activity coordinates study class contact patron coach broadcast streamer tfa settings preferences team perfStat search tourname faq lag swiss puzzle puzzleTheme".split(' ').toList,
+ dbs = "site arena emails learn activity coordinates study class contact patron coach broadcast streamer tfa settings preferences team perfStat search tourname faq lag swiss puzzle puzzleTheme challenge".split(' ').toList,
compileTo = (sourceManaged in Compile).value
)
}.taskValue
diff --git a/modules/challenge/src/main/Challenge.scala b/modules/challenge/src/main/Challenge.scala
index 836009d964..a02308e42d 100644
--- a/modules/challenge/src/main/Challenge.scala
+++ b/modules/challenge/src/main/Challenge.scala
@@ -6,6 +6,7 @@ import chess.{ Color, Mode, Speed }
import org.joda.time.DateTime
import lila.game.{ Game, PerfPicker }
+import lila.i18n.{ I18nKey, I18nKeys }
import lila.rating.PerfType
import lila.user.User
@@ -112,6 +113,13 @@ object Challenge {
def apply(id: Int): Option[Status] = all.find(_.id == id)
}
+ sealed abstract class DeclineReason(key: I18nKey)
+
+ object DeclineReason {
+ case object Generic extends DeclineReason(I18nKeys.challenge.declineGeneric)
+ case object Later extends DeclineReason(I18nKeys.challenge.declineLater)
+ }
+
case class Rating(int: Int, provisional: Boolean) {
def show = s"$int${if (provisional) "?" else ""}"
}
diff --git a/modules/challenge/src/main/ChallengeGranter.scala b/modules/challenge/src/main/ChallengeGranter.scala
index c66d22a05d..ebaeeec37c 100644
--- a/modules/challenge/src/main/ChallengeGranter.scala
+++ b/modules/challenge/src/main/ChallengeGranter.scala
@@ -2,7 +2,7 @@ package lila.challenge
import play.api.i18n.Lang
-import lila.i18n.I18nKeys
+import lila.i18n.I18nKeys.{ challenge => trans }
import lila.pref.Pref
import lila.rating.PerfType
import lila.relation.{ Block, Follow }
@@ -26,13 +26,13 @@ object ChallengeDenied {
def translated(d: ChallengeDenied)(implicit lang: Lang): String =
d.reason match {
- case Reason.YouAreAnon => I18nKeys.registerToSendChallenges.txt()
- case Reason.YouAreBlocked => I18nKeys.youCannotChallengeX.txt(d.dest.titleUsername)
- case Reason.TheyDontAcceptChallenges => I18nKeys.xDoesNotAcceptChallenges.txt(d.dest.titleUsername)
+ case Reason.YouAreAnon => trans.registerToSendChallenges.txt()
+ case Reason.YouAreBlocked => trans.youCannotChallengeX.txt(d.dest.titleUsername)
+ case Reason.TheyDontAcceptChallenges => trans.xDoesNotAcceptChallenges.txt(d.dest.titleUsername)
case Reason.RatingOutsideRange(perf) =>
- I18nKeys.yourXRatingIsTooFarFromY.txt(perf.trans, d.dest.titleUsername)
- case Reason.RatingIsProvisional(perf) => I18nKeys.cannotChallengeDueToProvisionalXRating.txt(perf.trans)
- case Reason.FriendsOnly => I18nKeys.xOnlyAcceptsChallengesFromFriends.txt(d.dest.titleUsername)
+ trans.yourXRatingIsTooFarFromY.txt(perf.trans, d.dest.titleUsername)
+ case Reason.RatingIsProvisional(perf) => trans.cannotChallengeDueToProvisionalXRating.txt(perf.trans)
+ case Reason.FriendsOnly => trans.xOnlyAcceptsChallengesFromFriends.txt(d.dest.titleUsername)
case Reason.BotUltraBullet => "Bots cannot play UltraBullet. Choose a slower time control."
}
}
diff --git a/modules/i18n/src/main/I18nKeys.scala b/modules/i18n/src/main/I18nKeys.scala
index bee2acd882..687868cff9 100644
--- a/modules/i18n/src/main/I18nKeys.scala
+++ b/modules/i18n/src/main/I18nKeys.scala
@@ -279,7 +279,6 @@ val `xStartedFollowingY` = new I18nKey("xStartedFollowingY")
val `more` = new I18nKey("more")
val `memberSince` = new I18nKey("memberSince")
val `lastSeenActive` = new I18nKey("lastSeenActive")
-val `challengeToPlay` = new I18nKey("challengeToPlay")
val `player` = new I18nKey("player")
val `list` = new I18nKey("list")
val `graph` = new I18nKey("graph")
@@ -604,7 +603,6 @@ val `error.max` = new I18nKey("error.max")
val `error.unknown` = new I18nKey("error.unknown")
val `custom` = new I18nKey("custom")
val `notifications` = new I18nKey("notifications")
-val `challenges` = new I18nKey("challenges")
val `perfRatingX` = new I18nKey("perfRatingX")
val `practiceWithComputer` = new I18nKey("practiceWithComputer")
val `anotherWasX` = new I18nKey("anotherWasX")
@@ -643,12 +641,6 @@ val `advantage` = new I18nKey("advantage")
val `opening` = new I18nKey("opening")
val `middlegame` = new I18nKey("middlegame")
val `endgame` = new I18nKey("endgame")
-val `registerToSendChallenges` = new I18nKey("registerToSendChallenges")
-val `youCannotChallengeX` = new I18nKey("youCannotChallengeX")
-val `xDoesNotAcceptChallenges` = new I18nKey("xDoesNotAcceptChallenges")
-val `yourXRatingIsTooFarFromY` = new I18nKey("yourXRatingIsTooFarFromY")
-val `cannotChallengeDueToProvisionalXRating` = new I18nKey("cannotChallengeDueToProvisionalXRating")
-val `xOnlyAcceptsChallengesFromFriends` = new I18nKey("xOnlyAcceptsChallengesFromFriends")
val `conditionalPremoves` = new I18nKey("conditionalPremoves")
val `addCurrentVariation` = new I18nKey("addCurrentVariation")
val `playVariationToCreateConditionalPremoves` = new I18nKey("playVariationToCreateConditionalPremoves")
@@ -698,9 +690,6 @@ val `teamNamedX` = new I18nKey("teamNamedX")
val `youCannotPostYetPlaySomeGames` = new I18nKey("youCannotPostYetPlaySomeGames")
val `subscribe` = new I18nKey("subscribe")
val `unsubscribe` = new I18nKey("unsubscribe")
-val `challengeDeclined` = new I18nKey("challengeDeclined")
-val `challengeAccepted` = new I18nKey("challengeAccepted")
-val `challengeCanceled` = new I18nKey("challengeCanceled")
val `opponentLeftCounter` = new I18nKey("opponentLeftCounter")
val `mateInXHalfMoves` = new I18nKey("mateInXHalfMoves")
val `nextCaptureOrPawnMoveInXHalfMoves` = new I18nKey("nextCaptureOrPawnMoveInXHalfMoves")
@@ -1958,4 +1947,20 @@ val `healthyMix` = new I18nKey("puzzleTheme:healthyMix")
val `healthyMixDescription` = new I18nKey("puzzleTheme:healthyMixDescription")
}
+object challenge {
+val `challenges` = new I18nKey("challenge:challenges")
+val `challengeToPlay` = new I18nKey("challenge:challengeToPlay")
+val `challengeDeclined` = new I18nKey("challenge:challengeDeclined")
+val `challengeAccepted` = new I18nKey("challenge:challengeAccepted")
+val `challengeCanceled` = new I18nKey("challenge:challengeCanceled")
+val `registerToSendChallenges` = new I18nKey("challenge:registerToSendChallenges")
+val `youCannotChallengeX` = new I18nKey("challenge:youCannotChallengeX")
+val `xDoesNotAcceptChallenges` = new I18nKey("challenge:xDoesNotAcceptChallenges")
+val `yourXRatingIsTooFarFromY` = new I18nKey("challenge:yourXRatingIsTooFarFromY")
+val `cannotChallengeDueToProvisionalXRating` = new I18nKey("challenge:cannotChallengeDueToProvisionalXRating")
+val `xOnlyAcceptsChallengesFromFriends` = new I18nKey("challenge:xOnlyAcceptsChallengesFromFriends")
+val `declineGeneric` = new I18nKey("challenge:declineGeneric")
+val `declineLater` = new I18nKey("challenge:declineLater")
+}
+
}
diff --git a/translation/source/challenge.xml b/translation/source/challenge.xml
new file mode 100644
index 0000000000..de28541396
--- /dev/null
+++ b/translation/source/challenge.xml
@@ -0,0 +1,16 @@
+
+
+ Challenges
+ Challenge to a game
+ Challenge declined
+ Challenge accepted!
+ Challenge canceled.
+ Please register to send challenges.
+ You cannot challenge %s.
+ %s does not accept challenges.
+ Your %1$s rating is too far from %2$s.
+ Cannot challenge due to provisional %s rating.
+ %s only accepts challenges from friends.
+ I'm not accepting challenges at the moment.
+ I'm not accepting challenges right now, please ask again later.
+
diff --git a/translation/source/site.xml b/translation/source/site.xml
index eaaa9c821b..9e06135af9 100644
--- a/translation/source/site.xml
+++ b/translation/source/site.xml
@@ -384,7 +384,6 @@ computer analysis, game chat and shareable URL.
More
Member since
Active %s
-
Challenge to a game
Player
List
Graph
@@ -737,7 +736,6 @@ computer analysis, game chat and shareable URL.
Error
Custom
Notifications
-
Challenges
Rating: %s
- %s second to play the first move
@@ -784,12 +782,6 @@ computer analysis, game chat and shareable URL.
Opening
Middlegame
Endgame
- Please register to send challenges.
- You cannot challenge %s.
- %s does not accept challenges.
- Your %1$s rating is too far from %2$s.
- Cannot challenge due to provisional %s rating.
- %s only accepts challenges from friends.
Conditional premoves
Add current variation
Play a variation to create conditional premoves
@@ -843,7 +835,4 @@ computer analysis, game chat and shareable URL.
You can't post in the forums yet. Play some games!
Subscribe
Unsubscribe
- Challenge declined
- Challenge accepted!
- Challenge canceled.