Russian narration for the Enshrouded notes: mod 0.4.0, installer, generation pipeline

This commit is contained in:
2026-10-18 15:56:52 +03:00
commit 73dee2d786
557 changed files with 4051 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
import re
U=["ноль","один","два","три","четыре","пять","шесть","семь","восемь","девять","десять","одиннадцать","двенадцать","тринадцать","четырнадцать","пятнадцать","шестнадцать","семнадцать","восемнадцать","девятнадцать"]
T=["","","двадцать","тридцать","сорок","пятьдесят","шестьдесят","семьдесят","восемьдесят","девяносто"]
H=["","сто","двести","триста","четыреста","пятьсот","шестьсот","семьсот","восемьсот","девятьсот"]
def card(n):
if n<20: return U[n]
if n<100: return (T[n//10]+(" "+U[n%10] if n%10 else ""))
if n<1000: return (H[n//100]+(" "+card(n%100) if n%100 else ""))
if n<1000000:
th,r=divmod(n,1000); t=th%10; tt=th%100
w=card(th) if th>2 or th>=20 else ""
if th==1: w="одна тысяча"
elif th==2: w="две тысячи"
else:
w=card(th)
w=re.sub(r"один$","одна",w); w=re.sub(r"два$","две",w)
w+=" "+("тысяча" if t==1 and tt!=11 else "тысячи" if 2<=t<=4 and not 12<=tt<=14 else "тысяч")
return w+(" "+card(r) if r else "")
return str(n)
ORD={"ноль":"нулев","один":"перв","два":"втор","три":"трет","четыре":"четвёрт","пять":"пят","шесть":"шест","семь":"седьм","восемь":"восьм","девять":"девят","десять":"десят","одиннадцать":"одиннадцат","двенадцать":"двенадцат","тринадцать":"тринадцат","четырнадцать":"четырнадцат","пятнадцать":"пятнадцат","шестнадцать":"шестнадцат","семнадцать":"семнадцат","восемнадцать":"восемнадцат","девятнадцать":"девятнадцат","двадцать":"двадцат","тридцать":"тридцат","сорок":"сороков","пятьдесят":"пятидесят","шестьдесят":"шестидесят","семьдесят":"семидесят","восемьдесят":"восьмидесят","девяносто":"девяност","сто":"сот","двести":"двухсот","триста":"трёхсот","четыреста":"четырёхсот","пятьсот":"пятисот","шестьсот":"шестисот","семьсот":"семисот","восемьсот":"восьмисот","девятьсот":"девятисот","тысяча":"тысячн","тысячи":"тысячн","тысяч":"тысячн"}
# ending by case/gender: suffix of written form -> ending (hard stem / трет soft)
END={"й":"ый","го":"ого","му":"ому","м":"ом","е":"ое","я":"ая","ю":"ую","х":"ых","ми":"ыми"}
def ordinal(n,suf):
ws=card(n).split(); last=ws[-1]; stem=ORD.get(last,last)
e=END.get(suf,"ый")
if stem=="трет": e={"ый":"ий","ого":"ьего","ому":"ьему","ом":"ьем","ое":"ье","ая":"ья","ую":"ью","ых":"ьих","ыми":"ьими"}[e]
elif stem in("втор","сороков") or stem.endswith(("тысячн",)):
e=e.replace("ый","ой") if stem=="втор" or stem=="сороков" else e
if e=="ый" and stem in("втор","шест","седьм","восьм","сороков"): e="ой"
return " ".join(ws[:-1]+[stem+e])
def normalize(t):
t=t.replace("\xa0"," ").replace("•","").replace("*","").replace("_"," ").replace("–",",").replace("№","номер ")
t=re.sub(r"(\d+)%",lambda m:card(int(m[1]))+" процентов",t)
t=re.sub(r"\b(\d+)-(й|го|му|м|е|я|ю|х|ми)\b",lambda m:ordinal(int(m[1]),m[2]),t)
t=re.sub(r"\b(\d+)\s+(году|года|год|годом)\b",lambda m:ordinal(int(m[1]),{"году":"м","года":"го","год":"й","годом":"м"}[m[2]])+" "+m[2],t)
t=re.sub(r"^\s*(\d+)\.\s",lambda m:card(int(m[1]))+". ",t,flags=re.M)
t=re.sub(r"\d+",lambda m:card(int(m[0])),t)
t=re.sub(r"[ \t]{2,}"," ",t)
return t
if __name__=="__main__":
for s in ["в 508 году","3-й ярус","341-го дня","34% урожая","1200 монет","1. Первое","до 507 года","2-ю неделю","3-е место","21 кролик"]: print(s,"->",normalize(s))