Skip to content

Commit 3c53d33

Browse files
authored
Merge pull request #195 from rffontenelle/add-localization
2 parents 3e81cef + 2aa3a04 commit 3c53d33

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed

Diff for: .babel.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[jinja2: **.html]

Diff for: .github/workflows/tests.yml

+38
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,41 @@ jobs:
4848
with:
4949
name: doc-html-${{ matrix.branch }}
5050
path: www/
51+
52+
translations:
53+
runs-on: ${{ matrix.os }}
54+
strategy:
55+
fail-fast: false
56+
matrix:
57+
os: ["ubuntu-latest", "windows-latest"]
58+
# Test minimum supported and latest stable from 3.x series
59+
python-version: ["3.9", "3"]
60+
steps:
61+
- uses: actions/checkout@v4
62+
- uses: actions/setup-python@v5
63+
with:
64+
python-version: ${{ matrix.python-version }}
65+
allow-prereleases: true
66+
cache: pip
67+
- name: Install dependencies
68+
run: |
69+
pip install --upgrade pip
70+
pip install -r requirements.txt
71+
- name: Remove locale file for testing
72+
shell: bash
73+
run: rm -rf locales/pt_BR/
74+
- run: python babel_runner.py extract
75+
- run: python babel_runner.py init -l pt_BR
76+
- run: python babel_runner.py update
77+
- run: python babel_runner.py update -l pt_BR
78+
- run: python babel_runner.py compile
79+
- run: python babel_runner.py compile -l pt_BR
80+
- name: Print .pot file
81+
shell: bash
82+
run: cat locales/messages.pot
83+
- name: Print .po file
84+
shell: bash
85+
run: cat locales/pt_BR/LC_MESSAGES/messages.po
86+
- name: list files in locales dir
87+
shell: bash
88+
run: ls -R locales/

Diff for: babel_runner.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/venv python3
2+
"""Script for handling translations with Babel"""
3+
from __future__ import annotations
4+
5+
import argparse
6+
import subprocess
7+
from pathlib import Path
8+
9+
try:
10+
import tomllib
11+
except ImportError:
12+
try:
13+
import tomli as tomllib
14+
except ImportError as ie:
15+
raise ImportError(
16+
"tomli or tomllib is required to parse pyproject.toml"
17+
) from ie
18+
19+
PROJECT_DIR = Path(__file__).resolve().parent
20+
21+
# Global variables used by pybabel below (paths relative to PROJECT_DIR)
22+
DOMAIN = "messages"
23+
COPYRIGHT_HOLDER = "Python Software Foundation"
24+
LOCALES_DIR = "locales"
25+
POT_FILE = Path(LOCALES_DIR, f"{DOMAIN}.pot")
26+
SOURCE_DIR = "python_docs_theme"
27+
MAPPING_FILE = ".babel.cfg"
28+
29+
30+
def get_project_info() -> dict:
31+
"""Retrieve project's info to populate the message catalog template"""
32+
with open(Path(PROJECT_DIR / "pyproject.toml"), "rb") as f:
33+
data = tomllib.load(f)
34+
return data["project"]
35+
36+
37+
def extract_messages() -> None:
38+
"""Extract messages from all source files into message catalog template"""
39+
Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True)
40+
project_data = get_project_info()
41+
subprocess.run(
42+
[
43+
"pybabel",
44+
"extract",
45+
"-F",
46+
MAPPING_FILE,
47+
"--copyright-holder",
48+
COPYRIGHT_HOLDER,
49+
"--project",
50+
project_data["name"],
51+
"--version",
52+
project_data["version"],
53+
"--msgid-bugs-address",
54+
project_data["urls"]["Issue tracker"],
55+
"-o",
56+
POT_FILE,
57+
SOURCE_DIR,
58+
],
59+
cwd=PROJECT_DIR,
60+
check=True,
61+
)
62+
63+
64+
def init_locale(locale: str) -> None:
65+
"""Initialize a new locale based on existing message catalog template"""
66+
pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po"
67+
if pofile.exists():
68+
print(f"There is already a message catalog for locale {locale}, skipping.")
69+
return
70+
cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale]
71+
subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
72+
73+
74+
def update_catalogs(locale: str) -> None:
75+
"""Update translations from existing message catalogs"""
76+
cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR]
77+
if locale:
78+
cmd.extend(["-l", locale])
79+
subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
80+
81+
82+
def compile_catalogs(locale: str) -> None:
83+
"""Compile existing message catalogs"""
84+
cmd = ["pybabel", "compile", "-d", LOCALES_DIR]
85+
if locale:
86+
cmd.extend(["-l", locale])
87+
subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
88+
89+
90+
def main() -> None:
91+
parser = argparse.ArgumentParser(description=__doc__)
92+
parser.add_argument(
93+
"command",
94+
choices=["extract", "init", "update", "compile"],
95+
help="command to be executed",
96+
)
97+
parser.add_argument(
98+
"-l",
99+
"--locale",
100+
default="",
101+
help="language code (needed for init, optional for update and compile)",
102+
)
103+
104+
args = parser.parse_args()
105+
locale = args.locale
106+
107+
if args.command == "extract":
108+
extract_messages()
109+
elif args.command == "init":
110+
if not locale:
111+
parser.error("init requires passing the --locale option")
112+
init_locale(locale)
113+
elif args.command == "update":
114+
update_catalogs(locale)
115+
elif args.command == "compile":
116+
compile_catalogs(locale)
117+
118+
119+
if __name__ == "__main__":
120+
main()

Diff for: requirements.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# for babel_runner.py
2+
setuptools
3+
Babel
4+
Jinja2
5+
tomli; python_version < "3.10"

0 commit comments

Comments
 (0)