From d271fac02cae550e8b051ac358465ad0894ec9fd Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Thu, 1 Aug 2024 18:10:26 -0300 Subject: [PATCH 01/14] Add script for handling translations --- babel.cfg | 1 + babel_runner.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 babel.cfg create mode 100755 babel_runner.py diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000..692580d --- /dev/null +++ b/babel.cfg @@ -0,0 +1 @@ +[jinja2: **.html] diff --git a/babel_runner.py b/babel_runner.py new file mode 100755 index 0000000..a6359af --- /dev/null +++ b/babel_runner.py @@ -0,0 +1,108 @@ +#!/usr/bin/venv python3 +"""Script for handling translations with Babel""" + +import argparse +import os +import subprocess +import tomllib + +PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Global variables used by pybabel below +DOMAIN = "messages" +COPYRIGHT_HOLDER = "Python Software Foundation" +LOCALES_DIR = os.path.relpath(os.path.join(PROJECT_DIR, "locales")) +POT_FILE = os.path.relpath(os.path.join(LOCALES_DIR, f"{DOMAIN}.pot"), PROJECT_DIR) +SOURCE_DIR = os.path.relpath( + os.path.join(PROJECT_DIR, "python_docs_theme"), PROJECT_DIR +) +MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, "babel.cfg"), PROJECT_DIR) + + +def get_project_info() -> dict: + """Retrieve project's info to populate the message catalog template""" + with open(os.path.join(PROJECT_DIR, "pyproject.toml"), "rb") as f: + data = tomllib.load(f) + return data["project"] + + +def extract_messages(): + """Extract messages from all source files into template file""" + os.makedirs(LOCALES_DIR, exist_ok=True) + project_data = get_project_info() + subprocess.run( + [ + "pybabel", + "extract", + "-F", + MAPPING_FILE, + "--copyright-holder", + COPYRIGHT_HOLDER, + "--project", + project_data["name"], + "--version", + project_data["version"], + "--msgid-bugs-address", + project_data["urls"]["Issue tracker"], + "-o", + POT_FILE, + SOURCE_DIR, + ], + check=True, + ) + + +def init_locale(locale: str): + """Initialize a new locale based on existing""" + cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale] + subprocess.run(cmd, check=True) + + +def update_catalogs(locale: str): + """Update translations from existing message catalogs""" + cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR] + if locale != "": + cmd.append(["-l", locale]) + subprocess.run(cmd, check=True) + + +def compile_catalogs(locale: str): + """Compile existing message catalogs""" + cmd = ["pybabel", "compile", "-d", LOCALES_DIR] + if locale != "": + cmd.append(["-l", locale]) + subprocess.run(cmd, check=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "command", + choices=["init", "extract", "update", "compile"], + help="command to be executed", + ) + parser.add_argument( + "-l", + "--locale", + help="language code (needed for init, optional for update and compile)", + ) + + args = parser.parse_args() + locale = args.locale if args.locale else "" + + os.chdir(PROJECT_DIR) + + if args.command == "extract": + extract_messages() + elif args.command == "init": + if locale == "": + parser.error("init requires passing the --locale option") + init_locale(locale) + elif args.command == "update": + update_catalogs(locale) + elif args.command == "compile": + compile_catalogs(locale) + + +if __name__ == "__main__": + main() From 634a20c0dc9d80f63f41352e74c4994cd6b47dfc Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Fri, 2 Aug 2024 13:31:25 -0300 Subject: [PATCH 02/14] Make ruff tests happy --- babel_runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/babel_runner.py b/babel_runner.py index a6359af..d447a16 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -1,9 +1,11 @@ #!/usr/bin/venv python3 """Script for handling translations with Babel""" +from __future__ import annotations import argparse import os import subprocess + import tomllib PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) From a809821c3fd5b06a081188c5c50f542da1676716 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Fri, 2 Aug 2024 15:29:19 -0300 Subject: [PATCH 03/14] Rename mapping file to .babel.cfg --- babel.cfg => .babel.cfg | 0 babel_runner.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename babel.cfg => .babel.cfg (100%) diff --git a/babel.cfg b/.babel.cfg similarity index 100% rename from babel.cfg rename to .babel.cfg diff --git a/babel_runner.py b/babel_runner.py index d447a16..039522f 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -18,7 +18,7 @@ SOURCE_DIR = os.path.relpath( os.path.join(PROJECT_DIR, "python_docs_theme"), PROJECT_DIR ) -MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, "babel.cfg"), PROJECT_DIR) +MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, ".babel.cfg"), PROJECT_DIR) def get_project_info() -> dict: From adf715c41dec595f51de89d752c21511f5ad7a6d Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Fri, 2 Aug 2024 17:19:10 -0300 Subject: [PATCH 04/14] Forbid initializing existent po --- babel_runner.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/babel_runner.py b/babel_runner.py index 039522f..ba5e351 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -29,7 +29,7 @@ def get_project_info() -> dict: def extract_messages(): - """Extract messages from all source files into template file""" + """Extract messages from all source files into message catalog template""" os.makedirs(LOCALES_DIR, exist_ok=True) project_data = get_project_info() subprocess.run( @@ -55,7 +55,11 @@ def extract_messages(): def init_locale(locale: str): - """Initialize a new locale based on existing""" + """Initialize a new locale based on existing message catalog template""" + pofile = os.path.join(LOCALES_DIR, locale, "LC_MESSAGES", f"{DOMAIN}.po") + if os.path.exists(pofile): + print(f"There is already a message catalog for locale {locale}, skipping.") + return cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale] subprocess.run(cmd, check=True) From 66820a55a24cc6188f52ca1f79c2272833e84f32 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Fri, 2 Aug 2024 17:21:13 -0300 Subject: [PATCH 05/14] Extend instead of append list for locale arg --- babel_runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/babel_runner.py b/babel_runner.py index ba5e351..386f34b 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -68,7 +68,7 @@ def update_catalogs(locale: str): """Update translations from existing message catalogs""" cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR] if locale != "": - cmd.append(["-l", locale]) + cmd.extend(["-l", locale]) subprocess.run(cmd, check=True) @@ -76,7 +76,7 @@ def compile_catalogs(locale: str): """Compile existing message catalogs""" cmd = ["pybabel", "compile", "-d", LOCALES_DIR] if locale != "": - cmd.append(["-l", locale]) + cmd.extend(["-l", locale]) subprocess.run(cmd, check=True) From 6b6f0d2787d30670a00ef4552d24ad1ebe5c7d3a Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Fri, 2 Aug 2024 17:22:24 -0300 Subject: [PATCH 06/14] Add translation tests to tests.yml --- .github/workflows/tests.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 70182f0..c551104 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,3 +48,36 @@ jobs: with: name: doc-html-${{ matrix.branch }} path: www/ + + translations: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "windows-latest"] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3 + allow-prereleases: true + cache: pip + - name: Install dependencies + run: | + pip install -U pip setuptools + pip install Babel jinja2 + - run: python3 babel_runner.py extract + - run: python3 babel_runner.py init -l pt_BR + - run: python3 babel_runner.py update + - run: python3 babel_runner.py update -l pt_BR + - run: python3 babel_runner.py compile + - run: python3 babel_runner.py compile -l pt_BR + - name: Print .pot file + shell: bash + run: cat locales/messages.pot + - name: Print .po file + shell: bash + run: cat locales/pt_BR/LC_MESSAGES/messages.po + - name: list files in locales dir + shell: bash + run: ls -R locales/ From 7878f4e51fbd79310a1cf7d8653ea5c20817fa11 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Sat, 3 Aug 2024 14:45:45 -0300 Subject: [PATCH 07/14] Use python instead of python3 to run babel_runner.py Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> --- .github/workflows/tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c551104..62b1f3c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -64,14 +64,14 @@ jobs: cache: pip - name: Install dependencies run: | - pip install -U pip setuptools - pip install Babel jinja2 - - run: python3 babel_runner.py extract - - run: python3 babel_runner.py init -l pt_BR - - run: python3 babel_runner.py update - - run: python3 babel_runner.py update -l pt_BR - - run: python3 babel_runner.py compile - - run: python3 babel_runner.py compile -l pt_BR + pip install --upgrade pip + pip install Babel jinja2 setuptools + - run: python babel_runner.py extract + - run: python babel_runner.py init -l pt_BR + - run: python babel_runner.py update + - run: python babel_runner.py update -l pt_BR + - run: python babel_runner.py compile + - run: python babel_runner.py compile -l pt_BR - name: Print .pot file shell: bash run: cat locales/messages.pot From 1fbd5d07695a6b6b58fd114c8de6d5133e9073a8 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Sat, 3 Aug 2024 15:25:06 -0300 Subject: [PATCH 08/14] Replace os with pahlib in babe_runner.py --- babel_runner.py | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/babel_runner.py b/babel_runner.py index 386f34b..ede0657 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -3,34 +3,32 @@ from __future__ import annotations import argparse -import os import subprocess +from pathlib import Path import tomllib -PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) +PROJECT_DIR = Path(__file__).resolve().parent -# Global variables used by pybabel below +# Global variables used by pybabel below (paths relative to PROJECT_DIR) DOMAIN = "messages" COPYRIGHT_HOLDER = "Python Software Foundation" -LOCALES_DIR = os.path.relpath(os.path.join(PROJECT_DIR, "locales")) -POT_FILE = os.path.relpath(os.path.join(LOCALES_DIR, f"{DOMAIN}.pot"), PROJECT_DIR) -SOURCE_DIR = os.path.relpath( - os.path.join(PROJECT_DIR, "python_docs_theme"), PROJECT_DIR -) -MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, ".babel.cfg"), PROJECT_DIR) +LOCALES_DIR = "locales" +POT_FILE = Path(LOCALES_DIR, f"{DOMAIN}.pot") +SOURCE_DIR = "python_docs_theme" +MAPPING_FILE = ".babel.cfg" def get_project_info() -> dict: """Retrieve project's info to populate the message catalog template""" - with open(os.path.join(PROJECT_DIR, "pyproject.toml"), "rb") as f: + with open(Path(PROJECT_DIR / "pyproject.toml"), "rb") as f: data = tomllib.load(f) return data["project"] def extract_messages(): """Extract messages from all source files into message catalog template""" - os.makedirs(LOCALES_DIR, exist_ok=True) + Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True) project_data = get_project_info() subprocess.run( [ @@ -50,18 +48,19 @@ def extract_messages(): POT_FILE, SOURCE_DIR, ], + cwd=PROJECT_DIR, check=True, ) def init_locale(locale: str): """Initialize a new locale based on existing message catalog template""" - pofile = os.path.join(LOCALES_DIR, locale, "LC_MESSAGES", f"{DOMAIN}.po") - if os.path.exists(pofile): + pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po" + if pofile.exists(): print(f"There is already a message catalog for locale {locale}, skipping.") return cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale] - subprocess.run(cmd, check=True) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) def update_catalogs(locale: str): @@ -69,7 +68,7 @@ def update_catalogs(locale: str): cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR] if locale != "": cmd.extend(["-l", locale]) - subprocess.run(cmd, check=True) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) def compile_catalogs(locale: str): @@ -77,7 +76,7 @@ def compile_catalogs(locale: str): cmd = ["pybabel", "compile", "-d", LOCALES_DIR] if locale != "": cmd.extend(["-l", locale]) - subprocess.run(cmd, check=True) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) def main(): @@ -96,8 +95,6 @@ def main(): args = parser.parse_args() locale = args.locale if args.locale else "" - os.chdir(PROJECT_DIR) - if args.command == "extract": extract_messages() elif args.command == "init": From e3e08ebcc6c1201302d73808c7fd8d324501af55 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Sat, 3 Aug 2024 15:58:51 -0300 Subject: [PATCH 09/14] Add tomli import to support python<3.11 --- babel_runner.py | 10 +++++++++- requirements.txt | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 requirements.txt diff --git a/babel_runner.py b/babel_runner.py index ede0657..4d51b64 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -6,7 +6,15 @@ import subprocess from pathlib import Path -import tomllib +try: + import tomllib +except ImportError: + try: + import tomli as tomllib + except ImportError as ie: + raise ImportError( + "tomli or tomllib is required to parse pyproject.toml" + ) from ie PROJECT_DIR = Path(__file__).resolve().parent diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..18e6c17 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +# for babel_runner.py +setuptools +Babel +Jinja2 +tomli; python_version < "3.10" From a845398dc335c9cc37113caee4952d7f47e0913f Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Sat, 3 Aug 2024 16:01:18 -0300 Subject: [PATCH 10/14] CI test for minimum supported python version --- .github/workflows/tests.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 62b1f3c..e79a125 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -55,17 +55,19 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest", "windows-latest"] + # Test minimum supported and latest stable from 3.x series + python-version: ["3.8", "3"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: 3 + python-version: ${{ matrix.python-version }} allow-prereleases: true cache: pip - name: Install dependencies run: | pip install --upgrade pip - pip install Babel jinja2 setuptools + pip install -r requirements.txt - run: python babel_runner.py extract - run: python babel_runner.py init -l pt_BR - run: python babel_runner.py update From bd7c059d3f233b7e4c7035aba798135dcdf816e8 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Mon, 28 Oct 2024 08:23:22 -0300 Subject: [PATCH 11/14] Apply suggestions from code review Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Ezio Melotti --- .github/workflows/tests.yml | 2 +- babel_runner.py | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1c77087..a4dd522 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,7 +56,7 @@ jobs: matrix: os: ["ubuntu-latest", "windows-latest"] # Test minimum supported and latest stable from 3.x series - python-version: ["3.8", "3"] + python-version: ["3.9", "3"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/babel_runner.py b/babel_runner.py index 4d51b64..b90b57b 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -34,7 +34,7 @@ def get_project_info() -> dict: return data["project"] -def extract_messages(): +def extract_messages() -> None: """Extract messages from all source files into message catalog template""" Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True) project_data = get_project_info() @@ -61,7 +61,7 @@ def extract_messages(): ) -def init_locale(locale: str): +def init_locale(locale: str) -> None: """Initialize a new locale based on existing message catalog template""" pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po" if pofile.exists(): @@ -71,23 +71,23 @@ def init_locale(locale: str): subprocess.run(cmd, cwd=PROJECT_DIR, check=True) -def update_catalogs(locale: str): +def update_catalogs(locale: str) -> None: """Update translations from existing message catalogs""" cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR] - if locale != "": + if locale: cmd.extend(["-l", locale]) subprocess.run(cmd, cwd=PROJECT_DIR, check=True) -def compile_catalogs(locale: str): +def compile_catalogs(locale: str) -> None: """Compile existing message catalogs""" cmd = ["pybabel", "compile", "-d", LOCALES_DIR] - if locale != "": + if locale: cmd.extend(["-l", locale]) subprocess.run(cmd, cwd=PROJECT_DIR, check=True) -def main(): +def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "command", @@ -97,16 +97,17 @@ def main(): parser.add_argument( "-l", "--locale", + default="", help="language code (needed for init, optional for update and compile)", ) args = parser.parse_args() - locale = args.locale if args.locale else "" + locale = args.locale if args.command == "extract": extract_messages() elif args.command == "init": - if locale == "": + if not locale: parser.error("init requires passing the --locale option") init_locale(locale) elif args.command == "update": From 65a0360a32bce266ff8b9db49507347c5dbe3d1c Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Mon, 28 Oct 2024 08:51:19 -0300 Subject: [PATCH 12/14] Remove possibly existing translation file Otherwise init command will be skipped --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a4dd522..b0ce07c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,6 +68,8 @@ jobs: run: | pip install --upgrade pip pip install -r requirements.txt + - name: Remove locale file for testing + run: rm -rf locales/pt_BR/ - run: python babel_runner.py extract - run: python babel_runner.py init -l pt_BR - run: python babel_runner.py update From 69ab91731e63dc625ff1f7405391ac4b6354dc35 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Mon, 28 Oct 2024 09:25:07 -0300 Subject: [PATCH 13/14] Add shell bash to success in Windows --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b0ce07c..ace177e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -69,6 +69,7 @@ jobs: pip install --upgrade pip pip install -r requirements.txt - name: Remove locale file for testing + shell: bash run: rm -rf locales/pt_BR/ - run: python babel_runner.py extract - run: python babel_runner.py init -l pt_BR From 2aa3a04d209e7496e2c3f08d5a2db68b83fbf9fb Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Mon, 28 Oct 2024 09:37:18 -0300 Subject: [PATCH 14/14] Swap init and extract to be didactic As one need to have POT before initializing PO --- babel_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/babel_runner.py b/babel_runner.py index b90b57b..da4001c 100755 --- a/babel_runner.py +++ b/babel_runner.py @@ -91,7 +91,7 @@ def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "command", - choices=["init", "extract", "update", "compile"], + choices=["extract", "init", "update", "compile"], help="command to be executed", ) parser.add_argument( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy