-
Notifications
You must be signed in to change notification settings - Fork 2
/
translate.py
executable file
·206 lines (159 loc) · 9.7 KB
/
translate.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
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
#!/usr/bin/env python3.6
#-*- coding:utf-8 -*-
import re
# подцепляем словарь из внешнего файла
import dicts.dicts as d
def replace_lang(text, dic):
"""Заменялка для языков"""
text = text.replace("Languages:", "Languages")
if "---" in text:
return "Языки ---"
langru = "Языки "
langs = text.replace("Languages ", "").split(",")
for lang in langs:
lang = lang.strip()
try:
langru = langru + dic[lang] + ", "
except:
langru = langru + lang.capitalize() + ", "
return langru[:-2]
def replace_other(line, dic):
"""Заменяем всё подряд, что не попало под другие фильтры"""
for i, j in dic.items():
line = line.replace(i, j)
return line
def replace_other_lower(line, dic):
"""
Заменяем всё подряд, что не попало под другие фильтры но в нижнем регистре
Используется в замене заклинаний
"""
for i, j in dic.items():
line = line.replace(i.lower(), j.lower())
return line
def fix_symbols(line):
"""Эта хрень нужна для исправления отображения разных символов"""
line = line.replace(b'\xc3\xa2\xc2\x88\xc2\x92'.decode('utf-8'), "-").\
replace(b'\xc3\xa2\xc2\x80\xc2\x99'.decode('utf-8'), "'").\
replace('¬', '').\
replace('¬', '').\
replace("’", "'").\
replace("+O", "+0").\
replace("+l", "+1")
return line
def replace_cr(line):
match = re.search(r"Challenge[\s:]+(?P<cr>[\d\/]+)\s\((?P<xp>[\d\s,]+)\sXP\)?", line)
if match:
cr = str(match.group('cr'))
xp = int(match.group('xp').replace(" ", "").replace(",", ""))
line = "Опасность {cr} ({xp} опыта)".format(cr=cr, xp=xp)
return line
def replace_multiattack(line):
line = line.replace("Multiattack", "Мультиатака").replace("melee attacks", "рукопашные атаки").\
replace("ranged attacks", "дальнобойные атаки").replace("attacks", "атаки").replace("makes", "совершает").\
replace("two", "две").replace("three", "три").replace("one with", "одну с помощью")
return line
def translate_spell(line, dic):
line = line.replace(";", ",").replace(":", ",")
spell_list = line.split(",")
newline = "{}:".format(spell_list[0])
for spell in spell_list[1:]:
spell_ru = replace_other_lower(spell.replace("'", "").strip(), d.spell_dict)
newline = "{0} {1} [{2}], ".format(newline.strip(), spell_ru.strip(), spell.strip())
newline = replace_other(newline, dic)
newline = newline.replace("Wisdom", "Мудрости").replace("Intelligence", "Интеллекте").\
replace("Charisma", "Харизме").replace("druid", "друида").replace("wizard", "чародея").\
replace("bard", "барда").replace("cleric", "жреца").replace("paladin", "паладина").\
replace("rander", "ренжера").replace("sorcerer", "волшебника").replace("warlock", "колдуна")
return newline[:-2]
def replacer(text, dic):
"""Основная функция, которая делает всю работу. В том числе запускает другие функции"""
translated_text = ""
for line in text.splitlines():
line = fix_symbols(line)
line_lower = line.lower()
if re.search("^languages", line_lower.strip(), re.IGNORECASE):
line = replace_lang(line, d.lang_dict)
elif "multiattack" in line_lower:
line = replace_multiattack(line)
elif "challenge" in line_lower:
line = replace_cr(line)
elif re.search("Cantrip|[\d\w\s]{4}level|\d\/day\seach|At\swill", line, re.IGNORECASE):
line = translate_spell(line, dic)
elif "innate spellcasting" in line_lower:
match = re.search(r"Innate Spellcasting. (?P<name>[\s\w\']+) innate spellcasting ability is (?P<abil>[\w]+)(?:[\s\(\w]+DC\s+(?P<dc>\d+)\)|)\.\s+(?:[\w\s]+) can innately cast the following spells, requiring (?P<comp>[\w\s]+) components", line)
if match:
name = str(match.group("name"))
abil = str(match.group("abil")).replace("Wisdom", "Мудрости").replace("Intelligence", "Интеллекте").\
replace("Charisma", "Харизме")
if match.group('dc'):
dc = int(match.group("dc"))
else:
dc = None
comp = str(match.group("comp"))
if dc:
save = " (спас бросок Сл {dc})".format(dc=dc)
else:
save = ""
line = "Врождённое колдовство. Базовой характеристикой {name} является {abil}{save}. Он может накладывать следующие заклинания, не нуждаясь {comp} компонентах"\
.format(name=name, abil=abil, save=save, comp=comp)
elif "spellcasting" in line_lower:
line = re.sub(r"Spellcasting. ([\s\w]+) is a.? ([\d]+)[\w]+-level spellcaster.",
r"Использование заклинаний. \1 является заклинателем \2 уровня.",
line)
line = re.sub(r"(?:[\s\w]+)spellcasting ability is (\w+) \(spell save(?:\sDC|)\s(\d+), ([\d+]+) to hit with spell attacks\).",
r" Его способность к заклинаниям основана на \1 (Сл спасброска от заклинаний \2, \3 к атакам заклинаниями).",
line)
line = re.sub(r"([\s\w]+) has the following (?:(\w+)\s|)spells prepared",
r"\1 обладает следующими заготовленными заклинаниями \2",
line)
else:
"""Замена всего оставшегося"""
line = replace_other(line, dic)
# elif "pack tactics" in line_lower:
line = re.sub(r"Pack Tactics. ([\s\w]+) has advantage on an attack roll against a creature if at least one of ([\s\w]+) allies.+",
r"Тактика стаи. \1 совершает с преимуществом броски атаки по существу, если в пределах 5 футов от этого существа находится как минимум один дееспособный союзник \2",
line)
# elif "keen smell" in line_lower:
line = re.sub(r"Keen Smell. ([\s\w]+) has advantage on Wisdom \(Perception\) checks that rely on smell",
r"Тонкий нюх. \1 совершает с преимуществом проверки Мудрости (Внимательность), полагающиеся на обоняние",
line)
# elif "keen sight and smell" in line_lower:
line = re.sub(r"Keen Sight and Smell. ([\s\w]+) has advantage on Wisdom \(Perception\) checks that rely on sight or smell.+",
r"Острый слух и тонкий нюх. \1 совершает с преимуществом проверки Мудрости (Внимательность), полагающиеся на слух и обоняние",
line)
line = re.sub(r"Change Shape. ([\s\w]+) magically polymorphs into a ([\s\w]+) it has seen, or back into its true form.",
r"Смена формы. \1 магическим образом превращается в \2, которого видел, или принимает свой истинный облик.",
line)
line = re.sub(r"The target must make a DC (\d+) (\w+) saving throw",
r"Цель должна совершить спасбросок \2 со Сл \1",
line)
line = re.sub(r"If the target is a creature, it must succeed on a DC (\d+) Strength saving throw or be knocked prone",
r"Если цель — существо, она должна преуспеть в спасброске Силы со Сл \1, иначе будет сбита с ног",
line)
# else:
# print(line_lower)
"""Исправление неправильных кубов"""
line = re.sub(r"(l)d([012468]{1,2})", r"1к\2", line)
line = re.sub(r"(lO)d([012468]{1,2})", r"10к\2", line)
line = re.sub(r"(ll)d([012468]{1,2})", r"11к\2", line)
line = re.sub(r"(S)d([012468]{1,2})", r"5к\2", line)
"""Замена кубов по всему тексту"""
line = re.sub(r"(\d+)d(\d+)", r"\1к\2", line)
"""Собираем текст заново построчно (с виндовым переносом строки)"""
translated_text = translated_text + "\r\n" + line
return translated_text
def main():
import sys
input_text = None
filename = None
try:
filename = sys.argv[1]
except IndexError:
print("Should specify input filename")
sys.exit(1)
with open(filename, 'r') as f:
input_text = f.read()
translated_text = replacer(input_text, d.all_dict)
print(translated_text)
if __name__ == "__main__":
main()