Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite57d72a

Browse files
authored
Add a script for machine-translation (python#76)
This script can be very handy for translating highly-viewed yet not translated documents. But it will require human review for sure.
1 parent4777eba commite57d72a

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

‎requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ poutils
22
tqdm
33
pre-commit
44
polib
5+
deep_translator

‎scripts/translate.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
importos
2+
importre
3+
importsys
4+
importpolib
5+
fromdeep_translatorimportDeeplTranslator,GoogleTranslator
6+
fromtypingimportDict,Tuple
7+
fromargparseimportArgumentParser
8+
9+
parser=ArgumentParser()
10+
parser.add_argument("filename",help="File to translate")
11+
parser.add_argument("-t","--translator",choices=["google","deepl"],default="deepl",help="Translator to use")
12+
parser.add_argument(
13+
"-a",
14+
"--api-key",
15+
required="deepl"inlist(map(lambdax:x.casefold(),sys.argv)),
16+
help="API key for DeepL (required if using DeepL)",
17+
)
18+
parser.add_argument("-v","--verbose",action="store_true",help="Verbose mode")
19+
parser.add_argument("-d","--debug",action="store_true",help="Debug mode")
20+
parser.add_argument("-s","--skip-translated-entries",choices=[True,False],default=True,help="Skip already translated entries")
21+
22+
args=parser.parse_args()
23+
24+
VERBOSE=args.verbose
25+
DEBUG=args.debug
26+
SKIP_TRANSLATED_ENTRIES=args.skip_translated_entries
27+
28+
29+
_patterns= [
30+
":c:func:`[^`]+`",
31+
":c:type:`[^`]+`",
32+
":c:macro:`[^`]+`",
33+
":c:member:`[^`]+`",
34+
":c:data:`[^`]+`",
35+
":py:data:`[^`]+`",
36+
":py:mod:`[^`]+`",
37+
":func:`[^`]+`",
38+
":mod:`[^`]+`",
39+
":ref:`[^`]+`",
40+
":class:`[^`]+`",
41+
":pep:`[^`]+`",
42+
":data:`[^`]+`",
43+
":exc:`[^`]+`",
44+
":term:`[^`]+`",
45+
":meth:`[^`]+`",
46+
":envvar:`[^`]+`",
47+
":file:`[^`]+`",
48+
":attr:`[^`]+`",
49+
":const:`[^`]+`",
50+
":issue:`[^`]+`",
51+
":opcode:`[^`]+`",
52+
":option:`[^`]+`",
53+
":program:`[^`]+`",
54+
":keyword:`[^`]+`",
55+
":RFC:`[^`]+`",
56+
":rfc:`[^`]+`",
57+
":doc:`[^`]+`",
58+
":source:`[^`]+`",
59+
":manpage:`[^`]+`",
60+
":mimetype:`[^`]+`",
61+
":sup:`[^`]+`",
62+
":kbd:`[^`]+`",
63+
":const:`[^`]+`",
64+
"``[^`]+``",
65+
"`[^`]+`__",
66+
"`[^`]+`_",
67+
r"\*\*[^\*]+\*\*",# bold text between **
68+
r"\*[^\*]+\*",# italic text between *
69+
]
70+
71+
_exps= [re.compile(e)forein_patterns]
72+
73+
74+
defprotect_sphinx_directives(s:str)->Tuple[dict,str]:
75+
"""
76+
Parameters:
77+
string containing the text to translate
78+
Returns:
79+
dictionary containing all the placeholder text as keys
80+
and the correct value.
81+
"""
82+
83+
d:Dict[str,str]= {}
84+
forindex,expinenumerate(_exps):
85+
matches=exp.findall(s)
86+
ifDEBUG:
87+
print(exp,matches)
88+
formatchinmatches:
89+
ph=f"XASDF{str(index).zfill(2)}"
90+
s=s.replace(match,ph)
91+
ifphindandVERBOSE:
92+
print(f"Error:{ph} is already in the dictionary")
93+
print("new",match)
94+
print("old",d[ph])
95+
d[ph]=match
96+
returnd,s
97+
98+
99+
defundo_sphinx_directives_protection(placeholders:dict,translated_text:str)->str:
100+
forph,valueinplaceholders.items():
101+
translated_text=translated_text.replace(ph,value)
102+
ifDEBUG:
103+
print(ph,value)
104+
print(translated_text)
105+
returntranslated_text
106+
107+
108+
if__name__=="__main__":
109+
filename=args.filename
110+
ifnotos.path.isfile(filename):
111+
print(f"File not found: '{filename}'")
112+
sys.exit(-1)
113+
114+
po=polib.pofile(filename)
115+
116+
ifargs.translator.lower()=="google":
117+
translator=GoogleTranslator(source="en",target="tr")
118+
elifargs.translator.lower()=="deepl":
119+
translator=DeeplTranslator(api_key=args.api_key,source="en",target="tr",use_free_api=True)
120+
else:
121+
raiseValueError("Invalid translator")
122+
123+
forentryinpo:
124+
# If the entry has already a translation, skip.
125+
ifSKIP_TRANSLATED_ENTRIESandentry.msgstr:
126+
continue
127+
128+
print("\nEN |",entry.msgid)
129+
placeholders,temp_text=protect_sphinx_directives(entry.msgid)
130+
ifVERBOSE:
131+
print(temp_text)
132+
print(placeholders)
133+
134+
# Translate the temporary text without sphinx statements
135+
translated_text=translator.translate(temp_text)
136+
137+
# Recover sphinx statements
138+
real_text=undo_sphinx_directives_protection(placeholders,translated_text)
139+
print("TR |",real_text)
140+
141+
# Replace the po file translated entry
142+
entry.msgstr=real_text
143+
144+
# Add fuzzy flag so a real-human can review later
145+
entry.flags.append("fuzzy")
146+
147+
# Save the file after all the entries are translated
148+
po.save()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp