-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathbuild_translations.moon
213 lines (166 loc) Β· 5.4 KB
/
build_translations.moon
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
-- generates lua file containing all the translations
compile = require "moonscript.compile"
lfs = require "lfs"
DIR = "locales/"
SOURCE_LOCALE = "en"
import types from require "tableshape"
argparse = require "argparse"
parser = argparse "build_translations.moon", "Build all translations into single file"
parser\option "--source-locale", "Which locale is the default", SOURCE_LOCALE
parser\option "--dir", "Directory to load translation files from", DIR, (str) -> if str\match "/$" then str else "#{str}/"
parser\option "--format", "Output format (lua, json, json_raw)", "lua", types.one_of({"lua", "json", "json_raw"})\transform
parser\flag "--nested", "Nest keys", false
parser\flag "--git", "Insert git hash as comment at top of output (Lua Only)"
args = parser\parse [v for _, v in ipairs arg]
json = require "cjson"
get_git_hash = ->
-- note this needs to be called from the right directory
f = io.popen "git rev-parse --short HEAD", "r"
if revision = f\read "*a"
revision\match "[^%s]+"
output = { }
flatten_nested = (t, prefix="", out={}) ->
for k,v in pairs t
if type(v) == "table"
flatten_nested v, "#{prefix}#{k}.", out
else
out["#{prefix}#{k}"] = v
out
empty_object = types.equivalent {}
merge_tables = (target, to_merge) ->
assert type(target) == "table", "target for merge is not table"
assert type(to_merge) == "table", "table to merge is not table"
for k, v in pairs to_merge
if target[k]
if type(target[k]) == "string"
error "can't merge into string: #{k}"
merge_tables target[k], v
else
target[k] = v
visit_directory = (dir) ->
for file in assert lfs.dir dir
continue if file\match "^%.+$"
path = "#{dir}#{file}"
switch lfs.attributes path, "mode"
when "directory"
visit_directory "#{path}/"
when "file"
name = file\match "^([%w_]+).json$"
continue unless name
handle = assert io.open path
contents = assert handle\read "*a"
object = json.decode contents
if empty_object object
continue
unless args.nested
object = flatten_nested object
if output[name]
merge_tables output[name], object
else
output[name] = object
visit_directory args.dir
-- summarize completion
if args.format == "lua"
-- remove any plural suffixes
normalize_key = (key) -> (key\gsub("_%d+$", "")\gsub("_plural$", ""))
source_translations = assert output[args.source_locale], "missing source locale: #{args.source_locale}"
source_keys = {normalize_key(key), true for key in pairs source_translations}
source_keys = [key for key in pairs source_keys]
for locale, translations in pairs output
found = 0
translated_keys = {normalize_key(key), true for key in pairs output when type(key) == "string"}
for key in *source_keys
if translations[key]
found += 1
table.insert translations, {
:found
-- completion_ratio: found / #source_keys
}
import parse_tags, chunk_to_syntax from require "helpers.compiler"
import types from require "tableshape"
simple_string = types.shape { types.string }
string_to_syntax = (str) ->
chunks = parse_tags\match str
unless chunks
error "failed to parse string: #{str}"
if simple_string chunks
return nil
lines = [chunk_to_syntax chunk for chunk in *chunks]
{"fndef", {{"text_fn"}, {"variables"}}, {}, "slim", lines}
encode_value = (v) ->
switch type(v)
when "number"
{"number", v}
when "table"
keys = [k for k in pairs v]
table.sort keys, (a, b) ->
if type(a) != type(b)
if type(a) == "number"
return true
if type(b) == "number"
return false
else
return a < b
{"table", for k in *keys
if type(k) == "number"
{
encode_value v[k]
}
else
k = tostring k
{
if k\match "%."
{"string", '"', k}
else
{"key_literal", k}
encode_value v[k]
}
}
else
str = tostring v
if fn = string_to_syntax str
return fn
delim = if str\match '"'
if str\match "'"
'[==['
else
"'"
else
'"'
{"string", delim, v}
switch args.format
when "json_raw"
print json.encode output
when "json"
local convert_syntax
convert_syntax = types.one_of {
types.equivalent({""}) / nil
types.shape({ types.string }) / (t) -> t[1]
types.array_of types.one_of {
types.string
types.shape({
variable: types.string
}, open: true) / (v) -> {"v", v.variable}
types.shape({
tag: types.string
contents: types.nil + types.proxy -> convert_syntax
}, open: true) / (v) -> {"t", v.tag, v.contents}
}
}
import parse_tags from require "helpers.compiler"
local strings_level
strings_level = types.map_of types.string, types.one_of {
types.string / parse_tags\match * convert_syntax
if args.nested
types.proxy -> strings_level
}
document = types.map_of types.string, strings_level
print json.encode assert document\transform output
when "lua"
if args.git
print "-- Generated file: commit #{get_git_hash!}"
print (compile.tree {
{"return", encode_value output}
})
else
error "unknown format: #{args.format}"