|
| 1 | +#!/usr/bin/env python |
| 2 | +# |
| 3 | +# This python file contains utility functions to manage a Python docs translation |
| 4 | +# with Transifex. |
| 5 | +# |
| 6 | +# This file is maintained at: https://github.com/python-docs-translations/transifex-automations/blob/main/sample-workflows/transifex-util.py |
| 7 | + |
| 8 | +importconfigparser |
| 9 | +fromargparseimportArgumentParser |
| 10 | +importos |
| 11 | +fromcontextlibimportchdir |
| 12 | +frompathlibimportPath |
| 13 | +fromsubprocessimportcall |
| 14 | +importsys |
| 15 | +fromtempfileimportTemporaryDirectory |
| 16 | + |
| 17 | + |
| 18 | +deffetch(): |
| 19 | +""" |
| 20 | + Fetch translations from Transifex, remove source lines. |
| 21 | + """ |
| 22 | +if (code:=call("tx --version",shell=True))!=0: |
| 23 | +sys.stderr.write("The Transifex client app is required.\n") |
| 24 | +exit(code) |
| 25 | +lang=LANGUAGE |
| 26 | +_call(f"tx pull -l{lang} --force")# XXX Do we pull everything? |
| 27 | +forfileinPath().rglob("*.po"): |
| 28 | +_call(f"msgcat --no-location -o{file}{file}") |
| 29 | + |
| 30 | + |
| 31 | +def_call(command:str): |
| 32 | +if (return_code:=call(command,shell=True))!=0: |
| 33 | +exit(return_code) |
| 34 | + |
| 35 | + |
| 36 | +defrecreate_tx_config(): |
| 37 | +""" |
| 38 | + Regenerate Transifex client config for all resources. |
| 39 | + """ |
| 40 | +withTemporaryDirectory()asdirectory: |
| 41 | +withchdir(directory): |
| 42 | +_clone_cpython_repo(VERSION) |
| 43 | +_build_gettext() |
| 44 | +withchdir(Path(directory)/"cpython/Doc/build"): |
| 45 | +_create_txconfig() |
| 46 | +_update_txconfig_resources() |
| 47 | +withopen(".tx/config","r")asfile: |
| 48 | +contents=file.read() |
| 49 | +contents=contents.replace("./<lang>/LC_MESSAGES/","") |
| 50 | +withopen(".tx/config","w")asfile: |
| 51 | +file.write(contents) |
| 52 | + |
| 53 | + |
| 54 | +defdelete_obsolete_files(): |
| 55 | +files_to_delete=list(_get_files_to_delete()) |
| 56 | +ifnotfiles_to_delete: |
| 57 | +return |
| 58 | +else: |
| 59 | +forfileinfiles_to_delete: |
| 60 | +print(f"Removing{file}") |
| 61 | +os.remove(file) |
| 62 | +_call(f'git rm --quiet "{file}"') |
| 63 | + |
| 64 | + |
| 65 | +def_get_files_to_delete(): |
| 66 | +withopen(".tx/config")asconfig_file: |
| 67 | +config=config_file.read() |
| 68 | +forfileinPath().rglob("*.po"): |
| 69 | +ifos.fsdecode(file)notinconfig: |
| 70 | +yieldos.fsdecode(file) |
| 71 | + |
| 72 | + |
| 73 | +def_clone_cpython_repo(version:str): |
| 74 | +_call( |
| 75 | +f"git clone -b{version} --single-branch https://github.com/python/cpython.git --depth 1" |
| 76 | + ) |
| 77 | + |
| 78 | + |
| 79 | +def_build_gettext(): |
| 80 | +_call("make -C cpython/Doc/ gettext") |
| 81 | + |
| 82 | + |
| 83 | +def_create_txconfig(): |
| 84 | +_call("sphinx-intl create-txconfig") |
| 85 | + |
| 86 | + |
| 87 | +def_update_txconfig_resources(): |
| 88 | +_call( |
| 89 | +f"sphinx-intl update-txconfig-resources --transifex-organization-name python-doc " |
| 90 | +f"--transifex-project-name{PROJECT_SLUG} --locale-dir . --pot-dir gettext" |
| 91 | + ) |
| 92 | + |
| 93 | + |
| 94 | +def_get_tx_token()->str: |
| 95 | +ifos.path.exists(".tx/api-key"): |
| 96 | +withopen(".tx/api-key")asf: |
| 97 | +returnf.read() |
| 98 | + |
| 99 | +config=configparser.ConfigParser() |
| 100 | +config.read(os.path.expanduser("~/.transifexrc")) |
| 101 | +try: |
| 102 | +returnconfig["https://www.transifex.com"]["token"] |
| 103 | +exceptKeyError: |
| 104 | +pass |
| 105 | + |
| 106 | +returnos.getenv("TX_TOKEN","") |
| 107 | + |
| 108 | + |
| 109 | +if__name__=="__main__": |
| 110 | +RUNNABLE_SCRIPTS= ("fetch","recreate_tx_config","delete_obsolete_files") |
| 111 | + |
| 112 | +parser=ArgumentParser() |
| 113 | +parser.add_argument("cmd",choices=RUNNABLE_SCRIPTS) |
| 114 | +parser.add_argument("--language",required=True) |
| 115 | +parser.add_argument("--project-slug",required=True) |
| 116 | +parser.add_argument("--version",required=True) |
| 117 | + |
| 118 | +options=parser.parse_args() |
| 119 | + |
| 120 | +LANGUAGE=options.language |
| 121 | +PROJECT_SLUG=options.project_slug |
| 122 | +VERSION=options.version |
| 123 | + |
| 124 | +globals()[options.cmd]() |