From 6a7f72ba22c4b028a401e276d6a74b0ca8564bac Mon Sep 17 00:00:00 2001
From: Leah Wasser <leah@pyopensci.org>
Date: Tue, 25 Jun 2024 18:59:30 -0600
Subject: [PATCH 1/5] Fix: update hatch install instructions

---
 tutorials/get-to-know-hatch.md | 92 ++++++++++++++++++++++++++++------
 1 file changed, 77 insertions(+), 15 deletions(-)

diff --git a/tutorials/get-to-know-hatch.md b/tutorials/get-to-know-hatch.md
index 9f61cbc3..ed20f776 100644
--- a/tutorials/get-to-know-hatch.md
+++ b/tutorials/get-to-know-hatch.md
@@ -1,35 +1,99 @@
 # Get to know Hatch
 
-Our Python packaging tutorials use the tool Hatch.
-In this tutorial, you will install and get to know Hatch a bit more before starting to use it.
+Our Python packaging tutorials use the tool
+[Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging](/package-structure-code/python-package-build-tools)
+tool options out there, we have selected to teach Hatch because
+
+1. It is an end-to-end tool that supports most of the steps required to create a quality Python package. Beginners will have fewer tools to learn if they use Hatch.
+1. It supports different build back-ends if you ever need to compile code in other languages.
+1. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that supports many different scientific Python use cases.
+
+In this tutorial, you will install and get to know Hatch a bit more before
+starting to use it.
+
+You need two things to successfully complete this tutorial:
+
+1. You need Python installed.
+2. You need Hatch installed.
+
+:::{important}
+If you don't already have Python installed, Hatch will do it for you when you
+install Hatch.
+
+Hatch uses [UV](https://astral.sh/blog/uv) to install Python. UV is a super
+fast Python package installer and resolver written in Rust.
+:::
 
 ## Install Hatch
-To begin, install Hatch from the command line using [pipx](https://pipx.pypa.io/stable/)
+
+To begin, follow the operating-specific instructions below to install Hatch.
+
+::::{tab-set}
+
+:::{tab-item} MAC
+
+Follow the instructions [here](https://hatch.pypa.io/latest/install/#installers).
+
+* Download the latest GUI installer for MAC [hatch-universal.pkg](https://github.com/pypa/hatch/releases/latest/download/hatch-universal.pkg).
+* Run the installer and follow the setup instructions.
+* If your terminal is open, then restart it.
+
+:::
+
+:::{tab-item} Windows
+
+* In your browser, download the correct `.msi` file for your system:
+[hatch-x64.msi](https://github.com/pypa/hatch/releases/latest/download/hatch-x64.msi)
+* Run your downloaded installer file and follow the on-screen instructions.
+
+:::
+
+:::{tab-item} Linux
+
+We suggest that you install Hatch using pipx on Linux.
+however, if you prefer another method, check out the [Hatch installation documentation](https://hatch.pypa.io/latest/install/) for other methods.
 
 ```bash
-pipx install hatch
+# First install pipx
+> apt install pipx
+# Then install hatch using pipx
+> pipx install hatch
 ```
 
-:::{tip}
-Hatch can also be installed directly using `pip` or `conda`, but we encourage you to use `pipx`.
-This is because `pipx` will ensure that your package is available across all of your Python
-environments on your computer rather than just in the environment that you install it into.
-If you install hatch this way you will have to take care that the environment it is installed into
-is activated for the command to work.
 :::
+::::
+
+### Check that hatch installed correctly
 
-You can check that hatch is working properly by issuing a simple command to get the version
+Once you have completed the installation instructions above, you can open your terminal, and make sure that Hatch installed correctly using
+the command below:
 
 ```bash
 hatch --version
 # Hatch, version 1.9.4
 ```
 
-Note the version numbers will likely be different
+*Note the version number output of `hatch --version` will likely  be
+different from the output above in this tutorial.*
+
+:::{tip}
+Hatch can also be installed directly using `pip` or `conda`. We
+encourage
+you to follow the instructions above because we have found that the Hatch installers for Windows and Mac are easiest and most efficient.
+
+Our Linux users have found success installing Hatch with `pipx` if they
+already use `apt install`.
+
+Both approaches (using a graphical installer on Windows / MAC and `pipx`) ensure that you have Hatch installed
+globally. A global install means that Hatch is available
+across all of your Python environments on your computer.
+:::
 
 ## Configure hatch
 
-Once you have installed Hatch, you will want to customize the configuration.
+Once you have installed Hatch, you can customize the configuration which
+includes the default name and setup that you want to have for every
+package that you create using Hatch. While this step is not required, we suggest it.
 
 Hatch stores your configuration information in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/).
 
@@ -141,14 +205,12 @@ and maintaining your Python package easier.
 
 A few features that Hatch offers
 
-
 1. it will convert metadata stored in a `setup.py` or `setup.cfg` file to a pyproject.toml file for you (see [Migrating setup.py to pyproject.toml using Hatch](setup-py-to-pyproject-toml.md
 ))
 2. It will help you by storing configuration information for publishing to PyPI after you've entered it once.
 
 Use `hatch -h` to see all of the available commands.
 
-
 ## What's next
 
 In the next lesson you'll learn how to package and make your code installable using Hatch.

From dd8f91f1e46bd6dbb150f045a341510b834fd454 Mon Sep 17 00:00:00 2001
From: Leah Wasser <leah@pyopensci.org>
Date: Wed, 26 Jun 2024 10:21:30 -0600
Subject: [PATCH 2/5] Fix: edits from review

---
 tutorials/get-to-know-hatch.md | 86 +++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 37 deletions(-)

diff --git a/tutorials/get-to-know-hatch.md b/tutorials/get-to-know-hatch.md
index ed20f776..2dd90617 100644
--- a/tutorials/get-to-know-hatch.md
+++ b/tutorials/get-to-know-hatch.md
@@ -1,12 +1,17 @@
-# Get to know Hatch
+# Get to Know Hatch
 
 Our Python packaging tutorials use the tool
-[Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging](/package-structure-code/python-package-build-tools)
-tool options out there, we have selected to teach Hatch because
-
-1. It is an end-to-end tool that supports most of the steps required to create a quality Python package. Beginners will have fewer tools to learn if they use Hatch.
-1. It supports different build back-ends if you ever need to compile code in other languages.
-1. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that supports many different scientific Python use cases.
+[Hatch](https://hatch.pypa.io/latest/). While there are [many great packaging
+tools](/package-structure-code/python-package-build-tools) out there, we have
+selected Hatch because:
+
+1. It is an end-to-end tool that supports most of the steps required to create
+   a quality Python package. Beginners will have fewer tools to learn if they
+   use Hatch.
+2. It supports different build back-ends if you ever need to compile code in
+   other languages.
+3. As a community, pyOpenSci has decided that Hatch is a user-friendly tool that
+   supports many different scientific Python use cases.
 
 In this tutorial, you will install and get to know Hatch a bit more before
 starting to use it.
@@ -17,16 +22,14 @@ You need two things to successfully complete this tutorial:
 2. You need Hatch installed.
 
 :::{important}
-If you don't already have Python installed, Hatch will do it for you when you
-install Hatch.
-
-Hatch uses [UV](https://astral.sh/blog/uv) to install Python. UV is a super
-fast Python package installer and resolver written in Rust.
+If you don't already have Python installed on your computer, Hatch will do it
+for you when you install Hatch.
 :::
 
 ## Install Hatch
 
-To begin, follow the operating-specific instructions below to install Hatch.
+To begin, follow the operating-system-specific instructions below to install
+Hatch.
 
 ::::{tab-set}
 
@@ -65,8 +68,8 @@ however, if you prefer another method, check out the [Hatch installation documen
 
 ### Check that hatch installed correctly
 
-Once you have completed the installation instructions above, you can open your terminal, and make sure that Hatch installed correctly using
-the command below:
+Once you have completed the installation instructions above, you can open your
+terminal, and make sure that Hatch installed correctly using the command below:
 
 ```bash
 hatch --version
@@ -77,38 +80,42 @@ hatch --version
 different from the output above in this tutorial.*
 
 :::{tip}
-Hatch can also be installed directly using `pip` or `conda`. We
-encourage
-you to follow the instructions above because we have found that the Hatch installers for Windows and Mac are easiest and most efficient.
+Hatch can also be installed directly using pip or conda. We encourage you to
+follow the instructions above because we have found that the Hatch installers
+for Windows and Mac are the easiest and most efficient.
 
-Our Linux users have found success installing Hatch with `pipx` if they
-already use `apt install`.
+Our Linux users have found success installing Hatch with pipx if they already
+use apt install.
 
-Both approaches (using a graphical installer on Windows / MAC and `pipx`) ensure that you have Hatch installed
-globally. A global install means that Hatch is available
-across all of your Python environments on your computer.
+Both approaches (using a graphical installer on Windows/Mac and pipx) ensure
+that you have Hatch installed globally. A global install means that Hatch is
+available across all of your Python environments on your computer.
 :::
 
-## Configure hatch
+## Configure Hatch
 
-Once you have installed Hatch, you can customize the configuration which
-includes the default name and setup that you want to have for every
-package that you create using Hatch. While this step is not required, we suggest it.
+Once you have installed Hatch, you can customize its configuration. This
+includes setting the default name and setup for every package you create. While
+this step is not required, we suggest that you do it.
 
-Hatch stores your configuration information in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/).
+Hatch stores your configuration in a [`config.toml` file](https://hatch.pypa.io/latest/config/project-templates/).
 
-While you can update the `config.toml` file through the command line,
-it might be easier to look at it and update it in a text editor if you are using it for the first time.
+While you can update the `config.toml` file through the command line, it might
+be easier to look at and update it in a text editor if you are using it for the
+first time.
 
-### Step 1: Open and edit your `config.toml` file
+### Step 1: Open and Edit Your `config.toml` File
 
-To open the config file in your file browser, run the following command in your shell:
+To open the config file in your file browser, run the following command in your
+shell:
 
 `hatch config explore`
 
-This will open up a directory window that will allow you to double click on the file and open it in your favorite text editor.
+This will open up a directory window that allows you to double-click on the file
+and open it in your favorite text editor.
 
-You can also retrieve the location of the Hatch config file by running the following command in your shell:
+You can also retrieve the location of the Hatch config file by running the
+following command in your shell:
 
 ```bash
 hatch config find
@@ -117,7 +124,9 @@ hatch config find
 
 ### Step 2 - update your email and name
 
-Once the file is open, update the [template] table of the `config.toml` file with your name and email. This information will be used in any `pyproject.toml` metadata files that you create using Hatch.
+Once the file is open, update the [template] table of the `config.toml` file
+with your name and email. This information will be used in any `pyproject.toml`
+metadata files that you create using Hatch.
 
 ```toml
 [template]
@@ -174,7 +183,8 @@ src-layout = true
 
 Also notice that the default license option is MIT. While we will discuss
 license in more detail in a later lesson, the MIT license is the
-recommended permissive license from [choosealicense.com](https://www.choosealicense.com) and as such we will
+recommended permissive license from
+[choosealicense.com](https://www.choosealicense.com) and as such we will
 use it for this tutorial series.
 
 You are of course welcome to select another license.
@@ -189,7 +199,9 @@ Once you have completed the steps above run the following command in your shell.
 
 `hatch config show`
 
-`hatch config show` will print out the contents of your `config.toml` file in your shell. look at the values and ensure that your name, email is set. Also make sure that `tests=false`.
+`hatch config show` will print out the contents of your `config.toml` file in
+your shell. look at the values and ensure that your name, email is set. Also
+make sure that `tests=false`.
 
 ## Hatch features
 

From 65bdd1be1f3be8606344284bca5875e992944e23 Mon Sep 17 00:00:00 2001
From: Leah Wasser <leah@pyopensci.org>
Date: Fri, 28 Jun 2024 11:58:24 -0600
Subject: [PATCH 3/5] Cleanup

---
 noxfile.py                                          | 13 ++++++-------
 package-structure-code/code-style-linting-format.md |  1 +
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/noxfile.py b/noxfile.py
index 7ba28129..31799979 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -9,6 +9,7 @@
 docs_dir = os.path.join("_build", "html")
 build_command = ["-b", "html", ".", docs_dir]
 
+
 @nox.session
 def docs(session):
     session.install("-e", ".")
@@ -16,6 +17,7 @@ def docs(session):
     cmd.extend(build_command + session.posargs)
     session.run(*cmd)
 
+
 @nox.session(name="docs-test")
 def docs_test(session):
     """
@@ -23,7 +25,7 @@ def docs_test(session):
     """
     session.install("-e", ".")
     cmd = ["sphinx-build"]
-    cmd.extend(['-W', '--keep-going', '-E', '-a'])
+    cmd.extend(["-W", "--keep-going", "-E", "-a"])
     cmd.extend(build_command + session.posargs)
     session.run(*cmd)
 
@@ -43,9 +45,7 @@ def docs_live(session):
     # well, they're static.
     # Include these as the final `filenames` argument
 
-    AUTOBUILD_INCLUDE = [
-        os.path.join("_static", "pyos.css")
-    ]
+    AUTOBUILD_INCLUDE = [os.path.join("_static", "pyos.css")]
 
     # ----------------
     # Assemble command
@@ -53,7 +53,7 @@ def docs_live(session):
     for folder in AUTOBUILD_IGNORE:
         cmd.extend(["--ignore", f"*/{folder}/*"])
 
-    #cmd.extend(build_command)
+    # cmd.extend(build_command)
     cmd.extend(build_command + session.posargs)
 
     # Use positional arguments if we have them
@@ -66,7 +66,6 @@ def docs_live(session):
     session.run(*cmd)
 
 
-
 @nox.session(name="docs-clean")
 def clean_dir(dir_path=docs_dir):
     """
@@ -74,7 +73,7 @@ def clean_dir(dir_path=docs_dir):
     live build.
     """
     dir_path = pathlib.Path(dir_path)
-    dir_contents = dir_path.glob('*')
+    dir_contents = dir_path.glob("*")
 
     for content in dir_contents:
         print(content)
diff --git a/package-structure-code/code-style-linting-format.md b/package-structure-code/code-style-linting-format.md
index 1616ddc6..7c5975b4 100644
--- a/package-structure-code/code-style-linting-format.md
+++ b/package-structure-code/code-style-linting-format.md
@@ -174,6 +174,7 @@ Also notice that there are no spaces in the imports listed below.
 :::
 
 From the project root, run:
+
 ```bash
 isort src/examplePy/temporal.py
 ```

From f6d16253aec71de3457f8ff8ff1f14c4880c0071 Mon Sep 17 00:00:00 2001
From: Leah Wasser <leah@pyopensci.org>
Date: Wed, 3 Jul 2024 17:24:17 -0600
Subject: [PATCH 4/5] Fix: rebase main

---
 noxfile.py | 261 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 219 insertions(+), 42 deletions(-)

diff --git a/noxfile.py b/noxfile.py
index 31799979..34c18b82 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -5,79 +5,256 @@
 
 nox.options.reuse_existing_virtualenvs = True
 
-OUTPUT_DIR = "_build"
-docs_dir = os.path.join("_build", "html")
-build_command = ["-b", "html", ".", docs_dir]
+## Sphinx related options
+
+# Sphinx output and source directories
+BUILD_DIR = "_build"
+OUTPUT_DIR = pathlib.Path(BUILD_DIR, "html")
+SOURCE_DIR = pathlib.Path(".")
+
+# Location of the translation templates
+TRANSLATION_TEMPLATE_DIR = pathlib.Path(BUILD_DIR, "gettext")
+TRANSLATION_LOCALES_DIR = pathlib.Path("locales")
+
+# Sphinx build commands
+SPHINX_BUILD = "sphinx-build"
+SPHINX_AUTO_BUILD = "sphinx-autobuild"
+
+# Sphinx parameters used to build the guide
+BUILD_PARAMETERS = ["-b", "html"]
+
+# Sphinx parameters used to test the build of the guide
+TEST_PARAMETERS = ["-W", "--keep-going", "-E", "-a"]
+
+# Sphinx parameters to generate translation templates
+TRANSLATION_TEMPLATE_PARAMETERS = ["-b", "gettext"]
+
+# Sphinx-autobuild ignore and include parameters
+AUTOBUILD_IGNORE = [
+    "_build",
+    ".nox",
+    "build_assets",
+    "tmp",
+]
+AUTOBUILD_INCLUDE = [pathlib.Path("_static", "pyos.css")]
+
+## Localization options (translations)
+
+# List of languages for which locales will be generated in (/locales/<lang>)
+LANGUAGES = ["es"]
+
+# List of languages that should be built when releasing the guide (docs or docs-test sessions)
+RELEASE_LANGUAGES = []
 
 
 @nox.session
 def docs(session):
+    """Build the packaging guide."""
     session.install("-e", ".")
-    cmd = ["sphinx-build"]
-    cmd.extend(build_command + session.posargs)
-    session.run(*cmd)
+    session.run(
+        SPHINX_BUILD,
+        *BUILD_PARAMETERS,
+        SOURCE_DIR,
+        OUTPUT_DIR,
+        *session.posargs,
+    )
+    # When building the guide, also build the translations in RELEASE_LANGUAGES
+    session.notify("build-translations", ["release-build"])
 
 
 @nox.session(name="docs-test")
 def docs_test(session):
     """
-    Same as `docs`, but rebuild everything and fail on warnings for testing
+    Build the packaging guide with more restricted parameters.
+
+    Note: this is the session used in CI/CD to release the guide.
     """
     session.install("-e", ".")
-    cmd = ["sphinx-build"]
-    cmd.extend(["-W", "--keep-going", "-E", "-a"])
-    cmd.extend(build_command + session.posargs)
-    session.run(*cmd)
+    session.run(
+        SPHINX_BUILD,
+        *BUILD_PARAMETERS,
+        *TEST_PARAMETERS,
+        SOURCE_DIR,
+        OUTPUT_DIR,
+        *session.posargs,
+    )
+    # When building the guide with additional parameters, also build the translations in RELEASE_LANGUAGES
+    # with those same parameters.
+    session.notify("build-translations", ["release-build", *TEST_PARAMETERS])
 
 
 @nox.session(name="docs-live")
 def docs_live(session):
-    session.install("-e", ".")
+    """
+    Build and launch a local copy of the guide.
 
-    AUTOBUILD_IGNORE = [
-        "_build",
-        "build_assets",
-        "tmp",
-    ]
+    This session will use sphinx-autobuild to build the guide and launch a local server so you can
+    browse it locally. It will automatically rebuild the guide when changes are detected in the source.
 
-    # Explicitly include custom CSS in each build since
-    # sphinx doesn't think _static files should change since,
-    # well, they're static.
-    # Include these as the final `filenames` argument
+    It can be used with the language parameter to build a specific translation, for example:
 
-    AUTOBUILD_INCLUDE = [os.path.join("_static", "pyos.css")]
+        nox -s docs-live -- -D language=es
 
-    # ----------------
-    # Assemble command
-    cmd = ["sphinx-autobuild"]
+    Note: The docs-live-lang session below is provided as a convenience session for beginner contributors
+    so they don't need to remember the specific sphinx-build parameters to build a different language.
+    """
+    session.install("-e", ".")
+    cmd = [
+        SPHINX_AUTO_BUILD,
+        *BUILD_PARAMETERS,
+        SOURCE_DIR,
+        OUTPUT_DIR,
+        *session.posargs,
+    ]
     for folder in AUTOBUILD_IGNORE:
         cmd.extend(["--ignore", f"*/{folder}/*"])
+    # This part was commented in the previous version of the nox file, keeping the same here
+    # for folder in AUTOBUILD_INCLUDE:
+    #     cmd.extend(["--watch", folder])
+    session.run(*cmd)
 
-    # cmd.extend(build_command)
-    cmd.extend(build_command + session.posargs)
 
-    # Use positional arguments if we have them
-    # if len(session.posargs) > 0:
-    #     cmd.extend(session.posargs)
-    # # Otherwise use default output and include directory
-    # else:
-    #     cmd.extend(AUTOBUILD_INCLUDE)
+@nox.session(name="docs-live-lang")
+def docs_live_lang(session):
+    """
+    A convenience session for beginner contributors to use the docs-live session with
+    a specific language.
 
-    session.run(*cmd)
+    It expects the language code to be passed as the first positional argument, so it needs
+    to be called with from the command line with the following syntax:
 
+        nox -s docs-live-lang -- LANG
 
-@nox.session(name="docs-clean")
-def clean_dir(dir_path=docs_dir):
-    """
-    Clean out the docs directory used in the
-    live build.
+    where LANG is one of the available languages defined in LANGUAGES.
+    For example, for Spanish: nox -s docs-live-lang -- es
     """
-    dir_path = pathlib.Path(dir_path)
-    dir_contents = dir_path.glob("*")
+    if not session.posargs:
+        session.error(
+            "Please provide a language using:\n\n      "
+            "nox -s docs-live-lang -- LANG\n\n     "
+            f" where LANG is one of: {LANGUAGES}"
+        )
+    lang = session.posargs[0]
+    if lang in LANGUAGES:
+        session.posargs.pop(0)
+        session.notify(
+            "docs-live", ("-D", f"language={lang}", *session.posargs)
+        )
+    else:
+        session.error(
+            f"[{lang}] locale is not available. Try using:\n\n      "
+            "nox -s docs-live-lang -- LANG\n\n      "
+            f"where LANG is one of: {LANGUAGES}"
+        )
+
 
+@nox.session(name="docs-clean")
+def clean_dir(session):
+    """Clean out the docs directory used in the live build."""
+    session.warn(f"Cleaning out {OUTPUT_DIR}")
+    dir_contents = OUTPUT_DIR.glob("*")
     for content in dir_contents:
-        print(content)
+        session.log(f"removing {content}")
         if content.is_dir():
             shutil.rmtree(content)
         else:
             os.remove(content)
+
+
+@nox.session(name="update-translations")
+def update_translations(session):
+    """
+    Update the translation files (./locales/*/.po) for all languages translations.
+
+    Note: this step is important because it makes sure that the translation files are
+    up to date with the latest changes in the guide.
+    """
+    session.install("-e", ".")
+    session.install("sphinx-intl")
+    session.log("Updating templates (.pot)")
+    session.run(
+        SPHINX_BUILD,
+        *TRANSLATION_TEMPLATE_PARAMETERS,
+        SOURCE_DIR,
+        TRANSLATION_TEMPLATE_DIR,
+        *session.posargs,
+    )
+    for lang in LANGUAGES:
+        session.log(f"Updating .po files for [{lang}] translation")
+        session.run(
+            "sphinx-intl", "update", "-p", TRANSLATION_TEMPLATE_DIR, "-l", lang
+        )
+
+
+@nox.session(name="build-languages")
+def build_languages(session):
+    """
+    Build the translations of the guide for the specified language.
+
+    Note: This sessions expects a list of languages to build in the first position of the session arguments.
+    It does not need to be called directly, it is started by build_translations session.
+    """
+    if not session.posargs:
+        session.error(
+            "Please provide the list of languages to build the translation for"
+        )
+    languages_to_build = session.posargs.pop(0)
+
+    session.install("-e", ".")
+    for lang in languages_to_build:
+        if lang not in LANGUAGES:
+            session.warn(f"Language [{lang}] is not available for translation")
+            continue
+        session.log(f"Building [{lang}] guide")
+        session.run(
+            SPHINX_BUILD,
+            *BUILD_PARAMETERS,
+            "-D",
+            f"language={lang}",
+            ".",
+            OUTPUT_DIR / lang,
+            *session.posargs,
+        )
+
+
+@nox.session(name="build-translations")
+def build_translations(session):
+    """
+    Build translations of the guide.
+
+    Note: this session can be called directly to build all available translations (defined in LANGUAGES).
+    It is also called by the docs and docs-test sessions with 'release-build' as the first positional
+    argument, to build only the translations defined in RELEASE_LANGUAGES.
+    """
+    release_build = False
+    if session.posargs and session.posargs[0] == "release-build":
+        session.posargs.pop(0)
+        release_build = True
+    # if running from the docs or docs-test sessions, build only release languages
+    BUILD_LANGUAGES = RELEASE_LANGUAGES if release_build else LANGUAGES
+    # only build languages that have a locale folder
+    BUILD_LANGUAGES = [
+        lang
+        for lang in BUILD_LANGUAGES
+        if (TRANSLATION_LOCALES_DIR / lang).exists()
+    ]
+    session.log(f"Declared languages: {LANGUAGES}")
+    session.log(f"Release languages: {RELEASE_LANGUAGES}")
+    session.log(
+        f"Building languages{' for release' if release_build else ''}: {BUILD_LANGUAGES}"
+    )
+    if not BUILD_LANGUAGES:
+        session.warn("No translations to build")
+    else:
+        session.notify("build-languages", [BUILD_LANGUAGES, *session.posargs])
+
+
+@nox.session(name="build-translations-test")
+def build_translations_test(session):
+    """
+    Build all translations of the guide with testing parameters.
+
+    This is a convenience session to test the build of all translations with the testing parameters
+    in the same way docs-test does for the English version.
+    """
+    session.notify("build-translations", [*TEST_PARAMETERS])

From ff8e19046b2309133ec073538f2123153407e9f7 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Wed, 3 Jul 2024 23:26:35 +0000
Subject: [PATCH 5/5] =?UTF-8?q?'[pre-commit.ci=20=F0=9F=A4=96]=20Apply=20c?=
 =?UTF-8?q?ode=20format=20tools=20to=20PR'?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 noxfile.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/noxfile.py b/noxfile.py
index 0e5b2bb6..4a0ea835 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -214,4 +214,4 @@ def build_translations_test(session):
     This is a convenience session to test the build of all translations with the testing parameters
     in the same way docs-test does for the English version.
     """
-    session.notify("build-translations", [*TEST_PARAMETERS])
\ No newline at end of file
+    session.notify("build-translations", [*TEST_PARAMETERS])