#!/usr/bin/env python3 try: from translatepy import Translator, Language except ModuleNotFoundError: print('You need to install translatepy. If you have no better idea, try:') print('pip install translatepy') exit(1) import argparse import io import os from pathlib import Path import polib import sys import textwrap import time # Available Translators from translatepy from translatepy.translators import (BaseTranslator, BingTranslate, DeeplTranslate, GoogleTranslate, LibreTranslate, MyMemoryTranslate, ReversoTranslate, TranslateComTranslate, YandexTranslate, MicrosoftTranslate) _my_name = os.path.basename(__file__) _my_input_default = 'my_strings.po' _my_output_default = 'auto_strings.po' DESCRIPTION = """ You may need to install translatepy, e.g. > pip install translatepy Opens the INFILE, assumed to be in 'english', and the needed language selected as --language Replace all (-r), or just fill in the missing translations ('msgstr':s), and save to OUTFILE """ USAGE_EXAMPLE = f""" Examples: > ./{_my_name} -i input.pot -l danish -o output.da.po > ./{_my_name} -i input.po -l danish -o output.da.po --replace In case you did not get them all, or already have most of them: > ./{_my_name} -i test.da.po -l danish -o test.da.po """ def parse_arguments(): parser = argparse.ArgumentParser(_my_name, formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent(DESCRIPTION), epilog=textwrap.dedent(USAGE_EXAMPLE)) add = parser.add_argument add('-r', '--replace', action='store_true', help='replace all translations (if using a .po file)') add('-q', '--quiet', action='store_true', help='be more quiet') add('-v', '--verbose', action='store_true', help='be more verbose') add('-l', '--language', metavar='LANGUAGE', help='select language') add('-i', '--input', metavar='INFILE', required=True, help='.po or .pot file for extraction') add('-o', '--output', metavar='OUTFILE', default=_my_output_default, help='output .po file with results') return parser.parse_args() def has_valid_text(the_string): if the_string.isspace(): return False if len(the_string): return True return False def translate_gettext_file(file_name, language, options): ''' Look for msgid's then translate their msgstr to language, note that these files are (expected to be) coded as UTF-8 ''' pofile = polib.pofile(file_name) translator = Translator() #translator = Translator([GoogleTranslate]) # Check if language is supported assert Language(language) translations = 0 fails = 0 result = 'FAIL' for entry in pofile: source = entry.msgid if options.verbose: print(f'In: "{source}"') else: print('.', end="") if not source: continue if not has_valid_text(source): result = source else: if not options.replace: if has_valid_text(entry.msgstr): result = entry.msgstr if options.verbose: print(f'Keeping: {result}\n') continue retries = 5 untranslated = True while retries: try: proposal = translator.translate(source, language, 'english') result = proposal.result translator = proposal.service except: retries -= 1 print(f'Exception, will try {retries} more after sleeping') time.sleep(1) result = "" else: untranslated = False translations += 1 retries = 0 if options.verbose: print(f'Got: {result}\nTranslated by: {translator}\n') if untranslated: fails += 1 entry.msgstr = result if not options.verbose: print() print(f'Did {translations} translations') if fails: print(f'Left {fails} translations empty, rerun with -f') else: print('Everything is translated') if translations: pofile.save(options.output) else: print(' or did you forget --replace?') def main(options): # To be able to make debug-printout #sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding = 'utf-8') #sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding = 'utf-8') input_file_name = options.input if not os.path.exists(input_file_name): print(f'{options.input}, from the -i option, does not exist - giving up') exit(3) start = time.time() translate_gettext_file(input_file_name, options.language, options) end = time.time() print('Total time:', end - start, 's') if __name__ == '__main__': main(parse_arguments())