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.