Merge branch 'master' into analyse-nvui-make-moves

pull/9295/head
Albert Ford 2021-06-28 19:28:39 -06:00 committed by GitHub
commit 3e044391c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
402 changed files with 2817 additions and 933 deletions

View File

@ -202,7 +202,7 @@ final class Challenge(
Action.async { req => Action.async { req =>
import cats.implicits._ import cats.implicits._
val scopes = List(OAuthScope.Challenge.Write) val scopes = List(OAuthScope.Challenge.Write)
(get("token1", req) map AccessToken.Id, get("token2", req) map AccessToken.Id).mapN { (get("token1", req) map AccessToken.Id.apply, get("token2", req) map AccessToken.Id.apply).mapN {
env.oAuth.server.authBoth(scopes) env.oAuth.server.authBoth(scopes)
} ?? { } ?? {
_ flatMap { _ flatMap {

View File

@ -20,6 +20,16 @@ final class Editor(env: Env) extends LilaController(env) {
}) })
} }
private lazy val endgamePositionsJson = lila.common.String.html.safeJsonValue {
JsArray(
chess.EndgamePosition.positions map { p =>
Json.obj(
"name" -> p.name,
"fen" -> p.fen
)
})
}
def index = load("") def index = load("")
def load(urlFen: String) = def load(urlFen: String) =
@ -35,7 +45,8 @@ final class Editor(env: Env) extends LilaController(env) {
html.board.editor( html.board.editor(
sit = situation, sit = situation,
fen = Forsyth >> situation, fen = Forsyth >> situation,
positionsJson positionsJson,
endgamePositionsJson
) )
) )
} }

View File

@ -48,9 +48,9 @@ final class OAuth(env: Env) extends LilaController(env) {
prompt.authorize(me) match { prompt.authorize(me) match {
case Validated.Valid(authorized) => case Validated.Valid(authorized) =>
env.oAuth.authorizationApi.create(authorized) map { code => env.oAuth.authorizationApi.create(authorized) map { code =>
Redirect(authorized.redirectUrl(code)) SeeOther(authorized.redirectUrl(code))
} }
case Validated.Invalid(error) => Redirect(prompt.redirectUri.error(error, prompt.state)).fuccess case Validated.Invalid(error) => SeeOther(prompt.redirectUri.error(error, prompt.state)).fuccess
} }
} }
} }

View File

@ -2,6 +2,7 @@ package lila.app
package templating package templating
import play.api.data._ import play.api.data._
import play.api.i18n.Lang
import lila.api.Context import lila.api.Context
import lila.app.ui.ScalatagsTemplate._ import lila.app.ui.ScalatagsTemplate._
@ -26,6 +27,14 @@ trait FormHelper { self: I18nHelper =>
val postForm = form(method := "post") val postForm = form(method := "post")
val submitButton = button(tpe := "submit") val submitButton = button(tpe := "submit")
def markdownAvailable(implicit lang: Lang) =
trans.markdownAvailable(
a(
href := "https://guides.github.com/features/mastering-markdown/",
targetBlank
)("Markdown")
)
object form3 { object form3 {
private val idPrefix = "form3" private val idPrefix = "form3"

View File

@ -150,6 +150,10 @@ object pref {
setting( setting(
sayGgWpAfterLosingOrDrawing(), sayGgWpAfterLosingOrDrawing(),
radios(form("behavior.courtesy"), booleanChoices) radios(form("behavior.courtesy"), booleanChoices)
),
setting(
scrollOnTheBoardToReplayMoves(),
radios(form("behavior.scrollMoves"), booleanChoices)
) )
), ),
categFieldset(PrefCateg.Privacy, categ)( categFieldset(PrefCateg.Privacy, categ)(

View File

@ -1,17 +0,0 @@
package views.html.base
import com.github.blemale.scaffeine.LoadingCache
import scala.concurrent.duration._
import lila.app.ui.ScalatagsTemplate._
object markdown {
private val renderer = new lila.common.Markdown
private val cache: LoadingCache[String, String] = lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterWrite(10 minutes)
.maximumSize(256)
.build(renderer.apply)
def apply(text: String): Frag = raw(cache get text)
}

View File

@ -59,6 +59,7 @@ object bits {
trans.flipBoard, trans.flipBoard,
trans.loadPosition, trans.loadPosition,
trans.popularOpenings, trans.popularOpenings,
trans.endgamePositions,
trans.castling, trans.castling,
trans.whiteCastlingKingside, trans.whiteCastlingKingside,
trans.blackCastlingKingside, trans.blackCastlingKingside,

View File

@ -13,7 +13,8 @@ object editor {
def apply( def apply(
sit: chess.Situation, sit: chess.Situation,
fen: FEN, fen: FEN,
positionsJson: String positionsJson: String,
endgamePositionsJson: String,
)(implicit ctx: Context) = )(implicit ctx: Context) =
views.html.base.layout( views.html.base.layout(
title = trans.boardEditor.txt(), title = trans.boardEditor.txt(),
@ -21,7 +22,7 @@ object editor {
jsModule("editor"), jsModule("editor"),
embedJsUnsafeLoadThen( embedJsUnsafeLoadThen(
s"""const data=${safeJsonValue(bits.jsData(sit, fen))};data.positions=$positionsJson; s"""const data=${safeJsonValue(bits.jsData(sit, fen))};data.positions=$positionsJson;
LichessEditor(document.getElementById('board-editor'), data);""" data.endgamePositions=$endgamePositionsJson;LichessEditor(document.getElementById('board-editor'), data);"""
) )
), ),
moreCss = cssTag("editor"), moreCss = cssTag("editor"),

View File

@ -27,7 +27,7 @@ object theirs {
case Status.Created | Status.Offline => case Status.Created | Status.Offline =>
frag( frag(
h1( h1(
if (c.isOpen) c.name | "Open Challenge" if (c.isOpen) c.name | "Open challenge"
else else
user.fold[Frag]("Anonymous")(u => user.fold[Frag]("Anonymous")(u =>
frag( frag(

View File

@ -34,16 +34,7 @@ object wall {
ul( ul(
li(trans.clas.newsEdit2()), li(trans.clas.newsEdit2()),
li(trans.clas.newsEdit3()), li(trans.clas.newsEdit3()),
li( li(markdownAvailable)
trans.clas.markdownAvailable(
a(
href := "https://guides.github.com/features/mastering-markdown/",
targetBlank
)(
"Markdown"
)
)
)
) )
), ),
postForm(cls := "form3", action := routes.Clas.wallUpdate(c.id.value))( postForm(cls := "form3", action := routes.Clas.wallUpdate(c.id.value))(

View File

@ -75,8 +75,10 @@ object coordinate {
), ),
div(cls := "coord-trainer__board main-board")( div(cls := "coord-trainer__board main-board")(
svgTag(cls := "coords-svg", viewBoxAttr := "0 0 100 100")( svgTag(cls := "coords-svg", viewBoxAttr := "0 0 100 100")(
textTag(cls := "coord current-coord"), textTag(cls := "coord coord--resolved"),
textTag(cls := "coord next-coord") textTag(cls := "coord coord--current"),
textTag(cls := "coord coord--next"),
textTag(cls := "coord coord--new")
), ),
chessgroundBoard chessgroundBoard
), ),

View File

@ -63,7 +63,7 @@ object event {
) )
), ),
e.description.map { d => e.description.map { d =>
div(cls := "desc")(views.html.base.markdown(d)) div(cls := "desc")(markdown(d))
}, },
if (e.isFinished) p(cls := "desc")("The event is finished.") if (e.isFinished) p(cls := "desc")("The event is finished.")
else if (e.isNow) a(href := e.url, cls := "button button-fat")(trans.eventInProgress()) else if (e.isNow) a(href := e.url, cls := "button button-fat")(trans.eventInProgress())
@ -76,6 +76,18 @@ object event {
) )
} }
private object markdown {
import scala.concurrent.duration._
private val renderer = new lila.common.Markdown(table = true, list = true)
private val cache: com.github.blemale.scaffeine.LoadingCache[String, String] =
lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterAccess(10 minutes)
.maximumSize(64)
.build(renderer.apply)
def apply(text: String): Frag = raw(cache get text)
}
def manager(events: List[Event])(implicit ctx: Context) = { def manager(events: List[Event])(implicit ctx: Context) = {
val title = "Event manager" val title = "Event manager"
layout(title = title) { layout(title = title) {

View File

@ -33,7 +33,8 @@ object index {
url = s"$netBaseUrl${routes.Learn.index}" url = s"$netBaseUrl${routes.Learn.index}"
) )
.some, .some,
zoomable = true zoomable = true,
chessground = false
) { ) {
main(id := "learn-app") main(id := "learn-app")
} }

View File

@ -139,7 +139,8 @@ object inquiry {
) )
}, },
isGranted(_.Shadowban) option isGranted(_.Shadowban) option
a(href := routes.Mod.communicationPublic(in.user.id))("View", br, "Comms") a(href := routes.Mod.communicationPublic(in.user.id))("View", br, "Comms"),
in.report.isAppeal option a(href := routes.Appeal.show(in.user.id))("View", br, "Appeal")
), ),
div(cls := "actions")( div(cls := "actions")(
isGranted(_.ModMessage) option div(cls := "dropper warn buttons")( isGranted(_.ModMessage) option div(cls := "dropper warn buttons")(

View File

@ -71,6 +71,7 @@ object racer {
s.raceComplete, s.raceComplete,
s.spectating, s.spectating,
s.joinTheRace, s.joinTheRace,
s.startTheRace,
s.yourRankX, s.yourRankX,
s.waitForRematch, s.waitForRematch,
s.nextRace, s.nextRace,

View File

@ -55,7 +55,7 @@ object form {
), ),
postForm(cls := "terminate", action := routes.Simul.abort(simul.id))( postForm(cls := "terminate", action := routes.Simul.abort(simul.id))(
submitButton(dataIcon := "", cls := "text button button-red confirm")( submitButton(dataIcon := "", cls := "text button button-red confirm")(
"Cancel the simul" trans.cancelSimul()
) )
) )
) )
@ -94,11 +94,11 @@ object form {
form3.split( form3.split(
form3.group( form3.group(
form("clockTime"), form("clockTime"),
raw("Clock initial time"), trans.clockInitialTime(),
help = trans.simulClockHint().some, help = trans.simulClockHint().some,
half = true half = true
)(form3.select(_, clockTimeChoices)), )(form3.select(_, clockTimeChoices)),
form3.group(form("clockIncrement"), raw("Clock increment"), half = true)( form3.group(form("clockIncrement"), trans.clockIncrement(), half = true)(
form3.select(_, clockIncrementChoices) form3.select(_, clockIncrementChoices)
) )
), ),
@ -111,37 +111,38 @@ object form {
)( )(
form3.select(_, clockExtraChoices) form3.select(_, clockExtraChoices)
), ),
form3.group(form("color"), raw("Host color for each game"), half = true)( form3.group(form("color"), trans.simulHostcolor(), half = true)(
form3.select(_, colorChoices) form3.select(_, colorChoices)
) )
), ),
form3.split( form3.split(
teams.nonEmpty option teams.nonEmpty option
form3.group(form("team"), raw("Only members of team"), half = true)( form3.group(form("team"), trans.onlyMembersOfTeam(), half = true)(
form3.select(_, List(("", "No Restriction")) ::: teams.map(_.pair)) form3.select(_, List(("", trans.noRestriction.txt())) ::: teams.map(_.pair))
), ),
form3.group( form3.group(
form("position"), form("position"),
trans.startPosition(), trans.startPosition(),
klass = "position", klass = "position",
half = true, half = true,
help = trans.positionInputHelp(a(href := routes.Editor.index, targetBlank)(trans.boardEditor.txt())).some help =
trans.positionInputHelp(a(href := routes.Editor.index, targetBlank)(trans.boardEditor.txt())).some
)(form3.input(_)) )(form3.input(_))
), ),
form3.group( form3.group(
form("estimatedStartAt"), form("estimatedStartAt"),
frag("Estimated start time"), trans.estimatedStart(),
half = true half = true
)(form3.flatpickr(_)), )(form3.flatpickr(_)),
form3.group( form3.group(
form("text"), form("text"),
raw("Simul description"), trans.simulDescription(),
help = frag("Anything you want to tell the participants?").some help = trans.simulDescriptionHelp().some
)(form3.textarea(_)(rows := 10)), )(form3.textarea(_)(rows := 10)),
ctx.me.exists(_.canBeFeatured) option form3.checkbox( ctx.me.exists(_.canBeFeatured) option form3.checkbox(
form("featured"), form("featured"),
frag("Feature on lichess.org/simul"), trans.simulFeatured("lichess.org/simul"),
help = frag("Show your simul to everyone on lichess.org/simul. Disable for private simuls.").some help = trans.simulFeaturedHelp("lichess.org/simul").some
) )
) )
} }

View File

@ -205,7 +205,10 @@ object contact {
Leaf( Leaf(
"casual", "casual",
noRatingPoints(), noRatingPoints(),
p(ratedGame()) frag(
p(ratedGame()),
botRatingAbuse()
)
), ),
Leaf( Leaf(
"error-page", "error-page",

View File

@ -5,6 +5,7 @@ import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._ import lila.app.ui.ScalatagsTemplate._
import lila.i18n.{ I18nKeys => trans } import lila.i18n.{ I18nKeys => trans }
import lila.swiss.Swiss import lila.swiss.Swiss
import play.api.i18n.Lang
import controllers.routes import controllers.routes
@ -70,17 +71,13 @@ object bits {
) )
) )
def showInterval(s: Swiss): Frag = def showInterval(s: Swiss)(implicit lang: Lang): Frag =
s.settings.dailyInterval match { s.settings.dailyInterval match {
case Some(1) => frag("One round per day") case Some(d) => trans.swiss.oneRoundEveryXDays.pluralSame(d)
case Some(d) => frag(s"One round every $d days") case None if s.settings.manualRounds => trans.swiss.roundsAreStartedManually()
case None if s.settings.manualRounds => frag("Rounds are started manually")
case None => case None =>
frag( if (s.settings.intervalSeconds < 60) trans.swiss.xSecondsBetweenRounds.pluralSame(s.settings.intervalSeconds)
if (s.settings.intervalSeconds < 60) pluralize("second", s.settings.intervalSeconds) else trans.swiss.xMinutesBetweenRounds.pluralSame(s.settings.intervalSeconds / 60)
else pluralize("minute", s.settings.intervalSeconds / 60),
" between rounds"
)
} }
def jsI18n(implicit ctx: Context) = i18nJsObject(i18nKeys) def jsI18n(implicit ctx: Context) = i18nJsObject(i18nKeys)
@ -102,6 +99,10 @@ object bits {
trans.averageOpponent, trans.averageOpponent,
trans.tournamentComplete, trans.tournamentComplete,
trans.password, trans.password,
trans.swiss.viewAllXRounds trans.swiss.viewAllXRounds,
trans.swiss.ongoingGames,
trans.swiss.startingIn,
trans.swiss.nextRound,
trans.team.joinTeam,
).map(_.key) ).map(_.key)
} }

View File

@ -14,14 +14,14 @@ object form {
def create(form: Form[_], teamId: TeamID)(implicit ctx: Context) = def create(form: Form[_], teamId: TeamID)(implicit ctx: Context) =
views.html.base.layout( views.html.base.layout(
title = "New Swiss tournament", title = trans.swiss.newSwiss.txt(),
moreCss = cssTag("swiss.form"), moreCss = cssTag("swiss.form"),
moreJs = jsModule("tourForm") moreJs = jsModule("tourForm")
) { ) {
val fields = new SwissFields(form, none) val fields = new SwissFields(form, none)
main(cls := "page-small")( main(cls := "page-small")(
div(cls := "swiss__form tour__form box box-pad")( div(cls := "swiss__form tour__form box box-pad")(
h1("New Swiss tournament"), h1(trans.swiss.newSwiss()),
postForm(cls := "form3", action := routes.Swiss.create(teamId))( postForm(cls := "form3", action := routes.Swiss.create(teamId))(
form3.split(fields.name, fields.nbRounds), form3.split(fields.name, fields.nbRounds),
form3.split(fields.rated, fields.variant), form3.split(fields.rated, fields.variant),
@ -80,7 +80,7 @@ object form {
), ),
postForm(cls := "terminate", action := routes.Swiss.terminate(swiss.id.value))( postForm(cls := "terminate", action := routes.Swiss.terminate(swiss.id.value))(
submitButton(dataIcon := "", cls := "text button button-red confirm")( submitButton(dataIcon := "", cls := "text button button-red confirm")(
"Cancel the tournament" trans.cancelTournament()
) )
) )
) )
@ -90,23 +90,23 @@ object form {
private def condition(form: Form[_], fields: SwissFields, swiss: Option[Swiss])(implicit ctx: Context) = private def condition(form: Form[_], fields: SwissFields, swiss: Option[Swiss])(implicit ctx: Context) =
frag( frag(
form3.split( form3.split(
form3.group(form("conditions.nbRatedGame.nb"), frag("Minimum rated games"), half = true)( form3.group(form("conditions.nbRatedGame.nb"), trans.minimumRatedGames(), half = true)(
form3.select(_, SwissCondition.DataForm.nbRatedGameChoices) form3.select(_, SwissCondition.DataForm.nbRatedGameChoices)
), ),
(ctx.me.exists(_.hasTitle) || isGranted(_.ManageTournament)) ?? { (ctx.me.exists(_.hasTitle) || isGranted(_.ManageTournament)) ?? {
form3.checkbox( form3.checkbox(
form("conditions.titled"), form("conditions.titled"),
frag("Only titled players"), trans.onlyTitled(),
help = frag("Require an official title to join the tournament").some, help = trans.onlyTitledHelp().some,
half = true half = true
) )
} }
), ),
form3.split( form3.split(
form3.group(form("conditions.minRating.rating"), frag("Minimum rating"), half = true)( form3.group(form("conditions.minRating.rating"), trans.minimumRating(), half = true)(
form3.select(_, SwissCondition.DataForm.minRatingChoices) form3.select(_, SwissCondition.DataForm.minRatingChoices)
), ),
form3.group(form("conditions.maxRating.rating"), frag("Maximum weekly rating"), half = true)( form3.group(form("conditions.maxRating.rating"), trans.maximumWeeklyRating(), half = true)(
form3.select(_, SwissCondition.DataForm.maxRatingChoices) form3.select(_, SwissCondition.DataForm.maxRatingChoices)
) )
) )
@ -133,8 +133,8 @@ final private class SwissFields(form: Form[_], swiss: Option[Swiss])(implicit ct
def nbRounds = def nbRounds =
form3.group( form3.group(
form("nbRounds"), form("nbRounds"),
"Number of rounds", trans.swiss.numberOfRounds(),
help = raw("An odd number of rounds allows optimal color balance.").some, help = trans.swiss.numberOfRoundsHelp().some,
half = true half = true
)( )(
form3.input(_, typ = "number") form3.input(_, typ = "number")
@ -145,7 +145,7 @@ final private class SwissFields(form: Form[_], swiss: Option[Swiss])(implicit ct
form3.checkbox( form3.checkbox(
form("rated"), form("rated"),
trans.rated(), trans.rated(),
help = raw("Games are rated<br>and impact players ratings").some help = trans.ratedFormHelp().some
), ),
st.input(tpe := "hidden", st.name := form("rated").name, value := "false") // hack allow disabling rated st.input(tpe := "hidden", st.name := form("rated").name, value := "false") // hack allow disabling rated
) )
@ -167,16 +167,14 @@ final private class SwissFields(form: Form[_], swiss: Option[Swiss])(implicit ct
) )
) )
def roundInterval = def roundInterval =
form3.group(form("roundInterval"), frag("Interval between rounds"), half = true)( form3.group(form("roundInterval"), trans.swiss.roundInterval(), half = true)(
form3.select(_, SwissForm.roundIntervalChoices) form3.select(_, SwissForm.roundIntervalChoices)
) )
def description = def description =
form3.group( form3.group(
form("description"), form("description"),
frag("Tournament description"), trans.tournDescription(),
help = frag( help = trans.tournDescriptionHelp().some,
"Anything special you want to tell the participants? Try to keep it short. Markdown links are available: [name](https://url)"
).some,
half = true half = true
)(form3.textarea(_)(rows := 4)) )(form3.textarea(_)(rows := 4))
def position = def position =
@ -185,25 +183,26 @@ final private class SwissFields(form: Form[_], swiss: Option[Swiss])(implicit ct
trans.startPosition(), trans.startPosition(),
klass = "position", klass = "position",
half = true, half = true,
help = trans.positionInputHelp(a(href := routes.Editor.index, targetBlank)(trans.boardEditor.txt())).some help =
trans.positionInputHelp(a(href := routes.Editor.index, targetBlank)(trans.boardEditor.txt())).some
)(form3.input(_)) )(form3.input(_))
def startsAt = def startsAt =
form3.group( form3.group(
form("startsAt"), form("startsAt"),
frag("Tournament start date"), trans.swiss.tournStartDate(),
help = frag("In your own local timezone").some, help = trans.inYourLocalTimezone().some,
half = true half = true
)(form3.flatpickr(_)) )(form3.flatpickr(_))
def chatFor = def chatFor =
form3.group(form("chatFor"), frag("Tournament chat"), half = true) { f => form3.group(form("chatFor"), trans.tournChat(), half = true) { f =>
form3.select( form3.select(
f, f,
Seq( Seq(
Swiss.ChatFor.NONE -> "No chat", Swiss.ChatFor.NONE -> trans.noChat.txt(),
Swiss.ChatFor.LEADERS -> "Only team leaders", Swiss.ChatFor.LEADERS -> trans.onlyTeamLeaders.txt(),
Swiss.ChatFor.MEMBERS -> "Only team members", Swiss.ChatFor.MEMBERS -> trans.onlyTeamMembers.txt(),
Swiss.ChatFor.ALL -> "All Lichess players" Swiss.ChatFor.ALL -> trans.study.everyone.txt()
) )
) )
} }
@ -219,10 +218,8 @@ final private class SwissFields(form: Form[_], swiss: Option[Swiss])(implicit ct
def forbiddenPairings = def forbiddenPairings =
form3.group( form3.group(
form("forbiddenPairings"), form("forbiddenPairings"),
frag("Forbidden pairings"), trans.swiss.forbiddenPairings(),
help = frag( help = trans.swiss.forbiddenPairingsHelp().some,
"Usernames of players that must not play together (Siblings, for instance). Two usernames per line, separated by a space."
).some,
half = true half = true
)(form3.textarea(_)(rows := 4)) )(form3.textarea(_)(rows := 4))
} }

View File

@ -33,8 +33,7 @@ object side {
if (s.settings.rated) trans.ratedTournament() else trans.casualTournament() if (s.settings.rated) trans.ratedTournament() else trans.casualTournament()
), ),
p( p(
span(cls := "swiss__meta__round")(s"${s.round}/${s.settings.nbRounds}"), span(cls := "swiss__meta__round")(trans.swiss.nbRounds.plural(s.settings.nbRounds, s"${s.round}/${s.settings.nbRounds}")),
" rounds",
separator, separator,
a(href := routes.Swiss.home)("Swiss"), a(href := routes.Swiss.home)("Swiss"),
(isGranted(_.ManageTournament) || (ctx.userId.has(s.createdBy) && !s.isFinished)) option frag( (isGranted(_.ManageTournament) || (ctx.userId.has(s.createdBy) && !s.isFinished)) option frag(

View File

@ -103,8 +103,18 @@ object form {
private def textFields(form: Form[_])(implicit ctx: Context) = frag( private def textFields(form: Form[_])(implicit ctx: Context) = frag(
form3.group(form("location"), trans.location())(form3.input(_)), form3.group(form("location"), trans.location())(form3.input(_)),
form3.group(form("description"), trans.description())(form3.textarea(_)(rows := 10)), form3.group(form("description"), trans.description(), help = markdownAvailable.some)(
form3.group(form("descPrivate"), trans.descPrivate(), help = trans.descPrivateHelp().some)( form3.textarea(_)(rows := 10)
),
form3.group(
form("descPrivate"),
trans.descPrivate(),
help = frag(
trans.descPrivateHelp(),
br,
markdownAvailable
).some
)(
form3.textarea(_)(rows := 10) form3.textarea(_)(rows := 10)
) )
) )

View File

@ -8,7 +8,7 @@ import lila.app.mashup.TeamInfo
import lila.app.templating.Environment._ import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._ import lila.app.ui.ScalatagsTemplate._
import lila.common.paginator.Paginator import lila.common.paginator.Paginator
import lila.common.String.html.{ markdownLinksOrRichText, richText, safeJsonValue } import lila.common.String.html.{ richText, safeJsonValue }
import lila.team.Team import lila.team.Team
object show { object show {
@ -176,7 +176,7 @@ object show {
div(cls := "team-show__content__col2")( div(cls := "team-show__content__col2")(
standardFlash(), standardFlash(),
st.section(cls := "team-show__desc")( st.section(cls := "team-show__desc")(
markdownLinksOrRichText { markdown {
t.descPrivate.ifTrue(info.mine) | t.description t.descPrivate.ifTrue(info.mine) | t.description
}, },
t.location.map { loc => t.location.map { loc =>
@ -228,6 +228,18 @@ object show {
) )
} }
private object markdown {
import scala.concurrent.duration._
private val renderer = new lila.common.Markdown(list = true)
private val cache: com.github.blemale.scaffeine.LoadingCache[String, String] =
lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterAccess(10 minutes)
.maximumSize(512)
.build(renderer.apply)
def apply(text: String): Frag = raw(cache get text)
}
// handle special teams here // handle special teams here
private def joinButton(t: Team)(implicit ctx: Context) = private def joinButton(t: Team)(implicit ctx: Context) =
t.id match { t.id match {

View File

@ -86,7 +86,7 @@ object form {
), ),
postForm(cls := "terminate", action := routes.Tournament.terminate(tour.id))( postForm(cls := "terminate", action := routes.Tournament.terminate(tour.id))(
submitButton(dataIcon := "", cls := "text button button-red confirm")( submitButton(dataIcon := "", cls := "text button button-red confirm")(
trans.cancelTournament() trans.cancelTournament()
) )
) )
) )
@ -234,7 +234,8 @@ final private class TourFields(form: Form[_], tour: Option[Tournament])(implicit
trans.startPosition(), trans.startPosition(),
klass = "position", klass = "position",
half = true, half = true,
help = trans.positionInputHelp(a(href := routes.Editor.index, targetBlank)(trans.boardEditor.txt())).some help =
trans.positionInputHelp(a(href := routes.Editor.index, targetBlank)(trans.boardEditor.txt())).some
)( )(
views.html.tournament.form.startingPosition(_, tour) views.html.tournament.form.startingPosition(_, tour)
) )

View File

@ -26,7 +26,7 @@ class Report:
def short_lang(lang): def short_lang(lang):
if lang in ["ne-NP", "la-LA", "nn-NO", "zh-CN", "ur-PK", "zh-TW", "tlh-AA", "ml-IN", "pt-BR", "tt-RU"]: if lang in ["ne-NP", "la-LA", "nn-NO", "zh-CN", "ur-PK", "zh-TW", "tlh-AA", "ml-IN", "pt-BR", "tt-RU", "de-CH"]:
return lang.replace("-", "").lower() return lang.replace("-", "").lower()
elif lang == "kab-DZ": elif lang == "kab-DZ":
return "kaby" return "kaby"

View File

@ -415,7 +415,7 @@ fishnet {
} }
offline_mode = true # any client can provide moves and analysis offline_mode = true # any client can provide moves and analysis
actor.name = fishnet actor.name = fishnet
analysis.nodes = 2000000 # nnue analysis.nodes = 2100000 # nnue
move.plies = 300 move.plies = 300
client_min_version = "2.1.3" client_min_version = "2.1.3"
} }

View File

@ -16,7 +16,7 @@ object BlogTransform {
private type Text = String private type Text = String
private type Html = String private type Html = String
private val renderer = new lila.common.Markdown private val renderer = new lila.common.Markdown(table = true)
private val cache: LoadingCache[Text, Html] = lila.memo.CacheApi.scaffeineNoScheduler private val cache: LoadingCache[Text, Html] = lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterWrite(15 minutes) .expireAfterWrite(15 minutes)

View File

@ -6,7 +6,7 @@ import scala.concurrent.duration._
final class ClasMarkup { final class ClasMarkup {
private val renderer = new lila.common.Markdown(autoLink = true) private val renderer = new lila.common.Markdown(autoLink = true, list = true)
private val cache: LoadingCache[String, String] = lila.memo.CacheApi.scaffeineNoScheduler private val cache: LoadingCache[String, String] = lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterAccess(20 minutes) .expireAfterAccess(20 minutes)

View File

@ -8,22 +8,41 @@ import com.vladsch.flexmark.parser.Parser
import com.vladsch.flexmark.util.data.MutableDataSet import com.vladsch.flexmark.util.data.MutableDataSet
import scala.jdk.CollectionConverters._ import scala.jdk.CollectionConverters._
final class Markdown(autoLink: Boolean = false) { final class Markdown(
autoLink: Boolean = true,
table: Boolean = false,
strikeThrough: Boolean = false,
header: Boolean = false,
blockQuote: Boolean = false,
list: Boolean = false
) {
private type Text = String private type Text = String
private type Html = String private type Html = String
private val extensions: java.util.List[Parser.ParserExtension] = List( private val extensions: java.util.List[Parser.ParserExtension] = List(
TablesExtension.create().some, table option TablesExtension.create(),
StrikethroughExtension.create().some, strikeThrough option StrikethroughExtension.create(),
autoLink option AutolinkExtension.create() autoLink option AutolinkExtension.create()
).flatten.asJava ).flatten.asJava
private val options = new MutableDataSet() private val options = new MutableDataSet()
options.set(Parser.EXTENSIONS, extensions) options.set(Parser.EXTENSIONS, extensions)
options.set(TablesExtension.CLASS_NAME, "slist") options.set(HtmlRenderer.ESCAPE_HTML, Boolean box true)
options.set(HtmlRenderer.ESCAPE_HTML, Boolean.box(true))
options.set(HtmlRenderer.SOFT_BREAK, "<br>") options.set(HtmlRenderer.SOFT_BREAK, "<br>")
// always disabled
options.set(Parser.HTML_BLOCK_PARSER, Boolean box false)
options.set(Parser.INDENTED_CODE_BLOCK_PARSER, Boolean box false)
options.set(Parser.FENCED_CODE_BLOCK_PARSER, Boolean box false)
// configurable
if (table) options.set(TablesExtension.CLASS_NAME, "slist")
if (!header) options.set(Parser.HEADING_PARSER, Boolean box false)
if (!blockQuote) options.set(Parser.BLOCK_QUOTE_PARSER, Boolean box false)
if (!list) options.set(Parser.LIST_BLOCK_PARSER, Boolean box false)
private val parser = Parser.builder(options).build() private val parser = Parser.builder(options).build()
private val renderer = HtmlRenderer.builder(options).build() private val renderer = HtmlRenderer.builder(options).build()

View File

@ -95,5 +95,5 @@ final class EvalCacheApi(
} }
private def destSize(fen: FEN): Int = private def destSize(fen: FEN): Int =
chess.Game(chess.variant.Standard.some, fen.some).situation.destinations.size chess.Game(chess.variant.Standard.some, fen.some).situation.moves.view.map(_._2.size).sum
} }

View File

@ -319,6 +319,7 @@ val `membersOnly` = new I18nKey("membersOnly")
val `boardEditor` = new I18nKey("boardEditor") val `boardEditor` = new I18nKey("boardEditor")
val `setTheBoard` = new I18nKey("setTheBoard") val `setTheBoard` = new I18nKey("setTheBoard")
val `popularOpenings` = new I18nKey("popularOpenings") val `popularOpenings` = new I18nKey("popularOpenings")
val `endgamePositions` = new I18nKey("endgamePositions")
val `startPosition` = new I18nKey("startPosition") val `startPosition` = new I18nKey("startPosition")
val `clearBoard` = new I18nKey("clearBoard") val `clearBoard` = new I18nKey("clearBoard")
val `savePosition` = new I18nKey("savePosition") val `savePosition` = new I18nKey("savePosition")
@ -712,6 +713,31 @@ val `welcome` = new I18nKey("welcome")
val `lichessPatronInfo` = new I18nKey("lichessPatronInfo") val `lichessPatronInfo` = new I18nKey("lichessPatronInfo")
val `coachManager` = new I18nKey("coachManager") val `coachManager` = new I18nKey("coachManager")
val `streamerManager` = new I18nKey("streamerManager") val `streamerManager` = new I18nKey("streamerManager")
val `cancelTournament` = new I18nKey("cancelTournament")
val `tournDescription` = new I18nKey("tournDescription")
val `tournDescriptionHelp` = new I18nKey("tournDescriptionHelp")
val `ratedFormHelp` = new I18nKey("ratedFormHelp")
val `onlyMembersOfTeam` = new I18nKey("onlyMembersOfTeam")
val `noRestriction` = new I18nKey("noRestriction")
val `minimumRatedGames` = new I18nKey("minimumRatedGames")
val `minimumRating` = new I18nKey("minimumRating")
val `maximumWeeklyRating` = new I18nKey("maximumWeeklyRating")
val `onlyTitled` = new I18nKey("onlyTitled")
val `onlyTitledHelp` = new I18nKey("onlyTitledHelp")
val `positionInputHelp` = new I18nKey("positionInputHelp")
val `cancelSimul` = new I18nKey("cancelSimul")
val `simulHostcolor` = new I18nKey("simulHostcolor")
val `estimatedStart` = new I18nKey("estimatedStart")
val `simulFeatured` = new I18nKey("simulFeatured")
val `simulFeaturedHelp` = new I18nKey("simulFeaturedHelp")
val `simulDescription` = new I18nKey("simulDescription")
val `simulDescriptionHelp` = new I18nKey("simulDescriptionHelp")
val `markdownAvailable` = new I18nKey("markdownAvailable")
val `inYourLocalTimezone` = new I18nKey("inYourLocalTimezone")
val `tournChat` = new I18nKey("tournChat")
val `noChat` = new I18nKey("noChat")
val `onlyTeamLeaders` = new I18nKey("onlyTeamLeaders")
val `onlyTeamMembers` = new I18nKey("onlyTeamMembers")
val `opponentLeftCounter` = new I18nKey("opponentLeftCounter") val `opponentLeftCounter` = new I18nKey("opponentLeftCounter")
val `mateInXHalfMoves` = new I18nKey("mateInXHalfMoves") val `mateInXHalfMoves` = new I18nKey("mateInXHalfMoves")
val `nextCaptureOrPawnMoveInXHalfMoves` = new I18nKey("nextCaptureOrPawnMoveInXHalfMoves") val `nextCaptureOrPawnMoveInXHalfMoves` = new I18nKey("nextCaptureOrPawnMoveInXHalfMoves")
@ -752,19 +778,6 @@ val `availableInNbLanguages` = new I18nKey("availableInNbLanguages")
val `nbSecondsToPlayTheFirstMove` = new I18nKey("nbSecondsToPlayTheFirstMove") val `nbSecondsToPlayTheFirstMove` = new I18nKey("nbSecondsToPlayTheFirstMove")
val `nbSeconds` = new I18nKey("nbSeconds") val `nbSeconds` = new I18nKey("nbSeconds")
val `andSaveNbPremoveLines` = new I18nKey("andSaveNbPremoveLines") val `andSaveNbPremoveLines` = new I18nKey("andSaveNbPremoveLines")
val `cancelTournament` = new I18nKey("cancelTournament")
val `tournDescription` = new I18nKey("tournDescription")
val `tournDescriptionHelp` = new I18nKey("tournDescriptionHelp")
val `ratedFormHelp` = new I18nKey("ratedFormHelp")
val `onlyMembersOfTeam` = new I18nKey("onlyMembersOfTeam")
val `noRestriction` = new I18nKey("noRestriction")
val `minimumRatedGames` = new I18nKey("minimumRatedGames")
val `minimumRating` = new I18nKey("minimumRating")
val `maximumWeeklyRating` = new I18nKey("maximumWeeklyRating")
val `onlyTitled` = new I18nKey("onlyTitled")
val `onlyTitledHelp` = new I18nKey("onlyTitledHelp")
val `hasChatHelp` = new I18nKey("hasChatHelp")
val `positionInputHelp` = new I18nKey("positionInputHelp")
object arena { object arena {
val `arenaTournaments` = new I18nKey("arena:arenaTournaments") val `arenaTournaments` = new I18nKey("arena:arenaTournaments")
@ -789,8 +802,6 @@ val `thisIsPrivate` = new I18nKey("arena:thisIsPrivate")
val `shareUrl` = new I18nKey("arena:shareUrl") val `shareUrl` = new I18nKey("arena:shareUrl")
val `drawStreak` = new I18nKey("arena:drawStreak") val `drawStreak` = new I18nKey("arena:drawStreak")
val `history` = new I18nKey("arena:history") val `history` = new I18nKey("arena:history")
val `drawingWithinNbMoves` = new I18nKey("arena:drawingWithinNbMoves")
val `viewAllXTeams` = new I18nKey("arena:viewAllXTeams")
val `newTeamBattle` = new I18nKey("arena:newTeamBattle") val `newTeamBattle` = new I18nKey("arena:newTeamBattle")
val `customStartDate` = new I18nKey("arena:customStartDate") val `customStartDate` = new I18nKey("arena:customStartDate")
val `customStartDateHelp` = new I18nKey("arena:customStartDateHelp") val `customStartDateHelp` = new I18nKey("arena:customStartDateHelp")
@ -799,6 +810,8 @@ val `allowBerserkHelp` = new I18nKey("arena:allowBerserkHelp")
val `allowChatHelp` = new I18nKey("arena:allowChatHelp") val `allowChatHelp` = new I18nKey("arena:allowChatHelp")
val `arenaStreaks` = new I18nKey("arena:arenaStreaks") val `arenaStreaks` = new I18nKey("arena:arenaStreaks")
val `arenaStreaksHelp` = new I18nKey("arena:arenaStreaksHelp") val `arenaStreaksHelp` = new I18nKey("arena:arenaStreaksHelp")
val `drawingWithinNbMoves` = new I18nKey("arena:drawingWithinNbMoves")
val `viewAllXTeams` = new I18nKey("arena:viewAllXTeams")
} }
object emails { object emails {
@ -1259,7 +1272,6 @@ val `nothingHere` = new I18nKey("class:nothingHere")
val `newsEdit1` = new I18nKey("class:newsEdit1") val `newsEdit1` = new I18nKey("class:newsEdit1")
val `newsEdit2` = new I18nKey("class:newsEdit2") val `newsEdit2` = new I18nKey("class:newsEdit2")
val `newsEdit3` = new I18nKey("class:newsEdit3") val `newsEdit3` = new I18nKey("class:newsEdit3")
val `markdownAvailable` = new I18nKey("class:markdownAvailable")
val `nbPendingInvitations` = new I18nKey("class:nbPendingInvitations") val `nbPendingInvitations` = new I18nKey("class:nbPendingInvitations")
val `nbTeachers` = new I18nKey("class:nbTeachers") val `nbTeachers` = new I18nKey("class:nbTeachers")
val `nbStudents` = new I18nKey("class:nbStudents") val `nbStudents` = new I18nKey("class:nbStudents")
@ -1318,6 +1330,7 @@ val `fideMate` = new I18nKey("contact:fideMate")
val `knightMate` = new I18nKey("contact:knightMate") val `knightMate` = new I18nKey("contact:knightMate")
val `noRatingPoints` = new I18nKey("contact:noRatingPoints") val `noRatingPoints` = new I18nKey("contact:noRatingPoints")
val `ratedGame` = new I18nKey("contact:ratedGame") val `ratedGame` = new I18nKey("contact:ratedGame")
val `botRatingAbuse` = new I18nKey("contact:botRatingAbuse")
val `errorPage` = new I18nKey("contact:errorPage") val `errorPage` = new I18nKey("contact:errorPage")
val `reportErrorPage` = new I18nKey("contact:reportErrorPage") val `reportErrorPage` = new I18nKey("contact:reportErrorPage")
val `banAppeal` = new I18nKey("contact:banAppeal") val `banAppeal` = new I18nKey("contact:banAppeal")
@ -1588,6 +1601,7 @@ val `inputMovesWithTheKeyboard` = new I18nKey("preferences:inputMovesWithTheKeyb
val `snapArrowsToValidMoves` = new I18nKey("preferences:snapArrowsToValidMoves") val `snapArrowsToValidMoves` = new I18nKey("preferences:snapArrowsToValidMoves")
val `sayGgWpAfterLosingOrDrawing` = new I18nKey("preferences:sayGgWpAfterLosingOrDrawing") val `sayGgWpAfterLosingOrDrawing` = new I18nKey("preferences:sayGgWpAfterLosingOrDrawing")
val `yourPreferencesHaveBeenSaved` = new I18nKey("preferences:yourPreferencesHaveBeenSaved") val `yourPreferencesHaveBeenSaved` = new I18nKey("preferences:yourPreferencesHaveBeenSaved")
val `scrollOnTheBoardToReplayMoves` = new I18nKey("preferences:scrollOnTheBoardToReplayMoves")
} }
object team { object team {
@ -1863,7 +1877,22 @@ val `lagCompensationExplanation` = new I18nKey("lag:lagCompensationExplanation")
object swiss { object swiss {
val `swissTournaments` = new I18nKey("swiss:swissTournaments") val `swissTournaments` = new I18nKey("swiss:swissTournaments")
val `roundsAreStartedManually` = new I18nKey("swiss:roundsAreStartedManually")
val `startingIn` = new I18nKey("swiss:startingIn")
val `nextRound` = new I18nKey("swiss:nextRound")
val `tournStartDate` = new I18nKey("swiss:tournStartDate")
val `numberOfRounds` = new I18nKey("swiss:numberOfRounds")
val `numberOfRoundsHelp` = new I18nKey("swiss:numberOfRoundsHelp")
val `roundInterval` = new I18nKey("swiss:roundInterval")
val `forbiddenPairings` = new I18nKey("swiss:forbiddenPairings")
val `forbiddenPairingsHelp` = new I18nKey("swiss:forbiddenPairingsHelp")
val `newSwiss` = new I18nKey("swiss:newSwiss")
val `viewAllXRounds` = new I18nKey("swiss:viewAllXRounds") val `viewAllXRounds` = new I18nKey("swiss:viewAllXRounds")
val `nbRounds` = new I18nKey("swiss:nbRounds")
val `oneRoundEveryXDays` = new I18nKey("swiss:oneRoundEveryXDays")
val `xSecondsBetweenRounds` = new I18nKey("swiss:xSecondsBetweenRounds")
val `xMinutesBetweenRounds` = new I18nKey("swiss:xMinutesBetweenRounds")
val `ongoingGames` = new I18nKey("swiss:ongoingGames")
} }
object puzzle { object puzzle {
@ -2109,6 +2138,7 @@ val `waitingForMorePlayers` = new I18nKey("storm:waitingForMorePlayers")
val `raceComplete` = new I18nKey("storm:raceComplete") val `raceComplete` = new I18nKey("storm:raceComplete")
val `spectating` = new I18nKey("storm:spectating") val `spectating` = new I18nKey("storm:spectating")
val `joinTheRace` = new I18nKey("storm:joinTheRace") val `joinTheRace` = new I18nKey("storm:joinTheRace")
val `startTheRace` = new I18nKey("storm:startTheRace")
val `yourRankX` = new I18nKey("storm:yourRankX") val `yourRankX` = new I18nKey("storm:yourRankX")
val `waitForRematch` = new I18nKey("storm:waitForRematch") val `waitForRematch` = new I18nKey("storm:waitForRematch")
val `nextRace` = new I18nKey("storm:nextRace") val `nextRace` = new I18nKey("storm:nextRace")

View File

@ -113,7 +113,7 @@ final class IrcApi(
text = s":$icon: ${slackdown.linkifyUsers(text)}", text = s":$icon: ${slackdown.linkifyUsers(text)}",
channel = s"tavern-monitor-${tpe.toString.toLowerCase}" channel = s"tavern-monitor-${tpe.toString.toLowerCase}"
) )
val md = s":$icon: ${markdown.linkifyUsers(text)}" val md = s"${markdown.userLink(mod.name)} :$icon: ${markdown.linkifyUsers(text)}"
slack(msg) >> slack(msg) >>
slack(msg.copy(channel = SlackClient.rooms.tavernMonitorAll)) >> slack(msg.copy(channel = SlackClient.rooms.tavernMonitorAll)) >>
zulip.mod(s"monitor-${tpe.toString.toLowerCase}")(md) >> zulip.mod(s"monitor-${tpe.toString.toLowerCase}")(md) >>
@ -235,7 +235,7 @@ final class IrcApi(
icon = "horsey", icon = "horsey",
text = slackdown linkifyUsers msg text = slackdown linkifyUsers msg
) )
) >> zulip()(s":lichess: ${markdown linkifyUsers msg}") ) >> zulip()(s":info: ${markdown linkifyUsers msg}")
object charge { object charge {
import lila.hub.actorApi.plan.ChargeEvent import lila.hub.actorApi.plan.ChargeEvent

View File

@ -278,7 +278,7 @@ final class ModlogApi(repo: ModlogRepo, userRepo: UserRepo, ircApi: IrcApi)(impl
import lila.mod.{ Modlog => M } import lila.mod.{ Modlog => M }
val icon = m.action match { val icon = m.action match {
case M.alt | M.engine | M.booster | M.troll | M.closeAccount => "thorhammer" case M.alt | M.engine | M.booster | M.troll | M.closeAccount => "thorhammer"
case M.unalt | M.unengine | M.unbooster | M.untroll | M.reopenAccount => "large_blue_circle" case M.unalt | M.unengine | M.unbooster | M.untroll | M.reopenAccount => "blue_circle"
case M.deletePost | M.deleteTeam | M.terminateTournament => "x" case M.deletePost | M.deleteTeam | M.terminateTournament => "x"
case M.chatTimeout => "hourglass_flowing_sand" case M.chatTimeout => "hourglass_flowing_sand"
case M.closeTopic | M.disableTeam => "lock" case M.closeTopic | M.disableTeam => "lock"

View File

@ -23,14 +23,11 @@ case class AccessToken(
object AccessToken { object AccessToken {
val idSize = 16 case class Id(value: String) extends AnyVal
object Id {
case class Id(value: String) extends AnyVal { def random() = Id(s"lio_${SecureRandom.nextString(32)}")
def isPersonal = value.lengthIs == idSize
} }
def makeId = Id(SecureRandom nextString idSize)
case class ForAuth(userId: User.ID, scopes: List[OAuthScope]) case class ForAuth(userId: User.ID, scopes: List[OAuthScope])
case class WithApp(token: AccessToken, app: OAuthApp) case class WithApp(token: AccessToken, app: OAuthApp)

View File

@ -15,7 +15,7 @@ final class AccessTokenApi(colls: OauthColls)(implicit ec: scala.concurrent.Exec
def create(granted: AccessTokenRequest.Granted): Fu[AccessToken] = { def create(granted: AccessTokenRequest.Granted): Fu[AccessToken] = {
val token = AccessToken( val token = AccessToken(
id = AccessToken.Id(Protocol.Secret.random("lio_").value), id = AccessToken.Id.random(),
publicId = BSONObjectID.generate(), publicId = BSONObjectID.generate(),
clientId = PersonalToken.clientId, // TODO clientId = PersonalToken.clientId, // TODO
userId = granted.userId, userId = granted.userId,

View File

@ -17,7 +17,7 @@ object AccessTokenRequest {
for { for {
grantType <- grantType.toValid(Error.GrantTypeRequired).andThen(GrantType.from) grantType <- grantType.toValid(Error.GrantTypeRequired).andThen(GrantType.from)
code <- code.map(AuthorizationCode.apply).toValid(Error.CodeRequired) code <- code.map(AuthorizationCode.apply).toValid(Error.CodeRequired)
codeVerifier <- codeVerifier.map(CodeVerifier.apply).toValid(Error.CodeVerifierRequired) codeVerifier <- codeVerifier.toValid(Error.CodeVerifierRequired).andThen(CodeVerifier.from)
redirectUri <- redirectUri.map(UncheckedRedirectUri.apply).toValid(Error.RedirectUriRequired) redirectUri <- redirectUri.map(UncheckedRedirectUri.apply).toValid(Error.RedirectUriRequired)
clientId <- clientId.map(ClientId.apply).toValid(Error.ClientIdRequired) clientId <- clientId.map(ClientId.apply).toValid(Error.ClientIdRequired)
} yield Prepared(grantType, code, codeVerifier, redirectUri, clientId) } yield Prepared(grantType, code, codeVerifier, redirectUri, clientId)

View File

@ -13,7 +13,7 @@ final class AuthorizationApi(val coll: Coll)(implicit ec: scala.concurrent.Execu
val code = Protocol.AuthorizationCode.random() val code = Protocol.AuthorizationCode.random()
coll.insert.one( coll.insert.one(
PendingAuthorizationBSONHandler write PendingAuthorization( PendingAuthorizationBSONHandler write PendingAuthorization(
code.secret.hashed, code.hashed,
request.clientId, request.clientId,
request.user, request.user,
request.redirectUri, request.redirectUri,
@ -27,7 +27,7 @@ final class AuthorizationApi(val coll: Coll)(implicit ec: scala.concurrent.Execu
def consume( def consume(
request: AccessTokenRequest.Prepared request: AccessTokenRequest.Prepared
): Fu[Validated[Protocol.Error, AccessTokenRequest.Granted]] = ): Fu[Validated[Protocol.Error, AccessTokenRequest.Granted]] =
coll.findAndModify($doc(F.hashedCode -> request.code.secret.hashed), coll.removeModifier) map { coll.findAndModify($doc(F.hashedCode -> request.code.hashed), coll.removeModifier) map {
_.result[PendingAuthorization] _.result[PendingAuthorization]
.toValid(Protocol.Error.AuthorizationCodeInvalid) .toValid(Protocol.Error.AuthorizationCodeInvalid)
.ensure(Protocol.Error.AuthorizationCodeExpired)(_.expires.isAfter(DateTime.now())) .ensure(Protocol.Error.AuthorizationCodeExpired)(_.expires.isAfter(DateTime.now()))

View File

@ -29,7 +29,7 @@ object OAuthForm {
) { ) {
def make(user: lila.user.User) = def make(user: lila.user.User) =
AccessToken( AccessToken(
id = AccessToken.makeId, id = AccessToken.Id.random(),
publicId = BSONObjectID.generate(), publicId = BSONObjectID.generate(),
clientId = PersonalToken.clientId, clientId = PersonalToken.clientId,
userId = user.id, userId = user.id,

View File

@ -10,23 +10,12 @@ import io.lemonlabs.uri.AbsoluteUrl
import lila.common.SecureRandom import lila.common.SecureRandom
object Protocol { object Protocol {
case class Secret(value: String) { case class AuthorizationCode(secret: String) extends AnyVal {
def hashed: String = Algo.sha256(value).hex def hashed = Algo.sha256(secret).hex
override def toString = "Secret(***)" override def toString = "AuthorizationCode(***)"
override def equals(other: Any) = other match {
case other: Secret => hashed == other.hashed
case _ => false
}
override def hashCode = hashed.hashCode()
} }
object Secret {
def random(prefix: String) = Secret(s"$prefix${SecureRandom.nextString(32)}")
}
case class AuthorizationCode(secret: Secret) extends AnyVal
object AuthorizationCode { object AuthorizationCode {
def apply(value: String): AuthorizationCode = AuthorizationCode(Secret(value)) def random() = AuthorizationCode(s"liu_${SecureRandom.nextString(32)}")
def random() = AuthorizationCode(Secret.random("liu_"))
} }
case class ClientId(value: String) extends AnyVal case class ClientId(value: String) extends AnyVal
@ -51,6 +40,13 @@ object Protocol {
Base64.getUrlEncoder().withoutPadding().encodeToString(Algo.sha256(value).bytes) Base64.getUrlEncoder().withoutPadding().encodeToString(Algo.sha256(value).bytes)
) )
} }
object CodeVerifier {
def from(value: String): Validated[Error, CodeVerifier] =
Validated
.valid(value)
.ensure(Error.CodeVerifierTooShort)(_.size >= 43)
.map(CodeVerifier.apply)
}
case class ResponseType() case class ResponseType()
object ResponseType { object ResponseType {
@ -84,7 +80,7 @@ object Protocol {
def code(code: AuthorizationCode, state: Option[State]): String = value def code(code: AuthorizationCode, state: Option[State]): String = value
.withQueryString( .withQueryString(
"code" -> Some(code.secret.value), "code" -> Some(code.secret),
"state" -> state.map(_.value) "state" -> state.map(_.value)
) )
.toString .toString
@ -129,13 +125,14 @@ object Protocol {
case object RedirectUriRequired extends InvalidRequest("redirect_uri required") case object RedirectUriRequired extends InvalidRequest("redirect_uri required")
case object RedirectUriInvalid extends InvalidRequest("redirect_uri invalid") case object RedirectUriInvalid extends InvalidRequest("redirect_uri invalid")
case object RedirectSchemeNotAllowed case object RedirectSchemeNotAllowed
extends InvalidRequest("contact us to get exotic redirect_uri schemes whitelisted") extends InvalidRequest("open a github issue to get exotic redirect_uri schemes whitelisted")
case object ResponseTypeRequired extends InvalidRequest("response_type required") case object ResponseTypeRequired extends InvalidRequest("response_type required")
case object CodeChallengeRequired extends InvalidRequest("code_challenge required") case object CodeChallengeRequired extends InvalidRequest("code_challenge required")
case object CodeChallengeMethodRequired extends InvalidRequest("code_challenge_method required") case object CodeChallengeMethodRequired extends InvalidRequest("code_challenge_method required")
case object GrantTypeRequired extends InvalidRequest("grant_type required") case object GrantTypeRequired extends InvalidRequest("grant_type required")
case object CodeRequired extends InvalidRequest("code required") case object CodeRequired extends InvalidRequest("code required")
case object CodeVerifierRequired extends InvalidRequest("code_verifier required") case object CodeVerifierRequired extends InvalidRequest("code_verifier required")
case object CodeVerifierTooShort extends InvalidRequest("code_verifier too short")
case class InvalidScope(val key: String) extends Error("invalid_scope") { case class InvalidScope(val key: String) extends Error("invalid_scope") {
def description = s"invalid scope: ${URLEncoder.encode(key, "UTF-8")}" def description = s"invalid scope: ${URLEncoder.encode(key, "UTF-8")}"

View File

@ -39,7 +39,7 @@ final class RacerApi(colls: RacerColls, selector: StormSelector, userRepo: UserR
.make( .make(
owner = player, owner = player,
puzzles = puzzles.grouped(2).flatMap(_.headOption).toList, puzzles = puzzles.grouped(2).flatMap(_.headOption).toList,
countdownSeconds = 10 countdownSeconds = 5
) )
store.put(race.id, race) store.put(race.id, race)
lila.mon.racer.race(lobby = race.isLobby).increment() lila.mon.racer.race(lobby = race.isLobby).increment()
@ -69,18 +69,23 @@ final class RacerApi(colls: RacerColls, selector: StormSelector, userRepo: UserR
def join(id: RacerRace.Id, player: RacerPlayer.Id): Option[RacerRace] = def join(id: RacerRace.Id, player: RacerPlayer.Id): Option[RacerRace] =
get(id).flatMap(_ join player) map { r => get(id).flatMap(_ join player) map { r =>
val race = start(r) | r val race = (r.isLobby ?? doStart(r)) | r
saveAndPublish(race) saveAndPublish(race)
race race
} }
private def start(race: RacerRace): Option[RacerRace] = race.startCountdown.map { starting => private[racer] def manualStart(race: RacerRace): Unit = !race.isLobby ?? {
system.scheduler.scheduleOnce(RacerRace.duration.seconds + race.countdownSeconds.seconds + 50.millis) { doStart(race) foreach saveAndPublish
finish(race.id)
}
starting
} }
private def doStart(race: RacerRace): Option[RacerRace] =
race.startCountdown.map { starting =>
system.scheduler.scheduleOnce(RacerRace.duration.seconds + race.countdownSeconds.seconds + 50.millis) {
finish(race.id)
}
starting
}
private def finish(id: RacerRace.Id): Unit = private def finish(id: RacerRace.Id): Unit =
get(id) foreach { race => get(id) foreach { race =>
lila.mon.racer.players(lobby = race.isLobby).record(race.players.size) lila.mon.racer.players(lobby = race.isLobby).record(race.players.size)

View File

@ -27,7 +27,8 @@ final class RacerJson(stormJson: StormJson, sign: StormSign, lightUserSync: Ligh
.add("lobby", race.isLobby), .add("lobby", race.isLobby),
"player" -> player, "player" -> player,
"puzzles" -> race.puzzles "puzzles" -> race.puzzles
) ++ state(race) )
.add("owner", race.owner == player.id) ++ state(race)
// socket updates // socket updates
def state(race: RacerRace) = Json def state(race: RacerRace) = Json

View File

@ -1,5 +1,6 @@
package lila.racer package lila.racer
import lila.room.RoomSocket.{ Protocol => RP, _ } import lila.room.RoomSocket.{ Protocol => RP, _ }
import lila.socket.RemoteSocket.{ Protocol => P, _ } import lila.socket.RemoteSocket.{ Protocol => P, _ }
import play.api.libs.json.{ JsObject, Json } import play.api.libs.json.{ JsObject, Json }
@ -28,6 +29,12 @@ final private class RacerSocket(
api.join(raceId, playerId).unit api.join(raceId, playerId).unit
case Protocol.In.PlayerScore(raceId, playerId, score) => case Protocol.In.PlayerScore(raceId, playerId, score) =>
api.registerPlayerScore(raceId, playerId, score) api.registerPlayerScore(raceId, playerId, score)
case Protocol.In.RaceStart(raceId, playerId) =>
api
.get(raceId)
.filter(_.startsAt.isEmpty)
.filter(_.owner == playerId)
.foreach(api.manualStart)
} }
remoteSocketApi.subscribe("racer-in", Protocol.In.reader)( remoteSocketApi.subscribe("racer-in", Protocol.In.reader)(
@ -45,6 +52,7 @@ object RacerSocket {
case class PlayerJoin(race: RacerRace.Id, player: RacerPlayer.Id) extends P.In case class PlayerJoin(race: RacerRace.Id, player: RacerPlayer.Id) extends P.In
case class PlayerScore(race: RacerRace.Id, player: RacerPlayer.Id, score: Int) extends P.In case class PlayerScore(race: RacerRace.Id, player: RacerPlayer.Id, score: Int) extends P.In
case class RaceStart(race: RacerRace.Id, player: RacerPlayer.Id) extends P.In
val reader: P.In.Reader = raw => raceReader(raw) orElse RP.In.reader(raw) val reader: P.In.Reader = raw => raceReader(raw) orElse RP.In.reader(raw)
@ -58,6 +66,10 @@ object RacerSocket {
raw.get(3) { case Array(raceId, playerId, scoreStr) => raw.get(3) { case Array(raceId, playerId, scoreStr) =>
scoreStr.toIntOption map { PlayerScore(RacerRace.Id(raceId), RacerPlayer.Id(playerId), _) } scoreStr.toIntOption map { PlayerScore(RacerRace.Id(raceId), RacerPlayer.Id(playerId), _) }
} }
case "racer/start" =>
raw.get(2) { case Array(raceId, playerId) =>
RaceStart(RacerRace.Id(raceId), RacerPlayer.Id(playerId)).some
}
case _ => none case _ => none
} }
} }

View File

@ -6,7 +6,14 @@ import scala.concurrent.duration._
final class RelayMarkup { final class RelayMarkup {
private val renderer = new lila.common.Markdown(autoLink = true) private val renderer =
new lila.common.Markdown(
autoLink = true,
list = true,
table = true,
strikeThrough = true,
header = true
)
private val cache: LoadingCache[String, String] = lila.memo.CacheApi.scaffeineNoScheduler private val cache: LoadingCache[String, String] = lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterAccess(20 minutes) .expireAfterAccess(20 minutes)

View File

@ -22,7 +22,7 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
val normalize = User normalize _ val normalize = User normalize _
def topNbGame(nb: Int): Fu[List[User]] = def topNbGame(nb: Int): Fu[List[User]] =
coll.find(enabledSelect).sort($sort desc "count.game").cursor[User]().list(nb) coll.find(enabledNoBotSelect).sort($sort desc "count.game").cursor[User]().list(nb)
def byId(id: ID): Fu[Option[User]] = User.noGhost(id) ?? coll.byId[User](id) def byId(id: ID): Fu[Option[User]] = User.noGhost(id) ?? coll.byId[User](id)
@ -277,6 +277,7 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
$doc(F.marks -> UserMark.Boost.key), $doc(F.marks -> UserMark.Boost.key),
$doc(F.marks -> UserMark.Troll.key) $doc(F.marks -> UserMark.Troll.key)
) )
val enabledNoBotSelect = enabledSelect ++ $doc(F.title $ne Title.BOT)
def stablePerfSelect(perf: String) = def stablePerfSelect(perf: String) =
$doc(s"perfs.$perf.gl.d" -> $lt(lila.rating.Glicko.provisionalDeviation)) $doc(s"perfs.$perf.gl.d" -> $lt(lila.rating.Glicko.provisionalDeviation))
val patronSelect = $doc(s"${F.plan}.active" -> true) val patronSelect = $doc(s"${F.plan}.active" -> true)

View File

@ -8,7 +8,7 @@ object Dependencies {
val scalalib = "com.github.ornicar" %% "scalalib" % "7.0.2" val scalalib = "com.github.ornicar" %% "scalalib" % "7.0.2"
val hasher = "com.roundeights" %% "hasher" % "1.2.1" val hasher = "com.roundeights" %% "hasher" % "1.2.1"
val jodaTime = "joda-time" % "joda-time" % "2.10.10" val jodaTime = "joda-time" % "joda-time" % "2.10.10"
val chess = "org.lichess" %% "scalachess" % "10.2.2" val chess = "org.lichess" %% "scalachess" % "10.2.4"
val compression = "org.lichess" %% "compression" % "1.6" val compression = "org.lichess" %% "compression" % "1.6"
val maxmind = "com.sanoma.cda" %% "maxmind-geoip2-scala" % "1.3.1-THIB" val maxmind = "com.sanoma.cda" %% "maxmind-geoip2-scala" % "1.3.1-THIB"
val prismic = "io.prismic" %% "scala-kit" % "1.2.19-THIB213" val prismic = "io.prismic" %% "scala-kit" % "1.2.19-THIB213"
@ -22,7 +22,7 @@ object Dependencies {
val autoconfig = "io.methvin.play" %% "autoconfig-macros" % "0.3.2" % "provided" val autoconfig = "io.methvin.play" %% "autoconfig-macros" % "0.3.2" % "provided"
val scalatest = "org.scalatest" %% "scalatest" % "3.1.0" % Test val scalatest = "org.scalatest" %% "scalatest" % "3.1.0" % Test
val uaparser = "org.uaparser" %% "uap-scala" % "0.13.0" val uaparser = "org.uaparser" %% "uap-scala" % "0.13.0"
val specs2 = "org.specs2" %% "specs2-core" % "4.12.1" % Test val specs2 = "org.specs2" %% "specs2-core" % "4.12.2" % Test
val apacheText = "org.apache.commons" % "commons-text" % "1.9" val apacheText = "org.apache.commons" % "commons-text" % "1.9"
val bloomFilter = "com.github.alexandrnikitin" %% "bloom-filter" % "0.13.1" val bloomFilter = "com.github.alexandrnikitin" %% "bloom-filter" % "0.13.1"

View File

@ -91,7 +91,7 @@ lichess.advantageChart = function (data, trans, el) {
events: { events: {
click: function (event) { click: function (event) {
if (event.point) { if (event.point) {
event.point.select(); event.point.select(true);
lichess.pubsub.emit('analysis.chart.click', event.point.x); lichess.pubsub.emit('analysis.chart.click', event.point.x);
} }
}, },

View File

@ -27,12 +27,12 @@
<item quantity="other">Spillede %1$s træk</item> <item quantity="other">Spillede %1$s træk</item>
</plurals> </plurals>
<plurals name="inNbCorrespondenceGames"> <plurals name="inNbCorrespondenceGames">
<item quantity="one">i %1$s korrespondance-spil</item> <item quantity="one">i %1$s korrespondanceparti</item>
<item quantity="other">i %1$s korrespondance-spil</item> <item quantity="other">i %1$s korrespondancepartier</item>
</plurals> </plurals>
<plurals name="completedNbGames"> <plurals name="completedNbGames">
<item quantity="one">Afsluttede %s korrespondancespil</item> <item quantity="one">Afsluttede %s korrespondanceparti</item>
<item quantity="other">Afsluttede %s korrespondancespil</item> <item quantity="other">Afsluttede %s korrespondancepartier</item>
</plurals> </plurals>
<plurals name="followedNbPlayers"> <plurals name="followedNbPlayers">
<item quantity="one">Begyndte at følge %s spiller</item> <item quantity="one">Begyndte at følge %s spiller</item>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="activity">Verlauf</string> <string name="activity">Verlauf</string>
<string name="hostedALiveStream">Hät en livestream gmacht</string> <string name="hostedALiveStream">Hät en liveschtriim gmacht</string>
<plurals name="supportedNbMonths"> <plurals name="supportedNbMonths">
<item quantity="one">Unterstützt lichess.org sit %1$s Monät als %2$s</item> <item quantity="one">Unterstützt lichess.org sit %1$s Monät als %2$s</item>
<item quantity="other">Unterstützt lichess.org seit %1$s Monaten als %2$s</item> <item quantity="other">Unterstützt lichess.org seit %1$s Monaten als %2$s</item>

View File

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="activity">Գործունեություն</string> <string name="activity">Գործունեություն</string>
<plurals name="competedInNbTournaments">
<item quantity="one">Ավարտված է %s «Արենա» մրցաշարը</item>
<item quantity="other">Ավարտված են %s «Արենա» մրցաշարերը</item>
</plurals>
</resources> </resources>

View File

@ -43,4 +43,10 @@
<item quantity="one">Вижте отбора</item> <item quantity="one">Вижте отбора</item>
<item quantity="other">Вижте всички %s отбора</item> <item quantity="other">Вижте всички %s отбора</item>
</plurals> </plurals>
<string name="newTeamBattle">Нова отборна битка</string>
<string name="customStartDate">Начална дата</string>
<string name="allowBerserk">Позволи Берсерк</string>
<string name="allowChatHelp">Позволи на играчите да обсъждат в чата</string>
<string name="arenaStreaks">Последователности в арената</string>
<string name="arenaStreaksHelp">След 2 победи, всяка последователна победа носи 4 точки вместо 2.</string>
</resources> </resources>

View File

@ -41,4 +41,6 @@ Juga ràpid i torna al vestíbul per jugar més partits i guanyar més punts.</s
<item quantity="one">Veure l\'equip</item> <item quantity="one">Veure l\'equip</item>
<item quantity="other">Veure els %s equips</item> <item quantity="other">Veure els %s equips</item>
</plurals> </plurals>
<string name="newTeamBattle">Nova batalla d\'equips</string>
<string name="allowBerserk">Es permet Berserk</string>
</resources> </resources>

View File

@ -24,7 +24,7 @@ Bersærk giver kun ekstra point, hvis du laver mindst 7 træk i partiet.</string
<string name="howIsTheWinnerDecided">Hvordan findes vinderen?</string> <string name="howIsTheWinnerDecided">Hvordan findes vinderen?</string>
<string name="howIsTheWinnerDecidedAnswer">Spilleren (eller spillerne) med flest point, når turneringens fastsatte tidsgrænse nås, erklæres for vinder(e).</string> <string name="howIsTheWinnerDecidedAnswer">Spilleren (eller spillerne) med flest point, når turneringens fastsatte tidsgrænse nås, erklæres for vinder(e).</string>
<string name="howDoesPairingWork">Hvordan foretages pardannelse?</string> <string name="howDoesPairingWork">Hvordan foretages pardannelse?</string>
<string name="howDoesPairingWorkAnswer">Ved starten på turneringen parres spillere på baggrund af deres rating. Vend tilbage til turneringslobbyen, når du afslutter et parti: så vil du igen blive parret med en spiller tæt på din score. Det sikrer minimal ventetid, men du møder måske ikke alle andre deltagere i turneringen. <string name="howDoesPairingWorkAnswer">Ved starten på turneringen parres spillere på baggrund af deres rating. Vend tilbage til turneringslobbyen, når du afslutter et parti: så vil du igen blive parret med en spiller tæt på din ranking. Det sikrer minimal ventetid, men du møder måske ikke alle andre deltagere i turneringen.
Spil hurtigt og vend tilbage til lobbyen for at spille flere partier og vinde flere point.</string> Spil hurtigt og vend tilbage til lobbyen for at spille flere partier og vinde flere point.</string>
<string name="howDoesItEnd">Hvordan afsluttes det?</string> <string name="howDoesItEnd">Hvordan afsluttes det?</string>
<string name="howDoesItEndAnswer">Turneringen har et nedtællingsur. Når det rammer nul fastfryses turneringsplaceringer, og en vinder kåres. Igangværende partier skal spilles færdig, men de tæller ikke med i turneringen.</string> <string name="howDoesItEndAnswer">Turneringen har et nedtællingsur. Når det rammer nul fastfryses turneringsplaceringer, og en vinder kåres. Igangværende partier skal spilles færdig, men de tæller ikke med i turneringen.</string>
@ -42,4 +42,12 @@ Spil hurtigt og vend tilbage til lobbyen for at spille flere partier og vinde fl
<item quantity="one">Se holdet</item> <item quantity="one">Se holdet</item>
<item quantity="other">Se alle %s hold</item> <item quantity="other">Se alle %s hold</item>
</plurals> </plurals>
<string name="newTeamBattle">Ny holdkamp</string>
<string name="customStartDate">Tilpasset startdato</string>
<string name="customStartDateHelp">I din egen lokale tidszone. Dette tilsidesætter \"Tid før turnering starter\" indstillingen</string>
<string name="allowBerserk">Tillad Berserk</string>
<string name="allowBerserkHelp">Lad spillerne halvere deres tid på uret for at få et ekstra point</string>
<string name="allowChatHelp">Lad spillere diskutere i et chatrum</string>
<string name="arenaStreaks">Arena-stime</string>
<string name="arenaStreaksHelp">Efter 2 sejre giver fortløbende sejre 4 point i stedet for 2.</string>
</resources> </resources>

View File

@ -29,8 +29,7 @@ Wenn zwei oder meh Schpiller/-innä di gliich Punktzahl bsitzäd, entscheidät d
Sobald du es Schpiil beändät häsch, chasch du zur Turnierübersicht zrugggoh. Dir wird dänn än Schpiller/ ä Schpillerin mit ähnlichäm Rang zuäteilt. So wird ä churzi Warteziit erreicht, allerdings cha passiärä, dass du nöd geg alli anderä Schpiller/-innä im Turnier spillsch. Sobald du es Schpiil beändät häsch, chasch du zur Turnierübersicht zrugggoh. Dir wird dänn än Schpiller/ ä Schpillerin mit ähnlichäm Rang zuäteilt. So wird ä churzi Warteziit erreicht, allerdings cha passiärä, dass du nöd geg alli anderä Schpiller/-innä im Turnier spillsch.
Prässiär und gohn zur Turnierübersicht zrugg, zum meh Schpiil z\'schpilä und ä höcheri Punktzahl z\'erziilä.</string> Prässiär und gohn zur Turnierübersicht zrugg, zum meh Schpiil z\'schpilä und ä höcheri Punktzahl z\'erziilä.</string>
<string name="howDoesItEnd">Wänn ändät äsTurnier?</string> <string name="howDoesItEnd">Wänn ändät äsTurnier?</string>
<string name="howDoesItEndAnswer">WährendmäTurnier wird d\'Ziit abäzellt. Wenn si null erreicht, wird d\'Ranglischte iigfrorä und dä Gwünner bekanntgeh. <string name="howDoesItEndAnswer">WährendmäTurnier wird d\'Ziit abäzellt. Wenn si null erreicht, wird d\'Ranglischte iigfrorä und dä Gwünner bekanntgeh. Laufendi Partiä münd beändä wärdä, zelläd aber nümä für das Turnier.</string>
Laufendi Partiä münd beändä wärdä, zelläd aber nümä für das Turnier.</string>
<string name="otherRules">Anderi wichtigi Reglä</string> <string name="otherRules">Anderi wichtigi Reglä</string>
<string name="thereIsACountdown">Es git en Countdown für din erschtä Zug. Züchsch du nöd innerhalb vo därä Zit, wird dä Siig dim Gegner zuegsprochä. Usserdem bechömäd Zürcher immer ein Punkt Abzug.</string> <string name="thereIsACountdown">Es git en Countdown für din erschtä Zug. Züchsch du nöd innerhalb vo därä Zit, wird dä Siig dim Gegner zuegsprochä. Usserdem bechömäd Zürcher immer ein Punkt Abzug.</string>
<plurals name="drawingWithinNbMoves"> <plurals name="drawingWithinNbMoves">
@ -45,4 +44,12 @@ Laufendi Partiä münd beändä wärdä, zelläd aber nümä für das Turnier.</
<item quantity="one">Das Team ansehen</item> <item quantity="one">Das Team ansehen</item>
<item quantity="other">Alli %s Teams aluägä</item> <item quantity="other">Alli %s Teams aluägä</item>
</plurals> </plurals>
<string name="newTeamBattle">Neuer Teamkampf</string>
<string name="customStartDate">Benutzerdefiniertes Startdatum</string>
<string name="customStartDateHelp">In deiner eigenen, lokalen Zeitzone. Dies wird die Einstellung \"Zeit bevor das Turnier beginnt\" überschreiben</string>
<string name="allowBerserk">Berserk erlauben</string>
<string name="allowBerserkHelp">Lasse Spieler ihre Bedenkzeit halbieren, um einen zusätzlichen Punkt zu erzielen</string>
<string name="allowChatHelp">Lasse Spieler in einem Chatraum diskutieren</string>
<string name="arenaStreaks">Arena-Siegesserien</string>
<string name="arenaStreaksHelp">Nach 2 Siegen gewähren aufeinander folgende Siege 4 Punkte anstelle von 2.</string>
</resources> </resources>

View File

@ -29,8 +29,7 @@ Wenn zwei oder mehr Spieler die gleiche Punktzahl besitzen, entscheidet die Turn
Sobald du ein Spiel beendet hast, kannst du zur Turnierübersicht zurückkehren. Dir wird dann ein Spieler mit ähnlichem Rang zugeteilt. Dadurch wird eine kurze Wartezeit erreicht, allerdings kann es sein, dass du nicht gegen alle anderen Spieler in diesem Turnier spielen wirst. Sobald du ein Spiel beendet hast, kannst du zur Turnierübersicht zurückkehren. Dir wird dann ein Spieler mit ähnlichem Rang zugeteilt. Dadurch wird eine kurze Wartezeit erreicht, allerdings kann es sein, dass du nicht gegen alle anderen Spieler in diesem Turnier spielen wirst.
Spiele schnell und kehre zur Turnierübersicht zurück, um mehr Spiele zu spielen und eine höhere Punktzahl zu erzielen.</string> Spiele schnell und kehre zur Turnierübersicht zurück, um mehr Spiele zu spielen und eine höhere Punktzahl zu erzielen.</string>
<string name="howDoesItEnd">Wann endet das Turnier?</string> <string name="howDoesItEnd">Wann endet das Turnier?</string>
<string name="howDoesItEndAnswer">Während des Turniers wird die Zeit heruntergezählt. Wenn sie null erreicht, wird die Rangliste eingefroren und der Gewinner bekanntgegeben. <string name="howDoesItEndAnswer">Während des Turniers wird die Zeit heruntergezählt. Wenn sie null erreicht, wird die Rangliste eingefroren und der Gewinner bekanntgegeben. Laufende Partien müssen beendet werden, zählen aber nicht mehr für das Turnier.</string>
Laufende Partien müssen beendet werden, zählen aber nicht mehr für das Turnier.</string>
<string name="otherRules">Andere wichtige Regeln</string> <string name="otherRules">Andere wichtige Regeln</string>
<string name="thereIsACountdown">Es gibt einen Countdown für deinen ersten Zug. Ziehst du nicht innerhalb dieser Zeit, wird der Sieg deinem Gegner zugesprochen.</string> <string name="thereIsACountdown">Es gibt einen Countdown für deinen ersten Zug. Ziehst du nicht innerhalb dieser Zeit, wird der Sieg deinem Gegner zugesprochen.</string>
<plurals name="drawingWithinNbMoves"> <plurals name="drawingWithinNbMoves">
@ -45,4 +44,12 @@ Laufende Partien müssen beendet werden, zählen aber nicht mehr für das Turnie
<item quantity="one">Das Team ansehen</item> <item quantity="one">Das Team ansehen</item>
<item quantity="other">Alle %s Teams ansehen</item> <item quantity="other">Alle %s Teams ansehen</item>
</plurals> </plurals>
<string name="newTeamBattle">Neuer Teamkampf</string>
<string name="customStartDate">Benutzerdefiniertes Startdatum</string>
<string name="customStartDateHelp">In deiner eigenen, lokalen Zeitzone. Dies wird die Einstellung \"Zeit bevor das Turnier beginnt\" überschreiben</string>
<string name="allowBerserk">Berserk erlauben</string>
<string name="allowBerserkHelp">Lasse Spieler ihre Bedenkzeit halbieren, um einen zusätzlichen Punkt zu erzielen</string>
<string name="allowChatHelp">Lasse Spieler in einem Chatraum diskutieren</string>
<string name="arenaStreaks">Arena-Siegesserien</string>
<string name="arenaStreaksHelp">Nach 2 Siegen gewähren aufeinander folgende Siege 4 Punkte anstelle von 2.</string>
</resources> </resources>

View File

@ -44,4 +44,12 @@ To Berserk δεν ισχύει για παρτίδες με μηδενικό α
<item quantity="one">Δείτε την ομάδα</item> <item quantity="one">Δείτε την ομάδα</item>
<item quantity="other">Δείτε όλες τις %s ομάδες</item> <item quantity="other">Δείτε όλες τις %s ομάδες</item>
</plurals> </plurals>
<string name="newTeamBattle">Νέα ομαδική μάχη</string>
<string name="customStartDate">Προσαρμοσμένη ημερομηνία έναρξης</string>
<string name="customStartDateHelp">Στην τοπική ζώνη ώρας σας. Αυτό υπερισχύει της ρύθμισης \"Χρόνος προτού ξεκινήσει το πρωτάθλημα\"</string>
<string name="allowBerserk">Να επιτρέπεται το Berserk</string>
<string name="allowBerserkHelp">Να επιτρέπεται στους παίκτες να μειώσουν τον χρόνο στο ρολόι τους κατά το ήμισυ για να κερδίσουν έναν επιπλέον πόντο</string>
<string name="allowChatHelp">Να επιτρέπεται στους παίκτες να συζητούν σε δωμάτιο συνομιλίας</string>
<string name="arenaStreaks">Arena streaks</string>
<string name="arenaStreaksHelp">Μετά από 2 νίκες, επιπλέον διαδοχικές νίκες σας 4 πόντους αντί για 2.</string>
</resources> </resources>

View File

@ -45,4 +45,12 @@ Play fast and return to the lobby to play more games and win more points.</strin
<item quantity="one">View the team</item> <item quantity="one">View the team</item>
<item quantity="other">View all %s teams</item> <item quantity="other">View all %s teams</item>
</plurals> </plurals>
<string name="newTeamBattle">New Team Battle</string>
<string name="customStartDate">Custom start date</string>
<string name="customStartDateHelp">In your own local timezone. This overrides the \"Time before tournament starts\" setting</string>
<string name="allowBerserk">Allow Berserk</string>
<string name="allowBerserkHelp">Let players halve their clock time to gain an extra point</string>
<string name="allowChatHelp">Let players discuss in a chat room</string>
<string name="arenaStreaks">Arena streaks</string>
<string name="arenaStreaksHelp">After 2 wins, consecutive wins grant 4 points instead of 2.</string>
</resources> </resources>

View File

@ -44,4 +44,12 @@ Juega rápido y vuelve al recibidor para jugar más partidas y ganar más puntos
<item quantity="one">Ver equipo</item> <item quantity="one">Ver equipo</item>
<item quantity="other">Ver los %s equipos</item> <item quantity="other">Ver los %s equipos</item>
</plurals> </plurals>
<string name="newTeamBattle">Nueva batalla de equipo</string>
<string name="customStartDate">Fecha de inicio personalizada</string>
<string name="customStartDateHelp">En tu propia zona horaria local. Esto reemplaza la configuración de «Tiempo antes de que comience el torneo».</string>
<string name="allowBerserk">Permitir Berserk</string>
<string name="allowBerserkHelp">Permite a los jugadores reducir el tiempo de la partida a la mitad para ganar un punto extra</string>
<string name="allowChatHelp">Permite a los jugadores comunicarse en una sala de chat</string>
<string name="arenaStreaks">Rachas de torneos</string>
<string name="arenaStreaksHelp">Después de ganar 2 partidas seguidas, cada victoria consecutiva concede 4 puntos en lugar de 2.</string>
</resources> </resources>

View File

@ -43,4 +43,12 @@ Jokatu azkar, itzuli egongelara partida gehiago jokatu eta puntu gehiago irabazt
<item quantity="one">Taldea ikusi</item> <item quantity="one">Taldea ikusi</item>
<item quantity="other">%s taldeak ikusi</item> <item quantity="other">%s taldeak ikusi</item>
</plurals> </plurals>
<string name="newTeamBattle">Taldeen Arteko Txapelketa berria</string>
<string name="customStartDate">Pertsonalizatutako hasiera data</string>
<string name="customStartDateHelp">Zure ordu-zonan. Honek \"Txapeketa hasi aurreko denbora\" ezarpena gainidazten du</string>
<string name="allowBerserk">Berserk onartu</string>
<string name="allowBerserkHelp">Utzi jokalariei beren denbora erdira jaisten puntu gehigarri bat lortzeko</string>
<string name="allowChatHelp">Utzi jokalariei txatean hitz egiten</string>
<string name="arenaStreaks">Arena boladak</string>
<string name="arenaStreaksHelp">Bi garaipenen ostean, jarraian datozen garaipenek 4 puntu emango dituzte 2 eman beharrean.</string>
</resources> </resources>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="arenaTournaments">مسابقات</string>
<string name="isItRated">آیا رسمی است؟</string> <string name="isItRated">آیا رسمی است؟</string>
<string name="willBeNotified">هنگام شروع تورنومنت به شما اطلاع داده خواهد شد، پس در زمان انتظار بازی کردن در تب های دیگر بلامانع است.</string> <string name="willBeNotified">هنگام شروع تورنومنت به شما اطلاع داده خواهد شد، پس در زمان انتظار بازی کردن در تب های دیگر بلامانع است.</string>
<string name="isRated">این تورنومنت رسمی است و بر روی ریتینگ شما تاثیر میگذارد.</string> <string name="isRated">این تورنومنت رسمی است و بر روی ریتینگ شما تاثیر میگذارد.</string>
@ -25,10 +26,17 @@
<string name="howDoesPairingWorkAnswer">در ابتدای تورنومنت، بازیکنان با توجه به امتیازهایشان با یکدیگر روبه رو میشوند. <string name="howDoesPairingWorkAnswer">در ابتدای تورنومنت، بازیکنان با توجه به امتیازهایشان با یکدیگر روبه رو میشوند.
به محض اینکه شما بازی را تمام کردید و به لابی تورنومنت برگردید: شما به بازیکنی که رتبه نزدیک تری به شما دارد متصل میشوید. این مکانیزم در حداقل زمان ممکن انجام میشود، هرچند امکان دارد با همه بازیکنان تورنومنت روبه رو نشوید. به محض اینکه شما بازی را تمام کردید و به لابی تورنومنت برگردید: شما به بازیکنی که رتبه نزدیک تری به شما دارد متصل میشوید. این مکانیزم در حداقل زمان ممکن انجام میشود، هرچند امکان دارد با همه بازیکنان تورنومنت روبه رو نشوید.
سریع بازی کنید و به لابی برگردید تا بازی های بیشتری بازی کنید و امتیاز بیشتری بگیرید.</string> سریع بازی کنید و به لابی برگردید تا بازی های بیشتری بازی کنید و امتیاز بیشتری بگیرید.</string>
<string name="howDoesItEnd">چگونه پایان میابد؟</string> <string name="howDoesItEnd">چگونه به پایان می رسد؟</string>
<string name="howDoesItEndAnswer">تورنومنت یک ساعت شمارش معکوس دارد. وقتی به صفر برسد، رتبه بندی تورنومنت غیرقابل تغییر میشود، و برنده اعلام میشود. <string name="howDoesItEndAnswer">تورنومنت یک ساعت شمارش معکوس دارد. وقتی به صفر برسد، رتبه بندی تورنومنت غیرقابل تغییر میشود، و برنده اعلام میشود. بازی های در حال اجرا باید تمام شوند، هر چند نتیجه آن بازی ها تاثیری در تورنومنت ندارد.</string>
بازی های در حال اجرا باید تمام شوند، هر چند نتیجه آن بازی ها تاثیری در تورنومنت ندارد.</string>
<string name="otherRules">قوانین مهم دیگر</string> <string name="otherRules">قوانین مهم دیگر</string>
<string name="thisIsPrivate">این یک تورنومنت خصوصی است</string> <string name="thisIsPrivate">این یک تورنومنت خصوصی است</string>
<string name="shareUrl">این لینک را برای پیوستن دیگران به اشتراک بگذارید.%s</string> <string name="shareUrl">این لینک را برای پیوستن دیگران به اشتراک بگذارید.%s</string>
<string name="history">تاریخچه مسابقات</string>
<string name="newTeamBattle">مبارزه تیمی جدید</string>
<string name="customStartDate">تنظیم تاریخ شروع</string>
<string name="customStartDateHelp">در منطقه زمانی محلی خودتان. تنظیمات \"زمان قبل شروع شدن مسابقه\" را نادیده می گیرد</string>
<string name="allowBerserk">مجاز کردن برسرک</string>
<string name="allowBerserkHelp">به بازیکنان اجازه دهید تا زمان خود را نصف کنند تا یک امتیاز اضافی بگیرند</string>
<string name="allowChatHelp">اجازه دادن بحث به بازیکنان در چت روم</string>
<string name="arenaStreaksHelp">بعد از دو برد، بردهای پی در پی بجای 2 امتیاز 4 امتیاز می دهند.</string>
</resources> </resources>

View File

@ -43,4 +43,12 @@ Pelaa nopeasti ja palaa aulaan, niin voit pelata lisää pelejä ja ansaita lis
<item quantity="one">Näytä joukkue</item> <item quantity="one">Näytä joukkue</item>
<item quantity="other">Näytä kaikki %s joukkuetta</item> <item quantity="other">Näytä kaikki %s joukkuetta</item>
</plurals> </plurals>
<string name="newTeamBattle">Uusi joukkuetaisto</string>
<string name="customStartDate">Mukautettu alkamisaika</string>
<string name="customStartDateHelp">Omalla aikavyöhykkeelläsi. Tämä korvaa asetuksen \"Aika ennen turnauksen alkua\"</string>
<string name="allowBerserk">Salli berserkki</string>
<string name="allowBerserkHelp">Anna pelaajien puolittaa aika kellossaan ja tavoitella lisäpistettä</string>
<string name="allowChatHelp">Anna pelaajien kirjoittaa keskusteluhuoneeseen</string>
<string name="arenaStreaks">Areenaputket</string>
<string name="arenaStreaksHelp">Kahden voiton jälkeen jokaisesta seuraavasta voitosta saa 4 pistettä (2 pisteen sijaan).</string>
</resources> </resources>

View File

@ -42,4 +42,12 @@ Jouez vite et retournez à la page d\'accueil du tournoi pour jouer plus de part
<item quantity="one">Voir l\'équipe</item> <item quantity="one">Voir l\'équipe</item>
<item quantity="other">Voir toutes les équipes %s</item> <item quantity="other">Voir toutes les équipes %s</item>
</plurals> </plurals>
<string name="newTeamBattle">Nouveau combat en équipe</string>
<string name="customStartDate">Date de début modifiée</string>
<string name="customStartDateHelp">Selon votre fuseau horaire. Ce paramètre désactive le paramètre « Temps restant avant le début du tournoi ».</string>
<string name="allowBerserk">Activer l\'option Berserk</string>
<string name="allowBerserkHelp">Permettre aux joueurs de réduire de moitié leur temps pour gagner un point supplémentaire</string>
<string name="allowChatHelp">Permettre aux joueurs de clavarder dans le salon de discussion</string>
<string name="arenaStreaks">Série de victoires dans l\'arène</string>
<string name="arenaStreaksHelp">Après 2 victoires, des victoires consécutives donnent 4 points au lieu de 2.</string>
</resources> </resources>

View File

@ -51,4 +51,12 @@ Imir go tapa agus filleadh chuig an forhalla chun níos mó cluichí a imirt agu
<item quantity="many">Féach ar na %s foireann go léir</item> <item quantity="many">Féach ar na %s foireann go léir</item>
<item quantity="other">Féach ar na %s foireann go léir</item> <item quantity="other">Féach ar na %s foireann go léir</item>
</plurals> </plurals>
<string name="newTeamBattle">Cath Foirne Nua</string>
<string name="customStartDate">Dáta tosaigh saincheaptha</string>
<string name="customStartDateHelp">I do chrios ama áitiúil féin. Sáraíonn sé seo an socrú \"Am sula dtosaíonn an comórtas\"</string>
<string name="allowBerserk">Lig Berserk</string>
<string name="allowBerserkHelp">Lig dimreoirí a gcuid ama clog a laghdú chun pointe breise a fháil</string>
<string name="allowChatHelp">Lig dimreoirí plé a dhéanamh i seomra comhrá</string>
<string name="arenaStreaks">Sruthanna airéine</string>
<string name="arenaStreaksHelp">Tar éis 2 bhua, deonaíonn 4 bhua as a chéile 4 phointe in ionad 2.</string>
</resources> </resources>

View File

@ -43,4 +43,12 @@ Xoga rápido e volta ao lobby para xogar máis partidas e gañar máis puntos.</
<item quantity="one">Ver o equipo</item> <item quantity="one">Ver o equipo</item>
<item quantity="other">Ver todos os %s equipos</item> <item quantity="other">Ver todos os %s equipos</item>
</plurals> </plurals>
<string name="newTeamBattle">Nova batalla por equipos</string>
<string name="customStartDate">Fecha de comezo persoalizada</string>
<string name="customStartDateHelp">Na túa zona de tempo local. Isto sobreescribe a preferencia \"Tempo antes de que o torneo comece\"</string>
<string name="allowBerserk">Berserk permitido</string>
<string name="allowBerserkHelp">Deixa ás xogadoras que reduzan á metade o seu tempo para gañar un ponto extra</string>
<string name="allowChatHelp">Deixa ás xogadoras falar nunha sala de chat</string>
<string name="arenaStreaks">Racha de victorias no Torneo</string>
<string name="arenaStreaksHelp">Despois de 2 victorias, as seguintes victorias consecutivas dan 4 pontos en lugar de 2.</string>
</resources> </resources>

View File

@ -43,4 +43,12 @@ Játssz gyorsan, térj vissza a lobbiba további játszmákért, hogy több pont
<item quantity="one">Csapat megtekintése</item> <item quantity="one">Csapat megtekintése</item>
<item quantity="other">Mind a %s csapat megtekintése</item> <item quantity="other">Mind a %s csapat megtekintése</item>
</plurals> </plurals>
<string name="newTeamBattle">Új csapatverseny</string>
<string name="customStartDate">Kezdés időpontja</string>
<string name="customStartDateHelp">Saját időzóna szerint. Ez felülbírálja a \"Hátralévő idő a verseny kezdetéig\" beállítást</string>
<string name="allowBerserk">Berserk engedélyezése</string>
<string name="allowBerserkHelp">A játékosok saját idejük feléért cserébe többletpontot kapnak</string>
<string name="allowChatHelp">Chatszoba engedélyezése a játékosoknak</string>
<string name="arenaStreaks">Aréna sorozatok</string>
<string name="arenaStreaksHelp">A második nyert játszmát követően minden nyert játszma 4 pontot ér 2 helyett.</string>
</resources> </resources>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="arenaTournaments">«Արենա» մրցաշարեր</string>
<string name="isItRated">Գնահատված է?</string> <string name="isItRated">Գնահատված է?</string>
<string name="willBeNotified">Դուք կտեղեկացվեք մրցաշարի սկզբի մասին, այնպես որ հանգիստ սպասեք:</string> <string name="willBeNotified">Դուք կտեղեկացվեք մրցաշարի սկզբի մասին, այնպես որ հանգիստ սպասեք:</string>
<string name="isRated">Այս մրցաշարում վարկանիշի հաշվարկ կա, այնպես որ այն կազդի Ձեր վարկանիշի վրա:</string> <string name="isRated">Այս մրցաշարում վարկանիշի հաշվարկ կա, այնպես որ այն կազդի Ձեր վարկանիշի վրա:</string>
@ -26,4 +27,6 @@
<string name="howDoesPairingWorkAnswer">Մրցաշարի սկզբում զույգերը կազմվում են ըստ անհատական վարկանիշների: <string name="howDoesPairingWorkAnswer">Մրցաշարի սկզբում զույգերը կազմվում են ըստ անհատական վարկանիշների:
Խաղի ավարտից հետո սեղմեք &lt;&lt;դեպի մրցաշար&gt;&gt; հետ վերադարձի կոճակը, որից հետո Դուք կստանաք նոր մրցակից՝ ըստ Ձեր զբաղեցրած դիրքի: Վիճակահանությունը կտևի ոչ այդքան երկար, սակայն բոլորի հետ խաղալ չեք կարող, միայն Ձեր մոտակայքում գտնվող խաղացողներից կկազմվի զույգը: Խաղի ավարտից հետո սեղմեք &lt;&lt;դեպի մրցաշար&gt;&gt; հետ վերադարձի կոճակը, որից հետո Դուք կստանաք նոր մրցակից՝ ըստ Ձեր զբաղեցրած դիրքի: Վիճակահանությունը կտևի ոչ այդքան երկար, սակայն բոլորի հետ խաղալ չեք կարող, միայն Ձեր մոտակայքում գտնվող խաղացողներից կկազմվի զույգը:
Խաղացեք արագ և վերադարձեք մրցաշարի հիմնական էջ, որպեսզի խաղաք շատ խաղեր և հավաքեք շատ միավորներ:</string> Խաղացեք արագ և վերադարձեք մրցաշարի հիմնական էջ, որպեսզի խաղաք շատ խաղեր և հավաքեք շատ միավորներ:</string>
<string name="drawStreak">Ոչ-ոքիների շարք. եթե խաղացողը «Արենայում» ունի իրար հաջորդող մի քանի ոչ-ոքի, ապա միավոր է տրվում միայն առաջին ոչ-ոքիի համար, կամ այն ոչ-ոքիի համար, որը կտևի %s քայլից ավելի։ Ոչ-ոքիների շարքը կարելի է ընդհատել միայն հաղթանակով, բայց ոչ պարտությամբ կամ ևս մեկ ոչ-ոքիով։</string>
<string name="history">«Արենայի» պատմություն</string>
</resources> </resources>

View File

@ -28,4 +28,12 @@
<plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed"> <plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed">
<item quantity="other">Lihat semua %s tim</item> <item quantity="other">Lihat semua %s tim</item>
</plurals> </plurals>
<string name="newTeamBattle">Pertempuran Tim Baru</string>
<string name="customStartDate">Tanggal mulai khusus</string>
<string name="customStartDateHelp">Dalam zona waktu lokal Anda sendiri. Ini akan menimpa pengaturan \"Waktu sebelum turnamen dimulai\"</string>
<string name="allowBerserk">Izinkan Berserk</string>
<string name="allowBerserkHelp">Biarkan pemain memotong waktu jam mereka untuk mendapatkan sebuah poin ekstra</string>
<string name="allowChatHelp">Biarkan pemain berdiskusi dalam sebuah ruang obrol</string>
<string name="arenaStreaks">Streak arena</string>
<string name="arenaStreaksHelp">Setelah 2 kemenangan, secar berurutan akan mendapatkan 4 poin alih-alih 2.</string>
</resources> </resources>

View File

@ -35,4 +35,12 @@
<plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed"> <plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed">
<item quantity="other">%s チームを表示</item> <item quantity="other">%s チームを表示</item>
</plurals> </plurals>
<string name="newTeamBattle">新しいチームバトル</string>
<string name="customStartDate">開始日を指定</string>
<string name="customStartDateHelp">自分のタイムゾーンでの日時。これは「トーナメント開始時刻」の設定より優先されます。</string>
<string name="allowBerserk">バーサークあり</string>
<string name="allowBerserkHelp">持時間半減で 1 ポイントボーナスを認める</string>
<string name="allowChatHelp">チャットルームでの会話を認める</string>
<string name="arenaStreaks">連勝ボーナスあり</string>
<string name="arenaStreaksHelp">2 連勝すると以降の勝ちは 2 ではなく 4 ポイントになる。</string>
</resources> </resources>

View File

@ -43,4 +43,12 @@
<plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed"> <plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed">
<item quantity="other">모두 %s개 팀 보기</item> <item quantity="other">모두 %s개 팀 보기</item>
</plurals> </plurals>
<string name="newTeamBattle">새 팀 배틀</string>
<string name="customStartDate">시작시간 설정</string>
<string name="customStartDateHelp">당신의 현지 시간대입니다. \"토너먼트 시작까지 시간\" 설정을 덮어씁니다.</string>
<string name="allowBerserk">버서크 모드 허용</string>
<string name="allowBerserkHelp">플레이어는 자신의 시간을 절반으로 줄이며 대신 추가 승점을 얻습니다</string>
<string name="allowChatHelp">플레이어가 채팅방에서 토론할 수 있습니다</string>
<string name="arenaStreaks">아레나 연승</string>
<string name="arenaStreaksHelp">2승 이후 추가로 연승을 하면 2점이 아니라 4점을 얻습니다.</string>
</resources> </resources>

View File

@ -47,4 +47,12 @@ Kai tik baigiate partiją, grįžkite į turnyro laukiamąjį: tuomet būsite su
<item quantity="many">Peržvelgti visas %s komandų</item> <item quantity="many">Peržvelgti visas %s komandų</item>
<item quantity="other">Peržvelgti visas %s komandų</item> <item quantity="other">Peržvelgti visas %s komandų</item>
</plurals> </plurals>
<string name="newTeamBattle">Nauja komandinė kova</string>
<string name="customStartDate">Kita pradžios data</string>
<string name="customStartDateHelp">Jūsų laiko zonoje. Turi pirmenybę prieš \"Laikas iki turnyro pradžios\" nustatymą</string>
<string name="allowBerserk">Leisti \"įsiutį\"</string>
<string name="allowBerserkHelp">Leisti žaidėjams gauti tašką perpus sumažinant laiką ant savo laikrodžio</string>
<string name="allowChatHelp">Leisti žaidėjams kalbėtis pokalbių kambaryje</string>
<string name="arenaStreaks">Arenos serijos</string>
<string name="arenaStreaksHelp">Po dviejų pergalių kiti laimėjimai suteikia keturis taškus vietoje dviejų.</string>
</resources> </resources>

View File

@ -48,4 +48,12 @@ Spēlē ātri un atgriezies vestibilā lai spēlētu vairāk spēļu un iegūtu
<item quantity="one">Skatīt %s komandu</item> <item quantity="one">Skatīt %s komandu</item>
<item quantity="other">Skatīt visas %s komandas</item> <item quantity="other">Skatīt visas %s komandas</item>
</plurals> </plurals>
<string name="newTeamBattle">Jauna Komandas Kauja</string>
<string name="customStartDate">Pielāgots sākuma datums</string>
<string name="customStartDateHelp">Jūsu laika zonā. Šis aizstās iestatījumu \"Laiks līdz turnīra sākumam\"</string>
<string name="allowBerserk">Atļaut \"dullās\" spēles</string>
<string name="allowBerserkHelp">Ļaut spēlētājiem apmainīt pusi laika pret iespēju gūt papildpunktu</string>
<string name="allowChatHelp">Ļaut spēlētājiem izmantot sarunu istabu</string>
<string name="arenaStreaks">Arēnas uzvaru sērija</string>
<string name="arenaStreaksHelp">Pēc 2 uzvarām, secīgās uzvaras piešķirs 4 punktus nevis 2.</string>
</resources> </resources>

View File

@ -1,2 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="newTeamBattle">အသင်းအလိုက် တိုက်ပွဲ အသစ်</string>
<string name="customStartDate">ပြိုင်ပွဲ စတင်ရန် စိတ်ကြိုက် သတ်မှတ်သည့် နေ့ရက်</string>
<string name="customStartDateHelp">သင့် ဒေသန္တရ အချိန်ဇုံ အရ။ ဤသတ်မှတ်ချက်က \"ပြိုင်ပွဲ မစမီ အချိန်ကာလ\" ဆက်တင်ကို လွှမ်းမိုးသည်</string>
<string name="allowBerserk">အသဲအသန် Berserk အချိန်တိုင်း ပုံစံ ခွင့်ပြုသည်</string>
<string name="allowBerserkHelp">ခွင့်ပြုချိန် တစ်ဝက် စွန့်လွှတ်ပါက အမှတ် တစ်မှတ် အပို ပေးမည်</string>
<string name="allowChatHelp">ကစားသမားတို့ ချက်ထ်ရူးမ် အတွင်း စကားပြောခွင့် ပေးသည်</string>
<string name="arenaStreaks">အရီနာပုံစံ ပြိုင်ပွဲ တွတ် သတ်မှတ်ချက်</string>
<string name="arenaStreaksHelp">နှစ်ပွဲနိုင်ပြီးနောက် ဆက်တိုက် နိုင်သည့် ပွဲတိုင်း ၂-မှတ် အစား ၄-မှတ် ရမည်။</string>
</resources>

View File

@ -37,4 +37,12 @@ Berserk gir ett ekstrapoeng bare om du spiller minst 7 trekk i partiet.</string>
<item quantity="one">Vis laget</item> <item quantity="one">Vis laget</item>
<item quantity="other">Vis alle %s lagene</item> <item quantity="other">Vis alle %s lagene</item>
</plurals> </plurals>
<string name="newTeamBattle">Ny lagkamp</string>
<string name="customStartDate">Egendefinert startdato</string>
<string name="customStartDateHelp">I tidssonen din. Dette overstyrer innstillingen «Tid før turnering starter»</string>
<string name="allowBerserk">Tillat berserk</string>
<string name="allowBerserkHelp">La spillerne halvere tiden sin på klokken for et ekstra poeng</string>
<string name="allowChatHelp">La spillerne diskutere i samtalerom</string>
<string name="arenaStreaks">Arenarekker</string>
<string name="arenaStreaksHelp">Etter 2 seiere gir påfølgende seiere 4 poeng i stedet for 2.</string>
</resources> </resources>

View File

@ -43,4 +43,12 @@ Speel snel en ga terug naar de toernooilobby om meer partijen te spelen en meer
<item quantity="one">Bekijk het team</item> <item quantity="one">Bekijk het team</item>
<item quantity="other">Bekijk alle %s teams</item> <item quantity="other">Bekijk alle %s teams</item>
</plurals> </plurals>
<string name="newTeamBattle">Nieuwe wedstrijd</string>
<string name="customStartDate">Aangepaste startdatum</string>
<string name="customStartDateHelp">In je eigen lokale tijdzone. Dit overschrijft de instelling \"Tijd voordat het toernooi begint\"</string>
<string name="allowBerserk">Berserk toestaan</string>
<string name="allowBerserkHelp">Spelers kunnen met de helft van de tijd spelen om een extra punt te krijgen</string>
<string name="allowChatHelp">Spelers kunnen chatten in de chat room</string>
<string name="arenaStreaks">Arena streaks</string>
<string name="arenaStreaksHelp">Na 2 overwinningen geven opeenvolgende overwinningen 4 punten in plaats van 2.</string>
</resources> </resources>

View File

@ -37,4 +37,12 @@ Berserk gjev eitt ekstrapoeng berre om du spelar minst 7 trekk i partiet.</strin
<item quantity="one">Vis laget</item> <item quantity="one">Vis laget</item>
<item quantity="other">Vis alle %s lag</item> <item quantity="other">Vis alle %s lag</item>
</plurals> </plurals>
<string name="newTeamBattle">Ny lagkamp</string>
<string name="customStartDate">Eigendefinert startdato</string>
<string name="customStartDateHelp">I din tidssone. Dette overstyrar innstillinga «Tid før turnering startar»</string>
<string name="allowBerserk">Tillat berserk</string>
<string name="allowBerserkHelp">Lat spelarane halvere tida si på klokka for eit ekstra poeng</string>
<string name="allowChatHelp">Lat spelarane diskutera i samtalerom</string>
<string name="arenaStreaks">Arena-sigersrekkjer</string>
<string name="arenaStreaksHelp">Etter to sigrar gjev seinara sigrar fire poeng i staden for to.</string>
</resources> </resources>

View File

@ -47,4 +47,12 @@ Graj szybko i wracaj do poczekalni, by rozegrać więcej partii i zdobyć więce
<item quantity="many">Zobacz wszystkie %s zespołów</item> <item quantity="many">Zobacz wszystkie %s zespołów</item>
<item quantity="other">Zobacz wszystkie %s zespołów</item> <item quantity="other">Zobacz wszystkie %s zespołów</item>
</plurals> </plurals>
<string name="newTeamBattle">Nowa bitwa klubów</string>
<string name="customStartDate">Niestandardowa data rozpoczęcia</string>
<string name="customStartDateHelp">W Twojej lokalnej strefie czasowej. Nadpisuje ustawienie \"Czas przed rozpoczęciem turnieju\"</string>
<string name="allowBerserk">Zezwalaj na Berserk</string>
<string name="allowBerserkHelp">Pozwól graczom na zmniejszenie o połowę czasu pozwalając na zdobycie dodatkowego punktu</string>
<string name="allowChatHelp">Pozwól graczom dyskutować na czacie</string>
<string name="arenaStreaks">Serie aren</string>
<string name="arenaStreaksHelp">Po dwóch zwycięstwach, kolejne zwycięstwa dają 4 punkty zamiast 2.</string>
</resources> </resources>

View File

@ -42,4 +42,12 @@ Assim que terminar a sua partida, você voltará a aguardar o emparceiramento co
<item quantity="one">Ver a equipe</item> <item quantity="one">Ver a equipe</item>
<item quantity="other">Ver todas as %s equipes</item> <item quantity="other">Ver todas as %s equipes</item>
</plurals> </plurals>
<string name="newTeamBattle">Nova batalha de equipes</string>
<string name="customStartDate">Mudar a data de início</string>
<string name="customStartDateHelp">No seu próprio fuso horário. Isso irá cancelar a configuração \"Contagem regressiva para início do torneio\"</string>
<string name="allowBerserk">Permitir Berserk</string>
<string name="allowBerserkHelp">Os jogadores poderão reduzir seu tempo pela metade para ganhar um ponto extra</string>
<string name="allowChatHelp">Permite que os jogadores discutam em uma sala de chat</string>
<string name="arenaStreaks">Sequências de vitória em arena</string>
<string name="arenaStreaksHelp">Após ganhar 2 partidas, vitórias consecutivas valem 4 pontos, ao invés de 2.</string>
</resources> </resources>

View File

@ -44,4 +44,12 @@ Joga rápido e volta ao vestíbulo para jogares mais jogos e ganhares mais ponto
<item quantity="one">Ver a equipa</item> <item quantity="one">Ver a equipa</item>
<item quantity="other">Ver todas as %s equipas</item> <item quantity="other">Ver todas as %s equipas</item>
</plurals> </plurals>
<string name="newTeamBattle">Batalha de Equipas</string>
<string name="customStartDate">Data inicial personalizada</string>
<string name="customStartDateHelp">No seu próprio fuso horário local. Substitui a configuração \"Tempo antes do torneio começar\"</string>
<string name="allowBerserk">Permitir Berserk</string>
<string name="allowBerserkHelp">Permitir aos jogadores ganhar um ponto extra ao reduzir a duração do relógio a metade</string>
<string name="allowChatHelp">Permitir que os jogadores discutam numa sala de bate-papo</string>
<string name="arenaStreaks">Séries de Arena</string>
<string name="arenaStreaksHelp">Depois de 2 vitórias, vitórias consecutivas concedem 4 pontos em vez de 2.</string>
</resources> </resources>

View File

@ -45,4 +45,7 @@ Joacă rapid și întoarce-te la lobby pentru a juca mai multe meciuri și pentr
<item quantity="few">Vezi toate cele %s echipe</item> <item quantity="few">Vezi toate cele %s echipe</item>
<item quantity="other">Vezi toate cele %s de echipe</item> <item quantity="other">Vezi toate cele %s de echipe</item>
</plurals> </plurals>
<string name="customStartDate">Data de început personalizată</string>
<string name="allowBerserkHelp">Lăsați jucătorii să își înjumătățească timpul pentru a obține un punct în plus</string>
<string name="allowChatHelp">Permiteți jucătorilor să discute într-o cameră de chat</string>
</resources> </resources>

View File

@ -41,4 +41,12 @@
<item quantity="many">Посмотреть все %s клубов</item> <item quantity="many">Посмотреть все %s клубов</item>
<item quantity="other">Посмотреть все %s клубов</item> <item quantity="other">Посмотреть все %s клубов</item>
</plurals> </plurals>
<string name="newTeamBattle">Новый межклубный турнир</string>
<string name="customStartDate">Особая дата начала</string>
<string name="customStartDateHelp">В вашем часовом поясе. Это переопределяет настройку «Время до начала турнира»</string>
<string name="allowBerserk">Разрешить Берсерк</string>
<string name="allowBerserkHelp">Разрешает игрокам получать дополнительные очки, если они уменьшат своё время наполовину</string>
<string name="allowChatHelp">Разрешить игрокам обсуждение в чате</string>
<string name="arenaStreaks">Серии Арены</string>
<string name="arenaStreaksHelp">После двух побед подряд каждая следующая победа даёт не 2 очка, а 4.</string>
</resources> </resources>

View File

@ -41,4 +41,12 @@ Igrajte hitro in se vrnite v čakalno vrsto v igralni dvorani, ter si tako zagot
<string name="shareUrl">Delite ta URL, da se igralci lahko pridružijo: %s</string> <string name="shareUrl">Delite ta URL, da se igralci lahko pridružijo: %s</string>
<string name="drawStreak">Niz remijev: Ko igralec zeporedoma remizira v areni, bo le leprvi remi rezultiral v točko ali remiji z več kot %s potezami. Niz remijev se lahko prekine le z zmago, ne pa s porazom ali remijem.</string> <string name="drawStreak">Niz remijev: Ko igralec zeporedoma remizira v areni, bo le leprvi remi rezultiral v točko ali remiji z več kot %s potezami. Niz remijev se lahko prekine le z zmago, ne pa s porazom ali remijem.</string>
<string name="history">Zgodovina arene</string> <string name="history">Zgodovina arene</string>
<string name="newTeamBattle">Nova skupinska bitka</string>
<string name="customStartDate">Začetni datum po meri</string>
<string name="customStartDateHelp">V svojem lokalnem časovnem pasu. To preglasi nastavitev \"Čas pred začetkom turnirja\"</string>
<string name="allowBerserk">Dovoli divjanje</string>
<string name="allowBerserkHelp">Naj igralci razpolovijo svoj čas ure, da pridobijo dodatno točko</string>
<string name="allowChatHelp">Naj igralci razpravljajo v klepetalnici</string>
<string name="arenaStreaks">Arena proge</string>
<string name="arenaStreaksHelp">Po 2 zaporednih zmagah nadaljne zmage namesto 2 dodelijo 4 točke.</string>
</resources> </resources>

View File

@ -42,4 +42,12 @@ Daha fazla oyun oynayıp daha çok puan kazanmak için hızlıca oynayın ve lob
<item quantity="one">Takımı görüntüleyin</item> <item quantity="one">Takımı görüntüleyin</item>
<item quantity="other">Tüm %s takımlarını görüntüleyin</item> <item quantity="other">Tüm %s takımlarını görüntüleyin</item>
</plurals> </plurals>
<string name="newTeamBattle">Yeni Takım Çarpışması</string>
<string name="customStartDate">Özel başlangıç tarihi</string>
<string name="customStartDateHelp">Kendi saat diliminizi kullanın. \"Turnuvaya kalan süre\" ayarı geçersiz kalacaktır</string>
<string name="allowBerserk">Divane moduna izin ver</string>
<string name="allowBerserkHelp">Ekstra puan kazanmak isteyen oyuncuların, sürelerinin yarısından feragat etmesine izin ver</string>
<string name="allowChatHelp">Oyuncuların sohbet odasında konuşmasına izin ver</string>
<string name="arenaStreaks">Arena serisi</string>
<string name="arenaStreaksHelp">2 kez üst üste kazandıktan sonra yapılan maçlar 2 yerine 4 puan verir.</string>
</resources> </resources>

View File

@ -46,4 +46,12 @@
<item quantity="many">Переглянути %s команд</item> <item quantity="many">Переглянути %s команд</item>
<item quantity="other">Переглянути %s команди</item> <item quantity="other">Переглянути %s команди</item>
</plurals> </plurals>
<string name="newTeamBattle">Нова Командна битва</string>
<string name="customStartDate">Власна дата початку</string>
<string name="customStartDateHelp">У вашому локальному часовому поясі. Це замінює налаштування \"Час до початку турніру\"</string>
<string name="allowBerserk">Дозволити Берсерк</string>
<string name="allowBerserkHelp">Дозволити гравцям зменшити наполовину свій час, щоб отримати додатковий бал</string>
<string name="allowChatHelp">Дозволити гравцям обговорення в чаті</string>
<string name="arenaStreaks">Серії Арени</string>
<string name="arenaStreaksHelp">Після двох перемог, кожна наступна перемога принесе 4 бали замість 2.</string>
</resources> </resources>

View File

@ -36,8 +36,7 @@
</plurals> </plurals>
<string name="thisIsPrivate">這是一個非公開的錦標賽</string> <string name="thisIsPrivate">這是一個非公開的錦標賽</string>
<string name="shareUrl">分享這個網址讓其他人加入這場錦標賽:%s</string> <string name="shareUrl">分享這個網址讓其他人加入這場錦標賽:%s</string>
<string name="drawStreak">連續平手機制:當一位玩家連續在錦標賽中或的平局,只有第一場平局會獲得積分,或是在下超過%s步時才會獲得積分。 <string name="drawStreak">連續平手機制:當一位玩家連續在錦標賽中或的平局,只有第一場平局會獲得積分,或是在下超過%s步時才會獲得積分。連續平手機制只會在獲勝或輸的時候被解除。</string>
連續平手機制只會在獲勝或輸的時候被解除。</string>
<string name="history">先前的重要錦標賽</string> <string name="history">先前的重要錦標賽</string>
<plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed"> <plurals name="viewAllXTeams" comment="viewAllXTeams [one] [other]&#10;&#10;%s is the number of teams that can be viewed">
<item quantity="other">查看所有 %s 團隊</item> <item quantity="other">查看所有 %s 團隊</item>

View File

@ -3,10 +3,14 @@
<string name="broadcasts">Трансляція</string> <string name="broadcasts">Трансляція</string>
<string name="liveBroadcasts">Онлайн трансляції турнірів</string> <string name="liveBroadcasts">Онлайн трансляції турнірів</string>
<string name="newBroadcast">Нова трансляція наживо</string> <string name="newBroadcast">Нова трансляція наживо</string>
<string name="addRound">Додати раунд</string>
<string name="ongoing">Поточні</string> <string name="ongoing">Поточні</string>
<string name="upcoming">Майбутні</string> <string name="upcoming">Майбутні</string>
<string name="completed">Завершені</string> <string name="completed">Завершені</string>
<string name="roundNumber">Номер раунда</string> <string name="roundName">Назва раунду</string>
<string name="roundNumber">Номер раунду</string>
<string name="tournamentName">Назва турніру</string>
<string name="tournamentDescription">Короткий опис турніру</string>
<string name="fullDescription">Повний опис події</string> <string name="fullDescription">Повний опис події</string>
<string name="fullDescriptionHelp">Необов\'язковий довгий опис трансляції. Наявна розмітка %1$s. Довжина має бути менша ніж %2$s символів.</string> <string name="fullDescriptionHelp">Необов\'язковий довгий опис трансляції. Наявна розмітка %1$s. Довжина має бути менша ніж %2$s символів.</string>
<string name="sourceUrlOrGameIds">URL джерела, або ідентифікатор гри</string> <string name="sourceUrlOrGameIds">URL джерела, або ідентифікатор гри</string>
@ -15,4 +19,9 @@
<string name="startDate">Дата початку у Вашому часовому поясі</string> <string name="startDate">Дата початку у Вашому часовому поясі</string>
<string name="startDateHelp">Необов\'язково, якщо Ви знаєте, коли починається подія</string> <string name="startDateHelp">Необов\'язково, якщо Ви знаєте, коли починається подія</string>
<string name="credits">Вдячність джерелу</string> <string name="credits">Вдячність джерелу</string>
<string name="resetRound">Скинути цей раунд</string>
<string name="deleteRound">Видалити цей раунд</string>
<string name="broadcastUrl">Посилання на трансляцію</string>
<string name="currentRoundUrl">Посилання на поточний раунд</string>
<string name="currentGameUrl">Посилання на поточну гру</string>
</resources> </resources>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="challenges">Usäfoderigä</string> <string name="challenges">Usäfoderigä</string>
<string name="challengeToPlay">Zu nere partie useforde</string> <string name="challengeToPlay">Zunärä Partii usäfordä</string>
<string name="challengeDeclined">Usäfoderig abglähnt</string> <string name="challengeDeclined">Usäfoderig abglähnt</string>
<string name="challengeAccepted">Usäfoderig angnoo!</string> <string name="challengeAccepted">Usäfoderig angnoo!</string>
<string name="challengeCanceled">Usäfoderig abbrochää.</string> <string name="challengeCanceled">Usäfoderig abbrochää.</string>
@ -13,11 +13,11 @@
<string name="xOnlyAcceptsChallengesFromFriends">%s nimmt Usäfoderigä nur vo Brudis a.</string> <string name="xOnlyAcceptsChallengesFromFriends">%s nimmt Usäfoderigä nur vo Brudis a.</string>
<string name="declineGeneric">I nim momentan kei Usäfoderigä me a.</string> <string name="declineGeneric">I nim momentan kei Usäfoderigä me a.</string>
<string name="declineLater">I nim momentan kei Usäfoderigä me a, bitte frog spöter nonemol.</string> <string name="declineLater">I nim momentan kei Usäfoderigä me a, bitte frog spöter nonemol.</string>
<string name="declineTooFast">Ziet zum überlege isch z\'churz für mi, bitte forderä mich nomel mit meh Bedenkzeit ussä.</string> <string name="declineTooFast">Ziit zum Überlegä isch z\'churz für mich, bitte fordärä mich nomol mit meh Bedänkziit usä.</string>
<string name="declineTooSlow">Ziet zum überlege isch z\'lang für mi, bitte forderä mich nomel mit weniger Bedenkzeit ussä.</string> <string name="declineTooSlow">Ziit zum Überlegä isch z\'lang für mich, bitte fordärä mich nomol mit wäniger Bedänkziit usä.</string>
<string name="declineTimeControl">I nim momentan kei Usäfoderigä me a.</string> <string name="declineTimeControl">I nim momentan kei Usäfoderigä me a.</string>
<string name="declineRated">Bitte forderä mi stattdessä zu enerä gewertetä Partie usä.</string> <string name="declineRated">Bitte fordrää mich schtattdessä zunärä gwärtätä Partii usä.</string>
<string name="declineCasual">Bitte fordere mich stattdessä zu einer ungewertetä Partie usä.</string> <string name="declineCasual">Bitte fordärä mich schtattdessä zunärä ungwärtätä Partii usä.</string>
<string name="declineStandard">I nimm momentan kei Usäforderigä für anderi Schpiilvariantä a.</string> <string name="declineStandard">I nimm momentan kei Usäforderigä für anderi Schpiilvariantä a.</string>
<string name="declineVariant">I bi im moment nöd parrat, diä Variantä zu spielä.</string> <string name="declineVariant">I bi im moment nöd parrat, diä Variantä zu spielä.</string>
<string name="declineNoBot">Ich nimm kei Usäfoderigä von Bots a.</string> <string name="declineNoBot">Ich nimm kei Usäfoderigä von Bots a.</string>

View File

@ -1,2 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="challenges">Defioj</string>
<string name="challengeToPlay">Defii al nova ludo</string>
<string name="challengeDeclined">Defio malakceptita</string>
<string name="challengeAccepted">Defio akceptita!</string>
<string name="challengeCanceled">Defio nuligita.</string>
<string name="youCannotChallengeX">Vi ne povas defii %s.</string>
<string name="xDoesNotAcceptChallenges">%s ne akceptas defiojn.</string>
<string name="xOnlyAcceptsChallengesFromFriends">%s nur akceptas defiojn de amikoj.</string>
<string name="declineGeneric">Mi ne akceptas defiojn en tiu ĉi momento.</string>
<string name="declineNoBot">Mi ne akceptas defiojn de robotoj.</string>
<string name="declineOnlyBot">Mi nur akceptas defiojn de robotoj.</string>
</resources>

View File

@ -8,5 +8,18 @@
<string name="registerToSendChallenges">אנא הירשמו על מנת לשלוח הזמנות למשחקים.</string> <string name="registerToSendChallenges">אנא הירשמו על מנת לשלוח הזמנות למשחקים.</string>
<string name="youCannotChallengeX">לא ניתן להזמין את %s למשחק.</string> <string name="youCannotChallengeX">לא ניתן להזמין את %s למשחק.</string>
<string name="xDoesNotAcceptChallenges">%s לא מקבל הזמנות למשחקים.</string> <string name="xDoesNotAcceptChallenges">%s לא מקבל הזמנות למשחקים.</string>
<string name="yourXRatingIsTooFarFromY">הדירוג שלך %1$s רחוק מדי מ%2$s.</string>
<string name="cannotChallengeDueToProvisionalXRating">אין אפשרות לאתגר בגלל דירוג זמני של %s.</string>
<string name="xOnlyAcceptsChallengesFromFriends">%s מאשר רק אתגרים מחברים.</string>
<string name="declineGeneric">לא מקבל תלמידים בזמן זה.</string>
<string name="declineLater">זה לא הזמן המתאים עבורי, אנא שאל שוב מאוחר יותר.</string>
<string name="declineTooFast">הזמנים האלו יותר מדי מהירים בשבילי, בבקשה תאתגר שוב עם משחק יותר איטי.</string>
<string name="declineTooSlow">הזמנים האלו יותר מדי איטיים בשבילי, בבקשה תאתגר שוב עם משחק יותר מהיר.</string>
<string name="declineTimeControl">אני לא מאשר אתגרים עם בקרת זמנים.</string>
<string name="declineRated">בבקשה תשלח לי אתגר מדורג במקום.</string>
<string name="declineCasual">בבקשה תשלח לי אתגר לא מדורג במקום.</string>
<string name="declineStandard">אני לא מקבל אתגרים של גרסאות אחרות בזמן זה.</string>
<string name="declineVariant">אני לא מוכן לשחק את הגרסה האחרת הזאת עכשיו.</string>
<string name="declineNoBot">אני לא מאשר הזמנות מבוטים.</string>
<string name="declineOnlyBot">מאשר הזמנות למשחק רק מבוטים.</string> <string name="declineOnlyBot">מאשר הזמנות למשחק רק מבוטים.</string>
</resources> </resources>

View File

@ -93,5 +93,4 @@ Hier is die skakel om die klas te betree.</string>
<string name="newsEdit2">Voeg die onlangse nuus aan die bokant. Moenie vorige nuus uitvee nie.</string> <string name="newsEdit2">Voeg die onlangse nuus aan die bokant. Moenie vorige nuus uitvee nie.</string>
<string name="newsEdit3">Skei nuus met --- <string name="newsEdit3">Skei nuus met ---
Dit sal \'n horisontale lyn vertoon.</string> Dit sal \'n horisontale lyn vertoon.</string>
<string name="markdownAvailable">%s is beskikbaar vir meer ingewikkelde sintaks.</string>
</resources> </resources>

View File

@ -92,5 +92,4 @@ Aquí ye lo vinclo d\'acceso.</string>
<string name="newsEdit1">Totas las noticias de clase en un solo puesto.</string> <string name="newsEdit1">Totas las noticias de clase en un solo puesto.</string>
<string name="newsEdit2">Anyade las noticias recients en a parte superior. No elimina las noticias anteriors.</string> <string name="newsEdit2">Anyade las noticias recients en a parte superior. No elimina las noticias anteriors.</string>
<string name="newsEdit3">Deseparar noticias con --- amostrará una linia horizontal.</string> <string name="newsEdit3">Deseparar noticias con --- amostrará una linia horizontal.</string>
<string name="markdownAvailable">%s ye disponible pa una sintaxi mas abanzada.</string>
</resources> </resources>

View File

@ -105,5 +105,4 @@
<string name="newsEdit2">إضافة الأخبار الأخيرة في الأعلى. لا تقم بحذف الأخبار السابقة.</string> <string name="newsEdit2">إضافة الأخبار الأخيرة في الأعلى. لا تقم بحذف الأخبار السابقة.</string>
<string name="newsEdit3">إفصل الأخبار ب --- <string name="newsEdit3">إفصل الأخبار ب ---
سيعرض سطرا أفقيا.</string> سيعرض سطرا أفقيا.</string>
<string name="markdownAvailable">%s متاح لتركيبات الأكثر تطوراً.</string>
</resources> </resources>

View File

@ -93,5 +93,4 @@ Sinfə daxil olmaq üçün link.</string>
<string name="newsEdit2">Üstə son xəbərləri əlavə edin. Əvvəlki xəbərləri silməyin.</string> <string name="newsEdit2">Üstə son xəbərləri əlavə edin. Əvvəlki xəbərləri silməyin.</string>
<string name="newsEdit3">Xəbərləri bununla ayırın --- <string name="newsEdit3">Xəbərləri bununla ayırın ---
Bu üfüqi bir xətt göstərəcək.</string> Bu üfüqi bir xətt göstərəcək.</string>
<string name="markdownAvailable">Daha inkişaf etmiş sintaksis üçün %s mövcuddur.</string>
</resources> </resources>

View File

@ -52,6 +52,10 @@
Ето линк за достъп към класа.</string> Ето линк за достъп към класа.</string>
<string name="invitationToClass">Вие сте поканен да влезете в класа \"%s\" като ученик.</string> <string name="invitationToClass">Вие сте поканен да влезете в класа \"%s\" като ученик.</string>
<string name="clickToViewInvitation">Натиснете тук, за да приемете поканата:</string> <string name="clickToViewInvitation">Натиснете тук, за да приемете поканата:</string>
<string name="closeStudent">Закриване на регистрацията</string>
<string name="closeTheAccount">Постоянно закриване на регистрацията на ученика.</string>
<string name="closeDesc1">Ученикът няма никога вече да може да използва тази регистрация. Затварянето е постоянно. Уверете се че ученикът разбира и се съгласява с това.</string>
<string name="closeDesc2">Вместо това, можете да предадете контрола върху регистрацията на ученика, така че тя/той да продължат да я използват.</string>
<string name="teachers">Учители</string> <string name="teachers">Учители</string>
<plurals name="nbTeachers"> <plurals name="nbTeachers">
<item quantity="one">Учител</item> <item quantity="one">Учител</item>

View File

@ -50,5 +50,4 @@
<string name="newsEdit2">সামপ্রতিক সংবাদ উপরে যোগ করুন। পুরনো সংবাদ মুছবেন না।</string> <string name="newsEdit2">সামপ্রতিক সংবাদ উপরে যোগ করুন। পুরনো সংবাদ মুছবেন না।</string>
<string name="newsEdit3">--- দিয়ে সংবাদ পৃথক করুন <string name="newsEdit3">--- দিয়ে সংবাদ পৃথক করুন
এটা একটা আনুভূমিক রেখা প্রদর্শন করবে।</string> এটা একটা আনুভূমিক রেখা প্রদর্শন করবে।</string>
<string name="markdownAvailable">%s আরো অ্যাডভান্সড সিনট্যাক্সের জন্য উপলব্ধ।</string>
</resources> </resources>

View File

@ -70,6 +70,9 @@ Amañ emañ al liamm evit mont ennañ.</string>
<string name="releaseDesc1">Ur wech dieubet ur gont ne c\'halloc\'h ket mui bezañ mestr warni. Gallout a ray ar studier lazhañ ar mod evit ar vugale ha cheñch ar ger-tremen e-unan.</string> <string name="releaseDesc1">Ur wech dieubet ur gont ne c\'halloc\'h ket mui bezañ mestr warni. Gallout a ray ar studier lazhañ ar mod evit ar vugale ha cheñch ar ger-tremen e-unan.</string>
<string name="releaseDesc2">Ezel eus ar c\'hlasad e chomo ar studier ur wech dieubet e gont.</string> <string name="releaseDesc2">Ezel eus ar c\'hlasad e chomo ar studier ur wech dieubet e gont.</string>
<string name="realUniqueEmail">Chomlec\'h postel nemetañ ha gwir ar studier. Ur gemennadenn gadarnaat a vo kaset gant ul liamm da glikañ warnañ evit dieubiñ ar gont.</string> <string name="realUniqueEmail">Chomlec\'h postel nemetañ ha gwir ar studier. Ur gemennadenn gadarnaat a vo kaset gant ul liamm da glikañ warnañ evit dieubiñ ar gont.</string>
<string name="closeStudent">Serriñ ar gont</string>
<string name="closeTheAccount">Serriñ kont ar studier da viken.</string>
<string name="closeDesc1">Ne c\'hallo ket ar studier implijout ar gont-mañ ken. Peurbadus eo serriñ. Bezit sur eo bet komprenet hag asantet gant ar studier.</string>
<string name="teachers">Kelennerien</string> <string name="teachers">Kelennerien</string>
<plurals name="nbTeachers"> <plurals name="nbTeachers">
<item quantity="one">Kelenner</item> <item quantity="one">Kelenner</item>
@ -102,5 +105,4 @@ Amañ emañ al liamm evit mont ennañ.</string>
<string name="newsEdit2">En nec\'h emañ ar c\'heleier nevez. Ne ziverkit ket ar c\'heleier kozh.</string> <string name="newsEdit2">En nec\'h emañ ar c\'heleier nevez. Ne ziverkit ket ar c\'heleier kozh.</string>
<string name="newsEdit3">Rannit ar c\'heleier gant --- <string name="newsEdit3">Rannit ar c\'heleier gant ---
Mod-se ho po ul linenn a-blaen.</string> Mod-se ho po ul linenn a-blaen.</string>
<string name="markdownAvailable">Bez\' eus %s evit mont pelloc\'h gant an ereadurezh.</string>
</resources> </resources>

View File

@ -95,5 +95,4 @@ Evo linka za pristup času.</string>
<string name="newsEdit1">Sve vijesti časa u jednom polju.</string> <string name="newsEdit1">Sve vijesti časa u jednom polju.</string>
<string name="newsEdit2">Dodajte najnoviju vijest na vrh. Ne brišite prethodne vijesti.</string> <string name="newsEdit2">Dodajte najnoviju vijest na vrh. Ne brišite prethodne vijesti.</string>
<string name="newsEdit3">Odvojite vijesti sa --- kako biste prikazali horizontalnu liniju.</string> <string name="newsEdit3">Odvojite vijesti sa --- kako biste prikazali horizontalnu liniju.</string>
<string name="markdownAvailable">%s je na raspolaganju za napredniju sintaksu.</string>
</resources> </resources>

View File

@ -93,5 +93,4 @@ Aquí està l\'enllaç per a accedir a la classe.</string>
<string name="newsEdit2">Afegeix les novetats més recents a la part superior. No eliminis les novetats anteriors.</string> <string name="newsEdit2">Afegeix les novetats més recents a la part superior. No eliminis les novetats anteriors.</string>
<string name="newsEdit3">Separa les novetats amb --- <string name="newsEdit3">Separa les novetats amb ---
Mostrarà una línia separadora horitzontal.</string> Mostrarà una línia separadora horitzontal.</string>
<string name="markdownAvailable">%s està disponible per a una sintaxis més avançada.</string>
</resources> </resources>

View File

@ -99,5 +99,4 @@ Zde je odkaz pro přístup ke třídě.</string>
<string name="newsEdit2">Přidejte poslední novinky nahoru. Neodstraňujte předchozí novinky.</string> <string name="newsEdit2">Přidejte poslední novinky nahoru. Neodstraňujte předchozí novinky.</string>
<string name="newsEdit3">Oddělte zprávy --- <string name="newsEdit3">Oddělte zprávy ---
Zobrazí se vodorovná čára.</string> Zobrazí se vodorovná čára.</string>
<string name="markdownAvailable">%s je k dispozici pro pokročilejší syntaxi.</string>
</resources> </resources>

View File

@ -63,10 +63,14 @@ Her er linket, der giver adgang til klassen.</string>
<string name="thisStudentAccountIsManaged">Denne elevkonto er under administration</string> <string name="thisStudentAccountIsManaged">Denne elevkonto er under administration</string>
<string name="upgradeFromManaged">Opgrader fra administreret til selvstyret</string> <string name="upgradeFromManaged">Opgrader fra administreret til selvstyret</string>
<string name="release">Frigiv</string> <string name="release">Frigiv</string>
<string name="releaseTheAccount">Frigiv kontoen så eleven kan styre den selv.</string> <string name="releaseTheAccount">Frigiv kontoen så eleven selv kan kontrollere den.</string>
<string name="releaseDesc1">En frigivet konto kan ikke sættes under administration igen. Eleven vil kunne ændre i børnetilstand og selv nulstille adgangskode.</string> <string name="releaseDesc1">En frigivet konto kan ikke sættes under administration igen. Eleven vil kunne ændre i børnetilstand og selv nulstille adgangskode.</string>
<string name="releaseDesc2">Eleven vil blive i klassen efter deres konto er frigivet.</string> <string name="releaseDesc2">Eleven vil blive i klassen efter deres konto er frigivet.</string>
<string name="realUniqueEmail">Korrekt, unik e-mailadresse for eleven. Vi sender en bekræftelsesmail til den med et link til at frigive kontoen.</string> <string name="realUniqueEmail">Rigtig, unik e-mailadresse for eleven. Vi sender en bekræftelsesmail til den med et link til frigivelse af kontoen.</string>
<string name="closeStudent">Luk konto</string>
<string name="closeTheAccount">Luk elevkontoen permanent.</string>
<string name="closeDesc1">Eleven vil aldrig kunne bruge denne konto igen. Lukning er endelig. Sørg for at eleven forstår og er enig.</string>
<string name="closeDesc2">Du bør måske give eleven kontrol over kontoen i stedet, så de kan fortsætte med at bruge den.</string>
<string name="teachers">Lærere</string> <string name="teachers">Lærere</string>
<plurals name="nbTeachers"> <plurals name="nbTeachers">
<item quantity="one">Lærer</item> <item quantity="one">Lærer</item>
@ -92,5 +96,4 @@ Her er linket, der giver adgang til klassen.</string>
<string name="newsEdit1">Alle klasse-nyheder i et enkelt felt.</string> <string name="newsEdit1">Alle klasse-nyheder i et enkelt felt.</string>
<string name="newsEdit2">Tilføj de seneste nyheder i toppen. Slet ikke tidligere nyheder.</string> <string name="newsEdit2">Tilføj de seneste nyheder i toppen. Slet ikke tidligere nyheder.</string>
<string name="newsEdit3">Adskil nyheder med --- det vil blive vist som en vandret linje.</string> <string name="newsEdit3">Adskil nyheder med --- det vil blive vist som en vandret linje.</string>
<string name="markdownAvailable">%s er tilgængelig for mere avanceret syntaks.</string>
</resources> </resources>

View File

@ -30,7 +30,7 @@
<string name="generateANewPassword">Generiere ein neues Passwort für den Schüler</string> <string name="generateANewPassword">Generiere ein neues Passwort für den Schüler</string>
<string name="invitedToXByY">Eingeladen zu %1$s von %2$s</string> <string name="invitedToXByY">Eingeladen zu %1$s von %2$s</string>
<string name="realName">Echter Name</string> <string name="realName">Echter Name</string>
<string name="privateWillNeverBeShown">Privat. Wird nie außerhalb der Klasse angezeigt. Hilft dir, dich zu erinnern, wer der Schüler ist.</string> <string name="privateWillNeverBeShown">Privat. Wird niä usserhalb vodä Klass aazeigt. Hilft dir, dich z\'erinnärä, wer dä Schüaler / diä Schüälerin isch.</string>
<string name="addStudent">Schüler hinzufügen</string> <string name="addStudent">Schüler hinzufügen</string>
<string name="lichessProfileXCreatedForY">Lichess-Profil %1$s erstellt für %2$s.</string> <string name="lichessProfileXCreatedForY">Lichess-Profil %1$s erstellt für %2$s.</string>
<string name="studentCredentials">Schüäler/-in: %1$s <string name="studentCredentials">Schüäler/-in: %1$s
@ -67,6 +67,10 @@ Hier ist der Link zum Zugriff auf die Klasse.</string>
<string name="releaseDesc1">Ein freigegebenes Konto kann nicht mehr verwaltet werden. Der Schüler wird in der Lage sein den Kindermodus abzuschalten und das Passwort selbstständig zurückzusetzen.</string> <string name="releaseDesc1">Ein freigegebenes Konto kann nicht mehr verwaltet werden. Der Schüler wird in der Lage sein den Kindermodus abzuschalten und das Passwort selbstständig zurückzusetzen.</string>
<string name="releaseDesc2">Der Schüler bleibt in der Klasse nachdem sein Konto freigegeben wurde.</string> <string name="releaseDesc2">Der Schüler bleibt in der Klasse nachdem sein Konto freigegeben wurde.</string>
<string name="realUniqueEmail">Echte, einmalige Email-Adresse des Schülers. Wir werden eine Bestätigungsmail mit einem Link zur Freigabe des Kontos versenden.</string> <string name="realUniqueEmail">Echte, einmalige Email-Adresse des Schülers. Wir werden eine Bestätigungsmail mit einem Link zur Freigabe des Kontos versenden.</string>
<string name="closeStudent">Benutzerkonto gschlüssä</string>
<string name="closeTheAccount">Schüälerkonto permanent gschlüssä.</string>
<string name="closeDesc1">Dä Schüäler / diä Schüälerin cha das Konto niä meh verwändä. Gschlüssä isch endgültig. Schtell sicher, dass dä Schüäler / d\'Schüälerin das verschtoht und akzeptiärt.</string>
<string name="closeDesc2">Du chasch schattdessä äm Schüäler / diä Schüälerin d\'Kontrollä über das Konto gäh, damit är sis / si ihräs Konto wiiterhin verwändä chan.</string>
<string name="teachers">Lehrer</string> <string name="teachers">Lehrer</string>
<plurals name="nbTeachers"> <plurals name="nbTeachers">
<item quantity="one">Lehrer</item> <item quantity="one">Lehrer</item>
@ -92,5 +96,4 @@ Hier ist der Link zum Zugriff auf die Klasse.</string>
<string name="newsEdit1">Alle Klassennachrichten in einem einzigen Feld.</string> <string name="newsEdit1">Alle Klassennachrichten in einem einzigen Feld.</string>
<string name="newsEdit2">Füge die aktuellen Neuigkeiten oben hinzu. Lösche keine vorherigen Neuigkeiten.</string> <string name="newsEdit2">Füge die aktuellen Neuigkeiten oben hinzu. Lösche keine vorherigen Neuigkeiten.</string>
<string name="newsEdit3">Trenne Neuigkeiten mit --- Es wird als horizontale Linie angezeigt.</string> <string name="newsEdit3">Trenne Neuigkeiten mit --- Es wird als horizontale Linie angezeigt.</string>
<string name="markdownAvailable">%s ist für erweiterte Syntax verfügbar.</string>
</resources> </resources>

View File

@ -62,11 +62,15 @@ Hier ist der Link zum Zugriff auf die Klasse.</string>
<string name="managed">Verwaltet</string> <string name="managed">Verwaltet</string>
<string name="thisStudentAccountIsManaged">Dieses Schülerkonto wird verwaltet</string> <string name="thisStudentAccountIsManaged">Dieses Schülerkonto wird verwaltet</string>
<string name="upgradeFromManaged">Aufwerten von verwaltet zu selbstständig</string> <string name="upgradeFromManaged">Aufwerten von verwaltet zu selbstständig</string>
<string name="release">Freigabe</string> <string name="release">Hochstufen</string>
<string name="releaseTheAccount">Gib das Konto frei, damit der Schüler es selbstständig verwalten kann.</string> <string name="releaseTheAccount">Gib das Konto frei, damit der Schüler es selbstständig verwalten kann.</string>
<string name="releaseDesc1">Ein freigegebenes Konto kann nicht mehr verwaltet werden. Der Schüler wird in der Lage sein den Kindermodus abzuschalten und das Passwort selbstständig zurückzusetzen.</string> <string name="releaseDesc1">Ein freigegebenes Konto kann nicht mehr verwaltet werden. Der Schüler wird in der Lage sein den Kindermodus abzuschalten und das Passwort selbstständig zurückzusetzen.</string>
<string name="releaseDesc2">Der Schüler bleibt in der Klasse nachdem sein Konto freigegeben wurde.</string> <string name="releaseDesc2">Der Schüler bleibt in der Klasse nachdem sein Konto freigegeben wurde.</string>
<string name="realUniqueEmail">Echte, einmalige Email-Adresse des Schülers. Wir werden eine Bestätigungsmail mit einem Link zur Freigabe des Kontos versenden.</string> <string name="realUniqueEmail">Echte, eindeutige E-Mail-Adresse des Schülers. Wir werden eine Bestätigungs-E-Mail mit einem Link zur Freigabe des Kontos versenden.</string>
<string name="closeStudent">Schülerkonto schließen</string>
<string name="closeTheAccount">Das Schülerkonto dauerhaft schließen.</string>
<string name="closeDesc1">Der Schüler wird das Konto nie wieder nutzen können. Die Schließung ist endgültig. Stelle sicher, dass der Schüler dies versteht und einverstanden ist.</string>
<string name="closeDesc2">Du kannst stattdessen dem Schüler die Kontrolle über das Konto überlassen, so dass er es weiter nutzen kann.</string>
<string name="teachers">Lehrer</string> <string name="teachers">Lehrer</string>
<plurals name="nbTeachers"> <plurals name="nbTeachers">
<item quantity="one">Lehrer</item> <item quantity="one">Lehrer</item>
@ -92,5 +96,4 @@ Hier ist der Link zum Zugriff auf die Klasse.</string>
<string name="newsEdit1">Alle Klassennachrichten in einem einzigen Feld.</string> <string name="newsEdit1">Alle Klassennachrichten in einem einzigen Feld.</string>
<string name="newsEdit2">Füge die aktuellen Neuigkeiten oben hinzu. Lösche keine vorherigen Neuigkeiten.</string> <string name="newsEdit2">Füge die aktuellen Neuigkeiten oben hinzu. Lösche keine vorherigen Neuigkeiten.</string>
<string name="newsEdit3">Trenne Neuigkeiten mit --- Es wird als horizontale Linie angezeigt.</string> <string name="newsEdit3">Trenne Neuigkeiten mit --- Es wird als horizontale Linie angezeigt.</string>
<string name="markdownAvailable">%s ist für erweiterte Syntax verfügbar.</string>
</resources> </resources>

View File

@ -67,6 +67,10 @@
<string name="releaseDesc1">Ένας αυτόνομος λογαριασμός δεν μπορεί να ξαναγίνει διαχειριζόμενος. Ο μαθητής θα μπορεί να ενεργοποιήσει ή να απενεργοποιήσει την παιδική λειτουργία και να επαναφέρει το κωδικό πρόσβασης.</string> <string name="releaseDesc1">Ένας αυτόνομος λογαριασμός δεν μπορεί να ξαναγίνει διαχειριζόμενος. Ο μαθητής θα μπορεί να ενεργοποιήσει ή να απενεργοποιήσει την παιδική λειτουργία και να επαναφέρει το κωδικό πρόσβασης.</string>
<string name="releaseDesc2">Ο μαθητής θα παραμείνει στην τάξη μετά την απελευθέρωση του λογαριασμού του.</string> <string name="releaseDesc2">Ο μαθητής θα παραμείνει στην τάξη μετά την απελευθέρωση του λογαριασμού του.</string>
<string name="realUniqueEmail">Πραγματική, μοναδική διεύθυνση ηλεκτρονικού ταχυδρομείου του μαθητή. Θα στείλουμε ένα email επιβεβαίωσης σε αυτήν με ένα σύνδεσμο για ενεργοποίηση του λογαριασμού.</string> <string name="realUniqueEmail">Πραγματική, μοναδική διεύθυνση ηλεκτρονικού ταχυδρομείου του μαθητή. Θα στείλουμε ένα email επιβεβαίωσης σε αυτήν με ένα σύνδεσμο για ενεργοποίηση του λογαριασμού.</string>
<string name="closeStudent">Κλείστε αυτόν τον λογαριασμό</string>
<string name="closeTheAccount">Κλείστε μόνιμα αυτόν τον μαθητικό λογαριασμό.</string>
<string name="closeDesc1">Ο μαθητής δε θα μπορέσει ποτέ να χρησιμοποιήσει ξανά αυτόν τον λογαριασμό. Η ενέργειά σας αυτή είναι τελική. Βεβαιωθείτε ότι ο μαθητής κατανοεί τις επιπτώσεις και συμφωνεί με την απόφαση.</string>
<string name="closeDesc2">Μπορεί εναλλακτικά, αν θέλετε, να δώσετε τον έλεγχο του λογαριασμού στον μαθητή, έτσι ώστε να μπορεί να τον χρησιμοποιεί.</string>
<string name="teachers">Δάσκαλοι</string> <string name="teachers">Δάσκαλοι</string>
<plurals name="nbTeachers"> <plurals name="nbTeachers">
<item quantity="one">Δάσκαλος</item> <item quantity="one">Δάσκαλος</item>
@ -93,5 +97,4 @@
<string name="newsEdit2">Προσθήκη πρόσφατων νέων στη κορυφή. Να μη διαγραφούν τα προηγούμενα νέα.</string> <string name="newsEdit2">Προσθήκη πρόσφατων νέων στη κορυφή. Να μη διαγραφούν τα προηγούμενα νέα.</string>
<string name="newsEdit3">Να διαχωρίζονται τα νέα με --- <string name="newsEdit3">Να διαχωρίζονται τα νέα με ---
Θα εμφανιστεί μια οριζόντια γραμμή.</string> Θα εμφανιστεί μια οριζόντια γραμμή.</string>
<string name="markdownAvailable">Η μορφή %s είναι διαθέσιμη για μια πιο προχωρημένη σύνταξη.</string>
</resources> </resources>

Some files were not shown because too many files have changed in this diff Show More