Fix view webapp translations
This commit is contained in:
@@ -103,6 +103,7 @@
|
||||
</httpConnector>
|
||||
<systemProperties>
|
||||
<pairgoth.api.url>http://localhost:8085/api/</pairgoth.api.url>
|
||||
<pairgoth.env>dev</pairgoth.env>
|
||||
</systemProperties>
|
||||
<webApp>
|
||||
<resourceBases>${project.basedir}/src/main/webapp,${project.build.directory}/generated-resources/</resourceBases>
|
||||
|
@@ -7,12 +7,14 @@ import org.apache.velocity.runtime.parser.node.ASTText
|
||||
import org.apache.velocity.runtime.parser.node.SimpleNode
|
||||
import org.jeudego.pairgoth.web.WebappManager
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.ConcurrentSkipListSet
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.io.path.readLines
|
||||
import kotlin.io.path.useDirectoryEntries
|
||||
@@ -79,7 +81,7 @@ class Translator private constructor(private val iso: String) {
|
||||
if (groupStart > start) output.print(text.substring(start, groupStart))
|
||||
val capture = matcher.group(group)
|
||||
var token: String = StringEscapeUtils.unescapeHtml4(capture)
|
||||
if (StringUtils.containsOnly(token, "\r\n\t -;:.\"/<>\u00A00123456789€!")) output.print(capture) else {
|
||||
if (StringUtils.containsOnly(token, "\r\n\t -;:.'\"/<>\u00A00123456789€[]!")) output.print(capture) else {
|
||||
token = normalize(token)
|
||||
token = translate(token)
|
||||
output.print(StringEscapeUtils.escapeHtml4(token))
|
||||
@@ -104,17 +106,15 @@ class Translator private constructor(private val iso: String) {
|
||||
map[0] = (ignoring != null)
|
||||
while (pos < text.length) {
|
||||
if (ignoring == null) {
|
||||
val nextIgnore = ignoredTags.map { tag ->
|
||||
Pair(tag, text.indexOf("<$tag(?:>\\s)"))
|
||||
}.filter {
|
||||
it.second != -1
|
||||
}.sortedBy {
|
||||
it.second
|
||||
}.firstOrNull()
|
||||
val nextIgnore = ignoredTags.mapNotNull { tag ->
|
||||
Regex("<($tag)(?:>|\\s)").find(text)
|
||||
}.minByOrNull {
|
||||
it.range.first
|
||||
}
|
||||
if (nextIgnore == null) pos = text.length
|
||||
else {
|
||||
ignoring = nextIgnore.first
|
||||
pos += nextIgnore.first.length + 2
|
||||
ignoring = nextIgnore.groupValues[1]
|
||||
pos += ignoring.length + 2
|
||||
}
|
||||
} else {
|
||||
val closingTag = text.indexOf("</$ignoring>")
|
||||
@@ -132,9 +132,12 @@ class Translator private constructor(private val iso: String) {
|
||||
get() = textAccessor[this] as String
|
||||
set(value: String) { textAccessor[this] = value }
|
||||
|
||||
private val saveMissingTranslations = System.getProperty("pairgoth.env") == "dev"
|
||||
private val missingTranslations: MutableSet<String> = ConcurrentSkipListSet()
|
||||
|
||||
private fun reportMissingTranslation(enText: String) {
|
||||
logger.warn("missing translation towards {}: {}", iso, enText)
|
||||
// CB TODO - create file
|
||||
if (saveMissingTranslations) missingTranslations.add(enText)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -165,5 +168,18 @@ class Translator private constructor(private val iso: String) {
|
||||
|
||||
val providedLanguages = setOf("en", "fr")
|
||||
const val defaultLanguage = "en"
|
||||
|
||||
internal fun notifyExiting() {
|
||||
translators.values.filter {
|
||||
it.saveMissingTranslations && it.missingTranslations.isNotEmpty()
|
||||
}.forEach {
|
||||
val missing = File("${it.iso}.missing")
|
||||
logger.info("Saving missing translations for ${it.iso} to ${missing.canonicalPath}")
|
||||
missing.printWriter().use { out ->
|
||||
|
||||
out.println(it.missingTranslations.map { "${it}\t" }.joinToString("\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package org.jeudego.pairgoth.web
|
||||
|
||||
import com.republicate.mailer.SmtpLoop
|
||||
import org.apache.commons.lang3.tuple.Pair
|
||||
import org.jeudego.pairgoth.util.Translator
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.IOException
|
||||
import java.lang.IllegalAccessError
|
||||
@@ -51,7 +52,7 @@ class WebappManager : ServletContextListener, ServletContextAttributeListener, H
|
||||
/* ServletContextListener interface */
|
||||
override fun contextInitialized(sce: ServletContextEvent) {
|
||||
context = sce.servletContext
|
||||
logger.info("---------- Starting Pairgoth Web Client ----------")
|
||||
logger.info("---------- Starting $WEBAPP_NAME ----------")
|
||||
context.setAttribute("manager", this)
|
||||
webappRoot = context.getRealPath("/")
|
||||
try {
|
||||
@@ -78,11 +79,15 @@ class WebappManager : ServletContextListener, ServletContextAttributeListener, H
|
||||
}
|
||||
|
||||
override fun contextDestroyed(sce: ServletContextEvent) {
|
||||
logger.info("---------- Stopping Web Application ----------")
|
||||
logger.info("---------- Stopping $WEBAPP_NAME ----------")
|
||||
|
||||
Translator.notifyExiting()
|
||||
|
||||
val context = sce.servletContext
|
||||
for (service in webServices.keys) stopService(service, true)
|
||||
// ??? DriverManager.deregisterDriver(com.mysql.cj.jdbc.Driver ...);
|
||||
|
||||
logger.info("---------- Stopped $WEBAPP_NAME ----------")
|
||||
}
|
||||
|
||||
/* ServletContextAttributeListener interface */
|
||||
@@ -95,6 +100,7 @@ class WebappManager : ServletContextListener, ServletContextAttributeListener, H
|
||||
override fun sessionDestroyed(se: HttpSessionEvent) {}
|
||||
|
||||
companion object {
|
||||
const val WEBAPP_NAME = "Pairgoth Web Client"
|
||||
const val PAIRGOTH_PROPERTIES_PREFIX = "pairgoth."
|
||||
lateinit var webappRoot: String
|
||||
lateinit var context: ServletContext
|
||||
|
@@ -1,2 +1,28 @@
|
||||
New tournament Nouveau tournoi
|
||||
Open Ouvrir
|
||||
Cancel Annuler
|
||||
Infos Infos
|
||||
Next Suivant
|
||||
Pairing Appariement
|
||||
Type Type
|
||||
(pairgo / rengo) (pairgo / rengo)
|
||||
(teams of individual players) (équipes de joueurs individuels)
|
||||
MacMahon MacMahon
|
||||
Number of rounds Nombre de rondes
|
||||
Partner teams tournament of Tournoi d'équipes partenaires de
|
||||
Standard tournament of individual players Tournoi standard de joueurs individuels
|
||||
Swiss Suisse
|
||||
Teams tournament of Tournoi par équipes de
|
||||
Tournament dates Dates du tournoi
|
||||
Tournament name Nom du tournoi
|
||||
Tournament pairing Appariement du tournoi
|
||||
Tournament short name Nom abbrégé du tournoi
|
||||
Tournament type Type de tournoi
|
||||
end date date de fin
|
||||
from du
|
||||
players joueurs
|
||||
rounds rondes
|
||||
short_name nom_tournoi
|
||||
start date date de début
|
||||
to au
|
||||
|
||||
|
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="scrolling content">
|
||||
#parse('tournament-form.inc.html')
|
||||
#translate('tournament-form.inc.html')
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui cancel black floating button">Cancel</button>
|
||||
|
@@ -1,20 +1,20 @@
|
||||
<form id="new-tournament-form" class="ui form">
|
||||
<form class="tournament-form" class="ui form">
|
||||
<div class="ui infos tab segment">
|
||||
<div class="field">
|
||||
<label>Tournament name</label>
|
||||
<input type="text" name="name" placeholder="Tournament name"/>
|
||||
<input type="text" name="name" required placeholder="Tournament name"/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Tournament short name</label>
|
||||
<input type="text" name="shortname" placeholder="short_name"/>
|
||||
<input type="text" name="shortname" required placeholder="short_name"/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Tournament dates</label>
|
||||
<span id="date-range">from <input type="text" name="start" class="date" placeholder="start date"/> to <input type="text" name="end" class="date" placeholder="end date"/></span>
|
||||
<span class="date-range">from <input type="text" name="start" required class="date" placeholder="start date"/> to <input type="text" name="end" required class="date" placeholder="end date"/></span>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Number of rounds</label>
|
||||
<span><input type="number" name="rounds" min="1"/> rounds</span>
|
||||
<span><input type="number" name="rounds" required min="1"/> rounds</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui type tab segment">
|
||||
@@ -23,7 +23,7 @@
|
||||
<div class="field">
|
||||
<div class="ui radio">
|
||||
<label>
|
||||
<input type="radio" name="type" value="standard"/>
|
||||
<input type="radio" name="type" value="standard" required/>
|
||||
Standard tournament of individual players
|
||||
</label>
|
||||
</div>
|
||||
@@ -31,7 +31,7 @@
|
||||
<div class="field">
|
||||
<div class="ui radio">
|
||||
<label>
|
||||
<input type="radio" name="type" value="partners"/>
|
||||
<input type="radio" name="type" value="partners" required/>
|
||||
<span>Partner teams tournament of <input type="number" min="2" name="partners"/> players</span> (pairgo / rengo)
|
||||
</label>
|
||||
</div>
|
||||
@@ -39,7 +39,7 @@
|
||||
<div class="field">
|
||||
<div class="ui radio">
|
||||
<label>
|
||||
<input type="radio" name="type" value="teams"/>
|
||||
<input type="radio" name="type" value="teams" required/>
|
||||
<span>Teams tournament of <input type="number" min="2" name="partners"/> players</span> (teams of individual players)
|
||||
</label>
|
||||
</div>
|
||||
@@ -52,7 +52,7 @@
|
||||
<div class="field">
|
||||
<div class="ui radio">
|
||||
<label>
|
||||
<input type="radio" name="pairing" value="macmahon"/>
|
||||
<input type="radio" name="pairing" value="macmahon" required/>
|
||||
MacMahon
|
||||
</label>
|
||||
</div>
|
||||
@@ -60,7 +60,7 @@
|
||||
<div class="field">
|
||||
<div class="ui radio">
|
||||
<label>
|
||||
<input type="radio" name="pairing" value="swiss"/>
|
||||
<input type="radio" name="pairing" value="swiss" required/>
|
||||
Swiss
|
||||
</label>
|
||||
</div>
|
||||
@@ -68,3 +68,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
onLoad(() => {
|
||||
$('#tournament-form').on('input', e => {
|
||||
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
CB TODO :
|
||||
s'il y a duplication du formulaire (pour nouveau/édition), il faut changer les ids en class, gérer les pbs d'init du date-range, etc.
|
||||
sinon, il faut paramétrer la dialog (mais les steps 1/2/3 deviennent des tabs, etc.)
|
||||
|
||||
Donc dans tous les cas il y a qqc à faire !
|
||||
|
Reference in New Issue
Block a user