123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- #!/usr/bin/env python3
- try:
- from simplytranslate_engines.googletranslate import GoogleTranslateEngine
- from simplytranslate_engines.utils import to_lang_code
- except ModuleNotFoundError:
- print('You need to install SimplyTranslate-Engines. If you have no better idea, try:')
- print('pip install git+https://codeberg.org/SimpleWeb/SimplyTranslate-Engines')
- exit(1)
- import asyncio
- import argparse
- import io
- import os
- from pathlib import Path
- import polib
- import sys
- import textwrap
- import time
- # Available Translators from SimplyTranslate-Engines
- '''
- from simplytranslate_engines.libretranslate import LibreTranslateEngine
- from simplytranslate_engines.googletranslate import GoogleTranslateEngine
- from simplytranslate_engines.icibatranslate import IcibaTranslateEngine
- from simplytranslate_engines.deepl import DeeplEngine
- from simplytranslate_engines.reverso import ReversoTranslateEngine
- '''
- _my_name = os.path.basename(__file__)
- _my_input_default = 'my_strings.po'
- _my_output_default = 'auto_strings.po'
- DESCRIPTION = """
- You may need to install SimplyTranslate-Engines, e.g.
- > pip install git+https://codeberg.org/SimpleWeb/SimplyTranslate-Engines
- 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 = GoogleTranslateEngine()
- # Remember to add instance URL for LibreTranslateEngine, api key is optional
- # Reference: https://codeberg.org/SimpleWeb/SimplyTranslate-CLI
- '''
- api_key = None
- if instance is None:
- instance = "https://libretranslate.de"
- elif not (instance.startswith("https://") or instance.startswith("http://")):
- instance = f"https://{instance}"
- if api_key is None:
- translator = LibreTranslateEngine(instance)
- else:
- translator = LibreTranslateEngine(instance, api_key=api_key)
- '''
- from_language = 'english'
- to_language = language
- # Check if language is supported
- async def get_languages():
- return await asyncio.gather(
- asyncio.create_task(to_lang_code(from_language, translator)),
- asyncio.create_task(to_lang_code(to_language, translator))
- )
- from_language, to_language = asyncio.run(get_languages())
- 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, from_language=from_language, to_language=to_language)
- result = asyncio.run(proposal)['translated-text']
- 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}\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())
|