blob: ae23e46404397fc094d4ef10b0ecc15c7391c67f (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package org.meshbay.client.shell
/**
* A sentence from the interface's own catalogues, for the few things the
* application draws itself (main.js `nativeText`). The page chooses the
* language and nothing else: a confirmation it worded would be one it could
* answer for itself.
*
* The catalogues are `export default { 'key': '…', … }` with single-quoted
* strings; a plural entry is an object, of which `other` is taken.
*/
class NativeText(private val readCatalogue: (String) -> String?) {
fun get(key: String, locale: String, params: Map<String, String> = emptyMap()): String {
var text = pick(readCatalogue(locale), key) ?: pick(readCatalogue("en"), key) ?: key
// split/join, as i18n.js: a folder name may contain `$&`.
for ((k, v) in params) text = text.split("{$k}").joinToString(v)
return text
}
companion object {
fun pick(source: String?, key: String): String? {
source ?: return null
val k = Regex.escape(key)
Regex("""(?m)^\s*'$k'\s*:\s*'((?:[^'\\]|\\.)*)'""").find(source)?.let { return unescape(it.groupValues[1]) }
Regex("""(?ms)^\s*'$k'\s*:\s*\{.*?\bother\s*:\s*'((?:[^'\\]|\\.)*)'""").find(source)?.let { return unescape(it.groupValues[1]) }
return null
}
fun unescape(s: String): String {
val out = StringBuilder()
var i = 0
while (i < s.length) {
val c = s[i]
if (c == '\\' && i + 1 < s.length) {
val n = s[i + 1]
when (n) {
'n' -> out.append('\n'); 't' -> out.append('\t')
'u' -> if (i + 5 < s.length) { out.append(s.substring(i + 2, i + 6).toInt(16).toChar()); i += 4 }
else -> out.append(n)
}
i += 2
} else { out.append(c); i++ }
}
return out.toString()
}
}
}
|