Skip to content

Commit ec7c4e2

Browse files
authored
Add: support for multiple languages to the guide
Add support for internationalization to the guide
2 parents 39730c7 + 8c26f89 commit ec7c4e2

File tree

4 files changed

+187
-48
lines changed

4 files changed

+187
-48
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ __pycache__
99
*.idea*
1010
# Grammar / syntax checkers
1111
styles/
12+
# Exclude translation .mo files
13+
locales/*/LC_MESSAGES/*.mo

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ repos:
3333
- tomli
3434
exclude: >
3535
(?x)^(
36-
.*vale-styles.*
36+
(.*vale-styles.*)|(.*\.po)
3737
)$
3838
3939
- repo: https://github.com/errata-ai/vale

noxfile.py

Lines changed: 178 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,213 @@
55

66
nox.options.reuse_existing_virtualenvs = True
77

8-
OUTPUT_DIR = "_build"
9-
docs_dir = os.path.join("_build", "html")
10-
build_command = ["-b", "html", ".", docs_dir]
8+
## Sphinx related options
9+
10+
# Sphinx output and source directories
11+
BUILD_DIR = '_build'
12+
OUTPUT_DIR = pathlib.Path(BUILD_DIR, "html")
13+
SOURCE_DIR = pathlib.Path(".")
14+
15+
# Location of the translation templates
16+
TRANSLATION_TEMPLATE_DIR = pathlib.Path(BUILD_DIR, "gettext")
17+
TRANSLATION_LOCALES_DIR = pathlib.Path("locales")
18+
19+
# Sphinx build commands
20+
SPHINX_BUILD = "sphinx-build"
21+
SPHINX_AUTO_BUILD = "sphinx-autobuild"
22+
23+
# Sphinx parameters used to build the guide
24+
BUILD_PARAMETERS = ["-b", "html"]
25+
26+
# Sphinx parameters used to test the build of the guide
27+
TEST_PARAMETERS = ['-W', '--keep-going', '-E', '-a']
28+
29+
# Sphinx parameters to generate translation templates
30+
TRANSLATION_TEMPLATE_PARAMETERS = ["-b", "gettext"]
31+
32+
# Sphinx-autobuild ignore and include parameters
33+
AUTOBUILD_IGNORE = [
34+
"_build",
35+
".nox",
36+
"build_assets",
37+
"tmp",
38+
]
39+
AUTOBUILD_INCLUDE = [
40+
pathlib.Path("_static", "pyos.css")
41+
]
42+
43+
## Localization options (translations)
44+
45+
# List of languages for which locales will be generated in (/locales/<lang>)
46+
LANGUAGES = ["es"]
47+
48+
# List of languages that should be built when releasing the guide (docs or docs-test sessions)
49+
RELEASE_LANGUAGES = []
50+
1151

1252
@nox.session
1353
def docs(session):
54+
"""Build the packaging guide."""
1455
session.install("-e", ".")
15-
cmd = ["sphinx-build"]
16-
cmd.extend(build_command + session.posargs)
17-
session.run(*cmd)
56+
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs)
57+
# When building the guide, also build the translations in RELEASE_LANGUAGES
58+
session.notify("build-translations", ['release-build'])
59+
1860

1961
@nox.session(name="docs-test")
2062
def docs_test(session):
2163
"""
22-
Same as `docs`, but rebuild everything and fail on warnings for testing
64+
Build the packaging guide with more restricted parameters.
65+
66+
Note: this is the session used in CI/CD to release the guide.
2367
"""
2468
session.install("-e", ".")
25-
cmd = ["sphinx-build"]
26-
cmd.extend(['-W', '--keep-going', '-E', '-a'])
27-
cmd.extend(build_command + session.posargs)
28-
session.run(*cmd)
69+
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, *TEST_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs)
70+
# When building the guide with additional parameters, also build the translations in RELEASE_LANGUAGES
71+
# with those same parameters.
72+
session.notify("build-translations", ['release-build', *TEST_PARAMETERS])
2973

3074

3175
@nox.session(name="docs-live")
3276
def docs_live(session):
33-
session.install("-e", ".")
77+
"""
78+
Build and launch a local copy of the guide.
3479
35-
AUTOBUILD_IGNORE = [
36-
"_build",
37-
"build_assets",
38-
"tmp",
39-
]
80+
This session will use sphinx-autobuild to build the guide and launch a local server so you can
81+
browse it locally. It will automatically rebuild the guide when changes are detected in the source.
4082
41-
# Explicitly include custom CSS in each build since
42-
# sphinx doesn't think _static files should change since,
43-
# well, they're static.
44-
# Include these as the final `filenames` argument
83+
It can be used with the language parameter to build a specific translation, for example:
4584
46-
AUTOBUILD_INCLUDE = [
47-
os.path.join("_static", "pyos.css")
48-
]
85+
nox -s docs-live -- -D language=es
4986
50-
# ----------------
51-
# Assemble command
52-
cmd = ["sphinx-autobuild"]
87+
Note: The docs-live-lang session below is provided as a convenience session for beginner contributors
88+
so they don't need to remember the specific sphinx-build parameters to build a different language.
89+
"""
90+
session.install("-e", ".")
91+
cmd = [SPHINX_AUTO_BUILD, *BUILD_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs]
5392
for folder in AUTOBUILD_IGNORE:
5493
cmd.extend(["--ignore", f"*/{folder}/*"])
94+
# This part was commented in the previous version of the nox file, keeping the same here
95+
# for folder in AUTOBUILD_INCLUDE:
96+
# cmd.extend(["--watch", folder])
97+
session.run(*cmd)
5598

56-
#cmd.extend(build_command)
57-
cmd.extend(build_command + session.posargs)
58-
59-
# Use positional arguments if we have them
60-
# if len(session.posargs) > 0:
61-
# cmd.extend(session.posargs)
62-
# # Otherwise use default output and include directory
63-
# else:
64-
# cmd.extend(AUTOBUILD_INCLUDE)
6599

66-
session.run(*cmd)
100+
@nox.session(name="docs-live-lang")
101+
def docs_live_lang(session):
102+
"""
103+
A convenience session for beginner contributors to use the docs-live session with
104+
a specific language.
67105
106+
It expects the language code to be passed as the first positional argument, so it needs
107+
to be called with from the command line with the following syntax:
68108
109+
nox -s docs-live-lang -- LANG
69110
70-
@nox.session(name="docs-clean")
71-
def clean_dir(dir_path=docs_dir):
111+
where LANG is one of the available languages defined in LANGUAGES.
112+
For example, for Spanish: nox -s docs-live-lang -- es
72113
"""
73-
Clean out the docs directory used in the
74-
live build.
75-
"""
76-
dir_path = pathlib.Path(dir_path)
77-
dir_contents = dir_path.glob('*')
114+
if not session.posargs:
115+
session.error(
116+
"Please provide a language using:\n\n "
117+
"nox -s docs-live-lang -- LANG\n\n "
118+
f" where LANG is one of: {LANGUAGES}"
119+
)
120+
lang = session.posargs[0]
121+
if lang in LANGUAGES:
122+
session.posargs.pop(0)
123+
session.notify("docs-live", ('-D', f"language={lang}", *session.posargs))
124+
else:
125+
session.error(
126+
f"[{lang}] locale is not available. Try using:\n\n "
127+
"nox -s docs-live-lang -- LANG\n\n "
128+
f"where LANG is one of: {LANGUAGES}"
129+
)
130+
78131

132+
@nox.session(name="docs-clean")
133+
def clean_dir(session):
134+
"""Clean out the docs directory used in the live build."""
135+
session.warn(f"Cleaning out {OUTPUT_DIR}")
136+
dir_contents = OUTPUT_DIR.glob('*')
79137
for content in dir_contents:
80-
print(content)
138+
session.log(f'removing {content}')
81139
if content.is_dir():
82140
shutil.rmtree(content)
83141
else:
84142
os.remove(content)
143+
144+
145+
@nox.session(name="update-translations")
146+
def update_translations(session):
147+
"""
148+
Update the translation files (./locales/*/.po) for all languages translations.
149+
150+
Note: this step is important because it makes sure that the translation files are
151+
up to date with the latest changes in the guide.
152+
"""
153+
session.install("-e", ".")
154+
session.install("sphinx-intl")
155+
session.log("Updating templates (.pot)")
156+
session.run(SPHINX_BUILD, *TRANSLATION_TEMPLATE_PARAMETERS, SOURCE_DIR, TRANSLATION_TEMPLATE_DIR, *session.posargs)
157+
for lang in LANGUAGES:
158+
session.log(f"Updating .po files for [{lang}] translation")
159+
session.run("sphinx-intl", "update", "-p", TRANSLATION_TEMPLATE_DIR, "-l", lang)
160+
161+
162+
@nox.session(name="build-languages")
163+
def build_languages(session):
164+
"""
165+
Build the translations of the guide for the specified language.
166+
167+
Note: This sessions expects a list of languages to build in the first position of the session arguments.
168+
It does not need to be called directly, it is started by build_translations session.
169+
"""
170+
if not session.posargs:
171+
session.error("Please provide the list of languages to build the translation for")
172+
languages_to_build = session.posargs.pop(0)
173+
174+
session.install("-e", ".")
175+
for lang in languages_to_build:
176+
if lang not in LANGUAGES:
177+
session.warn(f"Language [{lang}] is not available for translation")
178+
continue
179+
session.log(f"Building [{lang}] guide")
180+
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, "-D", f"language={lang}", ".", OUTPUT_DIR / lang, *session.posargs)
181+
182+
183+
@nox.session(name="build-translations")
184+
def build_translations(session):
185+
"""
186+
Build translations of the guide.
187+
188+
Note: this session can be called directly to build all available translations (defined in LANGUAGES).
189+
It is also called by the docs and docs-test sessions with 'release-build' as the first positional
190+
argument, to build only the translations defined in RELEASE_LANGUAGES.
191+
"""
192+
release_build = False
193+
if session.posargs and session.posargs[0] == 'release-build':
194+
session.posargs.pop(0)
195+
release_build = True
196+
# if running from the docs or docs-test sessions, build only release languages
197+
BUILD_LANGUAGES = RELEASE_LANGUAGES if release_build else LANGUAGES
198+
# only build languages that have a locale folder
199+
BUILD_LANGUAGES = [lang for lang in BUILD_LANGUAGES if (TRANSLATION_LOCALES_DIR / lang).exists()]
200+
session.log(f"Declared languages: {LANGUAGES}")
201+
session.log(f"Release languages: {RELEASE_LANGUAGES}")
202+
session.log(f"Building languages{' for release' if release_build else ''}: {BUILD_LANGUAGES}")
203+
if not BUILD_LANGUAGES:
204+
session.warn("No translations to build")
205+
else:
206+
session.notify("build-languages", [BUILD_LANGUAGES, *session.posargs])
207+
208+
209+
@nox.session(name="build-translations-test")
210+
def build_translations_test(session):
211+
"""
212+
Build all translations of the guide with testing parameters.
213+
214+
This is a convenience session to test the build of all translations with the testing parameters
215+
in the same way docs-test does for the English version.
216+
"""
217+
session.notify("build-translations", [*TEST_PARAMETERS])

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ dependencies = [
2626

2727
[project.optional-dependencies]
2828
dev = [
29-
# for checking style rules
30-
"vale"
29+
# for general build workflows
30+
"nox",
31+
# for prose linting
32+
"vale",
33+
# for managing translation files
34+
"sphinx-intl",
3135
]
3236

3337
[tool.hatch.build.targets.wheel]

0 commit comments

Comments
 (0)