From d271fac02cae550e8b051ac358465ad0894ec9fd Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@users.noreply.github.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@gmail.com>
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 <rffontenelle@users.noreply.github.com>
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 <ezio.melotti@gmail.com>
---
 .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 <rffontenelle@users.noreply.github.com>
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 <rffontenelle@users.noreply.github.com>
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 <rffontenelle@users.noreply.github.com>
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(