-
Notifications
You must be signed in to change notification settings - Fork 39
/
dictgen.py
executable file
·165 lines (130 loc) · 5.07 KB
/
dictgen.py
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
#!/usr/bin/env python3
# dictgen.py -- VGUI2 dictionary generator
# Copyright(C) 2019 a1batross
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
import os
import sys
import re
EXTENSIONS = ('.cpp', '.h')
EXCLUDE_FILES = ('./sdk_includes')
TRANSLATABLE_PATTERN = re.compile('[^a-zA-Z0-9_]L\s*\(\s*\".*?\"\s*\)')
STRING_LITERAL_PATTERN = re.compile('\".*?\"')
HEADER = '''// How to work with this file:
// 1) This file must be called mainui_x.txt, where x is your language in lower case
// 2) Tokens on left are original strings, on right is translation
// 3) StringsList_x where x is number is strings from strings.lst.
// Remove them if you want to use values from strings.lst
// 4) _everything.txt version of this file is intended to be used if you
// don't want to rely on strings.lst nor on non-free translations
// 5) _nostringslst.txt version of this file is intended to be used if you
// WANT to rely on strings.lst but still don't want non-free translations
// 6) _stripped.txt version of this file is intended to be used if you
// WANT to rely on original game files(both strings.lst and non-free translations)
"lang"
{
"Language" "<YOUR_LANGUAGE_HERE>"
"Tokens"
{
'''
FOOTER = '''}
}
'''
def process_file(name):
print('Processing %s...' % name)
trans = []
# TODO: dumb! It can't find multilines
with open(name, "r") as f:
for line in f.readlines():
trans += re.findall(TRANSLATABLE_PATTERN, line)
return trans
def strip_quotes(s):
return s[s.find('"') + 1 : s.rfind('"')]
def process_trans(trans):
def extract_string_literal(s):
return "".join(re.split(STRING_LITERAL_PATTERN, strip_quotes(s)))
# #1: extract string literals from L(" ") and combine them into one
trans = [extract_string_literal(t) for t in trans]
# #2: filter unique
trans = list(set(trans))
# #4: sort :)
trans.sort()
return trans
def vgui_translation_parse(name):
trans = []
parsing = False
isUtf16 = False
with open(name, "rb") as f:
BOM = f.read(2)
if BOM == b'\xFF\xFE':
isUtf16 = True
with open(name, "r", encoding = 'utf-16' if isUtf16 else 'utf-8') as f:
contents = f.read()
strings = re.findall(STRING_LITERAL_PATTERN, contents)
is_trans = True
for t in strings:
if not parsing:
if t == '"Tokens"':
parsing = True # now wait for strings
continue
if parsing and is_trans:
trans += [strip_quotes(t)]
is_trans = not is_trans
return trans
def create_translations_file(name, trans):
maxlength = min(72, len(max(trans, key=len)) + 1)
# we are working in UTF-8, it's easier to handle than UTF-16
with open(name, "w", encoding = 'utf-8',newline = '\r\n') as f:
f.write(HEADER)
for t in trans:
length = max(1, maxlength - len(t))
f.write('"%s"%*s""\n' % (t, length, ' '))
f.write(FOOTER)
print('Created skeleton translation file at %s' % name)
def main():
files = [ os.path.join(folder, name)
for (folder, subs, files) in os.walk('.')
for name in files + subs
if name.endswith(EXTENSIONS) ]
files.sort()
trans = []
for f in files:
if f.startswith(EXCLUDE_FILES):
continue
trans += process_file(f)
trans = process_trans(trans)
print('%d strings needs to be translated(WITHOUT strings.lst compatibiltiy and WITHOUT non-free translations)' % len(trans))
create_translations_file(os.path.join('translations', 'mainui_skeleton_everything.txt'), trans)
trans = [t for t in trans if not t.startswith('StringsList_')]
print('%d strings needs to be translated(WITH strings.lst compatibiltiy and WITHOUT non-free translations)' % len(trans))
create_translations_file(os.path.join('translations', 'mainui_skeleton_nostringslst.txt'), trans)
nonfree_translations = None
try:
nonfree_translations = os.listdir('nonfree_translations')
except OSError:
# silently ignore...
pass
if nonfree_translations:
avail_trans = []
for i in nonfree_translations:
avail_trans += vgui_translation_parse(os.path.join('nonfree_translations', i))
print('%d translated strings available from original GameUI/HL translations' % len(avail_trans))
trans = [t for t in trans if not t in avail_trans]
print('%d strings needs to be translated(WITH strings.lst compaitibility and WITH non-free translations)' % len(trans))
create_translations_file(os.path.join('translations', 'mainui_skeleton_stripped.txt'), trans)
else:
def check_nonfree(s):
return (s.startswith('GameUI_') or s.startswith('Valve_') or s.startswith('Cstrike_'))
trans = [t for t in trans if not check_nonfree(t)]
print('%d strings needs to be translated(WITH strings.lst compaitibility and WITH non-free translations)' % len(trans))
create_translations_file(os.path.join('translations', 'mainui_skeleton_stripped.txt'), trans)
if __name__ == '__main__':
main()