From 065e4c9d87833baa6065ea7f905c6ecc1876c4d4 Mon Sep 17 00:00:00 2001
From: Shengjing Zhu <i@zhsj.me>
Date: Wed, 3 Nov 2021 00:27:36 +0800
Subject: [PATCH 01/46] Pin docutils version when build with Sphinx 2.3.1

Closes: #227
---
 .github/scripts/build.sh | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index bbf4eb060..e29f73036 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,5 +13,8 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
+
+# Hotfix for #227
+sed -i 's|Sphinx==2.3.1|Sphinx==2.3.1 "docutils<0.18"|g'  Makefile
 make venv
 make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going -j2" 2> >(error)

From 4dac60f469b2bfa9c0d2e067f5087fae1d2a059c Mon Sep 17 00:00:00 2001
From: Shengjing Zhu <i@zhsj.me>
Date: Fri, 17 Jun 2022 10:49:21 +0800
Subject: [PATCH 02/46] Revert "Pin docutils version when build with Sphinx
 2.3.1"

This reverts commit 065e4c9d87833baa6065ea7f905c6ecc1876c4d4.

Closes: #258
---
 .github/scripts/build.sh | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index e29f73036..bbf4eb060 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,8 +13,5 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
-
-# Hotfix for #227
-sed -i 's|Sphinx==2.3.1|Sphinx==2.3.1 "docutils<0.18"|g'  Makefile
 make venv
 make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going -j2" 2> >(error)

From a67273b9fb80157109304f5c5ef6222e9a4fce8b Mon Sep 17 00:00:00 2001
From: BlueGlassBlock <blueglassblock@outlook.com>
Date: Mon, 27 Feb 2023 16:01:18 +0800
Subject: [PATCH 03/46] Update to Python 3.11

---
 .github/scripts/generate_tx_config.py | 119 ++++++++++++--------------
 .github/scripts/prepare.sh            |   2 +-
 .github/scripts/transifex_pull.py     |  38 --------
 .github/scripts/update.sh             |  15 +---
 .github/workflows/python-310.yml      |   2 +-
 .github/workflows/python-311.yml      |  29 +++++++
 .github/workflows/python-37.yml       |   2 +-
 .github/workflows/python-38.yml       |   2 +-
 .github/workflows/python-39.yml       |   2 +-
 README.rst                            |   3 +
 10 files changed, 93 insertions(+), 121 deletions(-)
 delete mode 100755 .github/scripts/transifex_pull.py
 create mode 100644 .github/workflows/python-311.yml

diff --git a/.github/scripts/generate_tx_config.py b/.github/scripts/generate_tx_config.py
index 0e72833f1..b21e099ee 100755
--- a/.github/scripts/generate_tx_config.py
+++ b/.github/scripts/generate_tx_config.py
@@ -1,76 +1,67 @@
-#!/usr/bin/env python3
-import glob
-import json
-import os
+"""Please note that this script requires a Transifex API token to run."""
+import subprocess
+from functools import partial
+from pathlib import Path
 import re
-import sys
-import urllib.request
 
+run = partial(subprocess.run, check=True)
 
-def list_resources(token, project):
-    auth_handler = urllib.request.HTTPBasicAuthHandler()
-    auth_handler.add_password(
-        realm="api", uri="https://api.transifex.com/", user="api", passwd=token
+
+def init_project():
+    run(["tx", "init"])
+
+
+def add_files(version: str):
+    run(
+        [
+            "tx",
+            "add",
+            "remote",
+            "--file-filter",
+            "trans/<lang>/<resource_slug>.<ext>",
+            f"https://www.transifex.com/python-doc/{version}/dashboard/",
+        ]
     )
-    opener = urllib.request.build_opener(auth_handler)
-    urllib.request.install_opener(opener)
-    next_ = (
-        "https://api.transifex.com/organizations/python-doc/projects/"
-        + project
-        + "/resources/"
+
+
+FILTER_PATTERN = re.compile(
+    r"^(?P<prefix>file_filter( *)=( *))(?P<resource>.+)$", re.MULTILINE
+)
+
+
+def name_replacer(match: re.Match[str]):
+    prefix, resource = match.group("prefix", "resource")
+    override_prefix = prefix.replace("file_filter", "trans.zh_CN")
+    override_resource = (
+        resource.replace("trans/<lang>/", "")
+        .replace("--", "/")
+        .replace("glossary_", "glossary")
+        .replace("_", ".")
     )
-    resources = []
-    while True:
-        resp = urllib.request.urlopen(next_)
-        result = json.loads(resp.read().decode("utf-8"))
-        resources.extend([i["slug"] for i in result])
-        link = re.findall('<([^<]*)>; rel="next"', resp.getheader("Link") or "")
-        if not link:
-            break
-        next_ = link[0]
-    return resources
-
-
-def render_config(doc_dir, project, resources):
-    os.chdir(doc_dir)
-    tpl = """
-
-[{project}.{resource}]
-trans.zh_CN = {filename}
-source_lang = en
-type = PO"""
-    conf = """[main]
-host = https://www.transifex.com"""
-    for resource in sorted(resources):
-        if resource == "glossary_":
-            filename = "glossary.po"
-        elif resource == "sphinx":
-            filename = "sphinx.po"
-        else:
-            pattern = resource.replace("--", "/").replace("_", "?")
-            matches = glob.glob(pattern + ".rst")
-            if len(matches) == 0:
-                print("missing", resource, file=sys.stderr)
-                continue
-            elif len(matches) == 1:
-                filename = matches[0].replace(".rst", ".po")
-            else:
-                print("multi match", resource, pattern, matches, file=sys.stderr)
-        conf += tpl.format(project=project, resource=resource, filename=filename)
-    return conf
+    return f"{prefix}{resource}\n{override_prefix}{override_resource}"
+
+
+def patch_config():
+    tx_config_path = Path(".tx", "config")
+
+    config_content = tx_config_path.read_text("utf-8")
+    config_content = FILTER_PATTERN.sub(name_replacer, config_content)
+    tx_config_path.write_text(config_content, "utf-8")
 
 
 if __name__ == "__main__":
-    import argparse
+    from argparse import ArgumentParser
+    import os
+
+    parser = ArgumentParser()
 
-    parser = argparse.ArgumentParser()
     parser.add_argument("--token")
-    parser.add_argument("--project")
-    parser.add_argument("--doc-dir")
-    args = parser.parse_args()
+    parser.add_argument("--version")
+
+    params = parser.parse_args()
 
-    resources = list_resources(args.token, args.project)
-    conf = render_config(args.doc_dir, args.project, resources)
-    print(conf)
+    os.environ["TX_TOKEN"] = params.token
 
-# vim: set et ts=4 sw=4 sts=4:
+    init_project()
+    add_files(params.version)
+    patch_config()
diff --git a/.github/scripts/prepare.sh b/.github/scripts/prepare.sh
index d16dbc056..cf1326646 100755
--- a/.github/scripts/prepare.sh
+++ b/.github/scripts/prepare.sh
@@ -6,6 +6,6 @@ git clone --depth=1 --branch="$VERSION" https://github.com/python/cpython cpytho
 git clone --branch="$VERSION" https://github.com/"$GITHUB_REPOSITORY" docs
 
 pip3 install --user setuptools
-pip3 install --user transifex-client
+curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
 sudo apt-get update
 sudo apt-get install -y python3-venv
diff --git a/.github/scripts/transifex_pull.py b/.github/scripts/transifex_pull.py
deleted file mode 100755
index 66c4046d9..000000000
--- a/.github/scripts/transifex_pull.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-
-from txclib import project
-from txclib.utils import perform_parallel_requests
-
-
-def pull(path, lang):
-    skip_decode = False
-    params = {}
-    parallel = True
-
-    prj = project.Project(path)
-    resource_list = prj.get_chosen_resources([])
-    for resource in resource_list:
-        project_slug, resource_slug = resource.split(".", 1)
-        host = prj.get_resource_host(resource)
-        prj._set_url_info(host=host, project=project_slug, resource=resource_slug)
-
-        files = prj.get_resource_files(resource)
-        url = prj._get_url_by_pull_mode(None)
-        local_file = files.get(lang)
-        prj.do_url_request(
-            url,
-            language=lang,
-            skip_decode=skip_decode,
-            params=params,
-            parallel=parallel,
-            callback=prj._save_file,
-            callback_args={"local_file": local_file},
-        )
-
-    perform_parallel_requests()
-
-
-if __name__ == "__main__":
-    import os
-
-    pull(os.getcwd(), os.getenv("LOCALE", "zh_CN"))
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index 544a31ae5..8424d2901 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,18 +1,5 @@
 #!/bin/bash
 
-set -ex
-
-script_dir="$(dirname "$(realpath "$0")")"
-
-if [[ -n "$TRANSIFEX_APIKEY" ]]; then
-  cat > ~/.transifexrc << EOF
-[https://www.transifex.com]
-api_hostname = https://api.transifex.com
-hostname = https://www.transifex.com
-password = $TRANSIFEX_APIKEY
-username = api
-EOF
-fi
 
 cd docs || exit 1
-"$script_dir"/transifex_pull.py
+tx pull --languages "$LOCALE"
diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 54037983e..5524337ef 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
new file mode 100644
index 000000000..e37354ae2
--- /dev/null
+++ b/.github/workflows/python-311.yml
@@ -0,0 +1,29 @@
+name: python-310
+
+on:
+  push:
+    branches:
+      - master
+  schedule:
+    - cron: "8 * * * *"
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    env:
+      LOCALE: zh_CN
+      VERSION: "3.11"
+    steps:
+      - uses: actions/checkout@v2
+      - name: prepare
+        run: .github/scripts/prepare.sh
+      - name: update
+        run: .github/scripts/update.sh
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: build
+        run: .github/scripts/build.sh
+      - name: commit
+        run: .github/scripts/commit.sh
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/python-37.yml b/.github/workflows/python-37.yml
index c35d61d2b..6864df933 100644
--- a/.github/workflows/python-37.yml
+++ b/.github/workflows/python-37.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index a99f0e20e..35948544c 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 76a6793bb..4b16958a5 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/README.rst b/README.rst
index 4ff062bc4..cf08f1294 100644
--- a/README.rst
+++ b/README.rst
@@ -12,6 +12,9 @@ Maintained versions:
    * - Version
      - Sync status
      - Translation progress
+   * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311
    * - `3.10 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-310

From 8602d5e6b7413731814e85181ab97032d384ccb7 Mon Sep 17 00:00:00 2001
From: Nyuan Zhang <blueglassblock@outlook.com>
Date: Mon, 27 Feb 2023 16:20:58 +0800
Subject: [PATCH 04/46] Update python-311.yml

---
 .github/workflows/python-311.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index e37354ae2..d2f7aee35 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -1,11 +1,11 @@
-name: python-310
+name: python-311
 
 on:
   push:
     branches:
       - master
   schedule:
-    - cron: "8 * * * *"
+    - cron: "11 * * * *"
 
 jobs:
   sync:

From 3554fc2397bf0d7975b5368b569ce36a8e81dc71 Mon Sep 17 00:00:00 2001
From: BlueGlassBlock <blueglassblock@outlook.com>
Date: Mon, 27 Feb 2023 17:59:07 +0800
Subject: [PATCH 05/46] Fix transifex cli position

---
 .github/scripts/update.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index 8424d2901..41279d019 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
 
-
+tx=$(realpath ./tx)
 cd docs || exit 1
-tx pull --languages "$LOCALE"
+$tx pull --languages "$LOCALE"

From c259ee1c2ba0576ceedbb67aeac979c85c9ebbd2 Mon Sep 17 00:00:00 2001
From: BlueGlassBlock <blueglassblock@outlook.com>
Date: Tue, 28 Feb 2023 14:11:44 +0800
Subject: [PATCH 06/46] Fix config generation script

---
 .github/scripts/generate_tx_config.py | 35 +++++++++++++++++++--------
 .github/scripts/update.sh             |  2 +-
 2 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/.github/scripts/generate_tx_config.py b/.github/scripts/generate_tx_config.py
index b21e099ee..f021d4ac9 100755
--- a/.github/scripts/generate_tx_config.py
+++ b/.github/scripts/generate_tx_config.py
@@ -1,4 +1,5 @@
 """Please note that this script requires a Transifex API token to run."""
+import glob
 import subprocess
 from functools import partial
 from pathlib import Path
@@ -32,20 +33,33 @@ def add_files(version: str):
 def name_replacer(match: re.Match[str]):
     prefix, resource = match.group("prefix", "resource")
     override_prefix = prefix.replace("file_filter", "trans.zh_CN")
-    override_resource = (
+    pattern = (
         resource.replace("trans/<lang>/", "")
-        .replace("--", "/")
         .replace("glossary_", "glossary")
-        .replace("_", ".")
+        .replace("--", "/")
+        .replace("_", "?")
     )
-    return f"{prefix}{resource}\n{override_prefix}{override_resource}"
-
-
-def patch_config():
+    matches = list(glob.glob(pattern.replace(".po", ".rst")))
+    if not matches:
+        print("missing", pattern)
+        return f"{prefix}{resource}\n{override_prefix}{pattern}"
+    elif len(matches) == 1:
+        filename = matches[0].replace(".rst", ".po").replace("\\", "/")
+    else:
+        raise ValueError("multi match", resource, pattern, matches)
+    return f"{prefix}{resource}\n{override_prefix}{filename}"
+
+
+def patch_config(path: str):
     tx_config_path = Path(".tx", "config")
 
     config_content = tx_config_path.read_text("utf-8")
+
+    cwd = os.getcwd()
+    os.chdir(path)
     config_content = FILTER_PATTERN.sub(name_replacer, config_content)
+    os.chdir(cwd)
+
     tx_config_path.write_text(config_content, "utf-8")
 
 
@@ -55,8 +69,9 @@ def patch_config():
 
     parser = ArgumentParser()
 
-    parser.add_argument("--token")
-    parser.add_argument("--version")
+    parser.add_argument("--token", required=True)
+    parser.add_argument("--version", required=True)
+    parser.add_argument("--doc-path", required=True)
 
     params = parser.parse_args()
 
@@ -64,4 +79,4 @@ def patch_config():
 
     init_project()
     add_files(params.version)
-    patch_config()
+    patch_config(params.doc_path)
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index 41279d019..bcdb2d7d9 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -2,4 +2,4 @@
 
 tx=$(realpath ./tx)
 cd docs || exit 1
-$tx pull --languages "$LOCALE"
+$tx pull --languages "$LOCALE" -t --use-git-timestamps

From 6d039834cda6b52dd18cefea6cde0ca8a2134fed Mon Sep 17 00:00:00 2001
From: BlueGlassBlock <blueglassblock@outlook.com>
Date: Tue, 28 Feb 2023 14:14:22 +0800
Subject: [PATCH 07/46] Add 3.11 to workflows

---
 README.rst | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index cf08f1294..d6847fc9c 100644
--- a/README.rst
+++ b/README.rst
@@ -15,11 +15,13 @@ Maintained versions:
    * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311
+     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/310
+          :target: https://www.transifex.com/python-doc/python-311/
    * - `3.10 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-310
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/310
-          :target: https://www.transifex.com/python-doc/python-39/
+          :target: https://www.transifex.com/python-doc/python-310/
    * - `3.9 <https://github.com/python/python-docs-zh-cn/tree/3.9>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-39/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-39

From c3d4b1a1b8502a649bfd502eee732cf25d723b0c Mon Sep 17 00:00:00 2001
From: BlueGlassBlock <blueglassblock@outlook.com>
Date: Sat, 13 May 2023 21:36:05 +0800
Subject: [PATCH 08/46] chore: update 3.11 links and badges

---
 README.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.rst b/README.rst
index d6847fc9c..53e6a6bed 100644
--- a/README.rst
+++ b/README.rst
@@ -12,10 +12,10 @@ Maintained versions:
    * - Version
      - Sync status
      - Translation progress
-   * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
+   * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.11>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/310
+     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/311
           :target: https://www.transifex.com/python-doc/python-311/
    * - `3.10 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg

From e01effbf98990f1f451c89ee77aa3af4089a5e33 Mon Sep 17 00:00:00 2001
From: BlueGlassBlock <blueglassblock@outlook.com>
Date: Mon, 29 May 2023 13:14:03 +0800
Subject: [PATCH 09/46] chore: Add 3.12 to workflow

---
 .github/scripts/generate_tx_config.py | 17 ++++++++--------
 .github/workflows/python-312.yml      | 29 +++++++++++++++++++++++++++
 README.rst                            | 15 +++++++++-----
 3 files changed, 48 insertions(+), 13 deletions(-)
 create mode 100644 .github/workflows/python-312.yml

diff --git a/.github/scripts/generate_tx_config.py b/.github/scripts/generate_tx_config.py
index f021d4ac9..ca3bb39e4 100755
--- a/.github/scripts/generate_tx_config.py
+++ b/.github/scripts/generate_tx_config.py
@@ -4,6 +4,7 @@
 from functools import partial
 from pathlib import Path
 import re
+import os
 
 run = partial(subprocess.run, check=True)
 
@@ -12,7 +13,7 @@ def init_project():
     run(["tx", "init"])
 
 
-def add_files(version: str):
+def add_files(project_name: str):
     run(
         [
             "tx",
@@ -20,7 +21,7 @@ def add_files(version: str):
             "remote",
             "--file-filter",
             "trans/<lang>/<resource_slug>.<ext>",
-            f"https://www.transifex.com/python-doc/{version}/dashboard/",
+            f"https://www.transifex.com/python-doc/{project_name}/dashboard/",
         ]
     )
 
@@ -42,7 +43,7 @@ def name_replacer(match: re.Match[str]):
     matches = list(glob.glob(pattern.replace(".po", ".rst")))
     if not matches:
         print("missing", pattern)
-        return f"{prefix}{resource}\n{override_prefix}{pattern}"
+        return f"{prefix}{resource}\n{override_prefix}{pattern.replace('?', '_')}"
     elif len(matches) == 1:
         filename = matches[0].replace(".rst", ".po").replace("\\", "/")
     else:
@@ -65,18 +66,18 @@ def patch_config(path: str):
 
 if __name__ == "__main__":
     from argparse import ArgumentParser
-    import os
 
     parser = ArgumentParser()
 
-    parser.add_argument("--token", required=True)
-    parser.add_argument("--version", required=True)
+    parser.add_argument("--token", default="")
+    parser.add_argument("--project-name", required=True)
     parser.add_argument("--doc-path", required=True)
 
     params = parser.parse_args()
 
-    os.environ["TX_TOKEN"] = params.token
+    if params.token:
+        os.environ["TX_TOKEN"] = params.token
 
     init_project()
-    add_files(params.version)
+    add_files(params.project_name)
     patch_config(params.doc_path)
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
new file mode 100644
index 000000000..51c5b3f6a
--- /dev/null
+++ b/.github/workflows/python-312.yml
@@ -0,0 +1,29 @@
+name: python-312
+
+on:
+  push:
+    branches:
+      - master
+  schedule:
+    - cron: "42 * * * *"
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    env:
+      LOCALE: zh_CN
+      VERSION: "3.12"
+    steps:
+      - uses: actions/checkout@v2
+      - name: prepare
+        run: .github/scripts/prepare.sh
+      - name: update
+        run: .github/scripts/update.sh
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: build
+        run: .github/scripts/build.sh
+      - name: commit
+        run: .github/scripts/commit.sh
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/README.rst b/README.rst
index 53e6a6bed..604acc8ba 100644
--- a/README.rst
+++ b/README.rst
@@ -12,31 +12,36 @@ Maintained versions:
    * - Version
      - Sync status
      - Translation progress
+   * - `3.12 <https://github.com/python/python-docs-zh-cn/tree/3.12>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-312/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-312
+     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/312
+          :target: https://app.transifex.com/python-doc/python-newest/
    * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.11>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/311
-          :target: https://www.transifex.com/python-doc/python-311/
+          :target: https://app.transifex.com/python-doc/python-311/
    * - `3.10 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-310
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/310
-          :target: https://www.transifex.com/python-doc/python-310/
+          :target: https://app.transifex.com/python-doc/python-310/
    * - `3.9 <https://github.com/python/python-docs-zh-cn/tree/3.9>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-39/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-39
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/39
-          :target: https://www.transifex.com/python-doc/python-39/
+          :target: https://app.transifex.com/python-doc/python-39/
    * - `3.8 <https://github.com/python/python-docs-zh-cn/tree/3.8>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-38/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/38
-          :target: https://www.transifex.com/python-doc/python-38/
+          :target: https://app.transifex.com/python-doc/python-38/
    * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/37
-          :target: https://www.transifex.com/python-doc/python-37/
+          :target: https://app.transifex.com/python-doc/python-37/
 
 Documentation Contribution Agreement
 ------------------------------------

From b40b5b2cecd1e03e28d09512ac8b9b61c26c18fa Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Tue, 20 Jun 2023 19:49:27 +0800
Subject: [PATCH 10/46] Commit

---
 .github/scripts/prepare.sh       |  3 ---
 .github/scripts/update.sh        |  3 +--
 .github/workflows/python-312.yml | 13 ++++++++++++-
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/.github/scripts/prepare.sh b/.github/scripts/prepare.sh
index cf1326646..970963db6 100755
--- a/.github/scripts/prepare.sh
+++ b/.github/scripts/prepare.sh
@@ -2,9 +2,6 @@
 
 set -ex
 
-git clone --depth=1 --branch="$VERSION" https://github.com/python/cpython cpython
-git clone --branch="$VERSION" https://github.com/"$GITHUB_REPOSITORY" docs
-
 pip3 install --user setuptools
 curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
 sudo apt-get update
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index bcdb2d7d9..b66e8758a 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,5 +1,4 @@
 #!/bin/bash
 
-tx=$(realpath ./tx)
 cd docs || exit 1
-$tx pull --languages "$LOCALE" -t --use-git-timestamps
+$(realpath ../tx) pull --languages "$LOCALE" -t --use-git-timestamps --worker 25
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 51c5b3f6a..4f0fbfd27 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -14,7 +14,18 @@ jobs:
       LOCALE: zh_CN
       VERSION: "3.12"
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
+      - name: Checkout CPython
+        uses: actions/checkout@v3
+        with:
+          repository: 'python/cpython'
+          ref: ${{env.VERSION}}
+          path: cpython
+      - name: Checkout Current Files
+        uses: actions/checkout@v3
+        with:
+          ref: ${{env.VERSION}}
+          path: docs
       - name: prepare
         run: .github/scripts/prepare.sh
       - name: update

From 0738865ffc16d6deaa29ac9d9712048b37d1c9ff Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Tue, 20 Jun 2023 19:51:00 +0800
Subject: [PATCH 11/46] commit

---
 .github/scripts/update.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index b66e8758a..d2f6f13be 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 
 cd docs || exit 1
-$(realpath ../tx) pull --languages "$LOCALE" -t --use-git-timestamps --worker 25
+$(realpath ../tx) pull --languages "$LOCALE" -t --use-git-timestamps --workers 25 --silent

From 2e0347328dc1287a9c730c7e4ce8ca5a2ce0ac7f Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Tue, 20 Jun 2023 20:07:25 +0800
Subject: [PATCH 12/46] Remove token

---
 .github/scripts/commit.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/commit.sh b/.github/scripts/commit.sh
index ae7d04096..da2acf89a 100755
--- a/.github/scripts/commit.sh
+++ b/.github/scripts/commit.sh
@@ -12,4 +12,4 @@ fi
 git add .
 git commit -m '[po] auto sync'
 header="$(echo -n token:"$GITHUB_TOKEN" | base64)"
-git -c http.extraheader="AUTHORIZATION: basic $header" push
+git push

From 2a26dfb8036869778e767edd1a0e17de6c9ddf91 Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 10:33:27 +0800
Subject: [PATCH 13/46] fix

---
 .github/workflows/python-312.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 4f0fbfd27..c3dde8a3c 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -21,7 +21,7 @@ jobs:
           repository: 'python/cpython'
           ref: ${{env.VERSION}}
           path: cpython
-      - name: Checkout Current Files
+      - name: Checkout Current Branch
         uses: actions/checkout@v3
         with:
           ref: ${{env.VERSION}}

From 3040c4b8056c6dd46cdbfdc56c3d7205f7a6c200 Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 10:56:04 +0800
Subject: [PATCH 14/46] remove venv

---
 .github/scripts/build.sh   | 4 ++--
 .github/scripts/prepare.sh | 3 ---
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index bbf4eb060..2cbcb8e11 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,5 +13,5 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
-make venv
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going -j2" 2> >(error)
+pip3 install -q -r requirements.txt
+make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
diff --git a/.github/scripts/prepare.sh b/.github/scripts/prepare.sh
index 970963db6..9b60c4479 100755
--- a/.github/scripts/prepare.sh
+++ b/.github/scripts/prepare.sh
@@ -2,7 +2,4 @@
 
 set -ex
 
-pip3 install --user setuptools
 curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
-sudo apt-get update
-sudo apt-get install -y python3-venv

From 15998601742e604bd87b64c48ee1db43f86c3fc5 Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 11:18:08 +0800
Subject: [PATCH 15/46] faster

---
 .github/scripts/build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 2cbcb8e11..720a268f0 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -14,4 +14,4 @@ cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
 pip3 install -q -r requirements.txt
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
+make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -D html_copy_source=False -W --keep-going" 2> >(error)

From 296c3d3eb94f299e25046ea15cb1c7f37690b4a7 Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 11:58:13 +0800
Subject: [PATCH 16/46] search

---
 .github/scripts/build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 720a268f0..ca2b7dba9 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -14,4 +14,4 @@ cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
 pip3 install -q -r requirements.txt
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -D html_copy_source=False -W --keep-going" 2> >(error)
+make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -D html_search_language='' -W --keep-going" 2> >(error)

From 52551de04d32a304daaa83b0938733a180ee44d6 Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 12:39:16 +0800
Subject: [PATCH 17/46] cache

---
 .github/scripts/commit.sh        |  1 -
 .github/workflows/python-312.yml | 12 ++++++++++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/.github/scripts/commit.sh b/.github/scripts/commit.sh
index da2acf89a..878c0d57e 100755
--- a/.github/scripts/commit.sh
+++ b/.github/scripts/commit.sh
@@ -11,5 +11,4 @@ if ! git status -s|grep '\.po'; then
 fi
 git add .
 git commit -m '[po] auto sync'
-header="$(echo -n token:"$GITHUB_TOKEN" | base64)"
 git push
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index c3dde8a3c..b4a8f5b84 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -32,9 +32,17 @@ jobs:
         run: .github/scripts/update.sh
         env:
           TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: Restore doctrees Cache
+        uses: actions/cache/restore@v3
+        with:
+          path: ./cpython/Doc/build/doctrees
+          key: sphinx-cache-${{env.VERSION}}
       - name: build
         run: .github/scripts/build.sh
+      - name: Save doctrees Cache
+        uses: actions/cache/save@v3
+        with:
+          path: ./cpython/Doc/build/doctrees
+          key: sphinx-cache-${{env.VERSION}}
       - name: commit
         run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

From 73af92c9fee9ba88ee7a327eda23be3df63ca01b Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 12:49:40 +0800
Subject: [PATCH 18/46] update cache path

---
 .github/scripts/build.sh         | 2 +-
 .github/workflows/python-312.yml | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index ca2b7dba9..2cbcb8e11 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -14,4 +14,4 @@ cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
 pip3 install -q -r requirements.txt
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -D html_search_language='' -W --keep-going" 2> >(error)
+make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index b4a8f5b84..b3338b880 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -32,17 +32,17 @@ jobs:
         run: .github/scripts/update.sh
         env:
           TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: Restore doctrees Cache
+      - name: Restore build Cache
         uses: actions/cache/restore@v3
         with:
-          path: ./cpython/Doc/build/doctrees
+          path: ./cpython/Doc/build
           key: sphinx-cache-${{env.VERSION}}
       - name: build
         run: .github/scripts/build.sh
-      - name: Save doctrees Cache
+      - name: Save build Cache
         uses: actions/cache/save@v3
         with:
-          path: ./cpython/Doc/build/doctrees
+          path: ./cpython/Doc/build
           key: sphinx-cache-${{env.VERSION}}
       - name: commit
         run: .github/scripts/commit.sh

From 7c46dfd1d62b9db942c163e7119912cd6dcfc4fc Mon Sep 17 00:00:00 2001
From: A <793763955@qq.com>
Date: Wed, 21 Jun 2023 13:56:36 +0800
Subject: [PATCH 19/46] remove cache

---
 .github/workflows/python-312.yml | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index b3338b880..bc9a5b47b 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -32,17 +32,7 @@ jobs:
         run: .github/scripts/update.sh
         env:
           TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: Restore build Cache
-        uses: actions/cache/restore@v3
-        with:
-          path: ./cpython/Doc/build
-          key: sphinx-cache-${{env.VERSION}}
       - name: build
         run: .github/scripts/build.sh
-      - name: Save build Cache
-        uses: actions/cache/save@v3
-        with:
-          path: ./cpython/Doc/build
-          key: sphinx-cache-${{env.VERSION}}
       - name: commit
         run: .github/scripts/commit.sh

From df8186d4ceeb7e75e37587bfbe948097aff5bbe4 Mon Sep 17 00:00:00 2001
From: Nyuan Zhang <blueglassblock@outlook.com>
Date: Thu, 3 Aug 2023 15:08:39 +0800
Subject: [PATCH 20/46] Update to Python 3.12 (#301)

* Update to Python 3.11

* Update python-311.yml

* Fix transifex cli position

* Fix config generation script

* Add 3.11 to workflows

* chore: update 3.11 links and badges

* chore: Add 3.12 to workflow
---
 .github/scripts/generate_tx_config.py | 135 ++++++++++++++------------
 .github/scripts/prepare.sh            |   2 +-
 .github/scripts/transifex_pull.py     |  38 --------
 .github/scripts/update.sh             |  17 +---
 .github/workflows/python-310.yml      |   2 +-
 .github/workflows/python-311.yml      |  29 ++++++
 .github/workflows/python-312.yml      |  29 ++++++
 .github/workflows/python-37.yml       |   2 +-
 .github/workflows/python-38.yml       |   2 +-
 .github/workflows/python-39.yml       |   2 +-
 README.rst                            |  18 +++-
 11 files changed, 150 insertions(+), 126 deletions(-)
 delete mode 100755 .github/scripts/transifex_pull.py
 create mode 100644 .github/workflows/python-311.yml
 create mode 100644 .github/workflows/python-312.yml

diff --git a/.github/scripts/generate_tx_config.py b/.github/scripts/generate_tx_config.py
index 0e72833f1..ca3bb39e4 100755
--- a/.github/scripts/generate_tx_config.py
+++ b/.github/scripts/generate_tx_config.py
@@ -1,76 +1,83 @@
-#!/usr/bin/env python3
+"""Please note that this script requires a Transifex API token to run."""
 import glob
-import json
-import os
+import subprocess
+from functools import partial
+from pathlib import Path
 import re
-import sys
-import urllib.request
+import os
+
+run = partial(subprocess.run, check=True)
+
 
+def init_project():
+    run(["tx", "init"])
 
-def list_resources(token, project):
-    auth_handler = urllib.request.HTTPBasicAuthHandler()
-    auth_handler.add_password(
-        realm="api", uri="https://api.transifex.com/", user="api", passwd=token
+
+def add_files(project_name: str):
+    run(
+        [
+            "tx",
+            "add",
+            "remote",
+            "--file-filter",
+            "trans/<lang>/<resource_slug>.<ext>",
+            f"https://www.transifex.com/python-doc/{project_name}/dashboard/",
+        ]
     )
-    opener = urllib.request.build_opener(auth_handler)
-    urllib.request.install_opener(opener)
-    next_ = (
-        "https://api.transifex.com/organizations/python-doc/projects/"
-        + project
-        + "/resources/"
+
+
+FILTER_PATTERN = re.compile(
+    r"^(?P<prefix>file_filter( *)=( *))(?P<resource>.+)$", re.MULTILINE
+)
+
+
+def name_replacer(match: re.Match[str]):
+    prefix, resource = match.group("prefix", "resource")
+    override_prefix = prefix.replace("file_filter", "trans.zh_CN")
+    pattern = (
+        resource.replace("trans/<lang>/", "")
+        .replace("glossary_", "glossary")
+        .replace("--", "/")
+        .replace("_", "?")
     )
-    resources = []
-    while True:
-        resp = urllib.request.urlopen(next_)
-        result = json.loads(resp.read().decode("utf-8"))
-        resources.extend([i["slug"] for i in result])
-        link = re.findall('<([^<]*)>; rel="next"', resp.getheader("Link") or "")
-        if not link:
-            break
-        next_ = link[0]
-    return resources
-
-
-def render_config(doc_dir, project, resources):
-    os.chdir(doc_dir)
-    tpl = """
-
-[{project}.{resource}]
-trans.zh_CN = {filename}
-source_lang = en
-type = PO"""
-    conf = """[main]
-host = https://www.transifex.com"""
-    for resource in sorted(resources):
-        if resource == "glossary_":
-            filename = "glossary.po"
-        elif resource == "sphinx":
-            filename = "sphinx.po"
-        else:
-            pattern = resource.replace("--", "/").replace("_", "?")
-            matches = glob.glob(pattern + ".rst")
-            if len(matches) == 0:
-                print("missing", resource, file=sys.stderr)
-                continue
-            elif len(matches) == 1:
-                filename = matches[0].replace(".rst", ".po")
-            else:
-                print("multi match", resource, pattern, matches, file=sys.stderr)
-        conf += tpl.format(project=project, resource=resource, filename=filename)
-    return conf
+    matches = list(glob.glob(pattern.replace(".po", ".rst")))
+    if not matches:
+        print("missing", pattern)
+        return f"{prefix}{resource}\n{override_prefix}{pattern.replace('?', '_')}"
+    elif len(matches) == 1:
+        filename = matches[0].replace(".rst", ".po").replace("\\", "/")
+    else:
+        raise ValueError("multi match", resource, pattern, matches)
+    return f"{prefix}{resource}\n{override_prefix}{filename}"
+
+
+def patch_config(path: str):
+    tx_config_path = Path(".tx", "config")
+
+    config_content = tx_config_path.read_text("utf-8")
+
+    cwd = os.getcwd()
+    os.chdir(path)
+    config_content = FILTER_PATTERN.sub(name_replacer, config_content)
+    os.chdir(cwd)
+
+    tx_config_path.write_text(config_content, "utf-8")
 
 
 if __name__ == "__main__":
-    import argparse
+    from argparse import ArgumentParser
+
+    parser = ArgumentParser()
+
+    parser.add_argument("--token", default="")
+    parser.add_argument("--project-name", required=True)
+    parser.add_argument("--doc-path", required=True)
 
-    parser = argparse.ArgumentParser()
-    parser.add_argument("--token")
-    parser.add_argument("--project")
-    parser.add_argument("--doc-dir")
-    args = parser.parse_args()
+    params = parser.parse_args()
 
-    resources = list_resources(args.token, args.project)
-    conf = render_config(args.doc_dir, args.project, resources)
-    print(conf)
+    if params.token:
+        os.environ["TX_TOKEN"] = params.token
 
-# vim: set et ts=4 sw=4 sts=4:
+    init_project()
+    add_files(params.project_name)
+    patch_config(params.doc_path)
diff --git a/.github/scripts/prepare.sh b/.github/scripts/prepare.sh
index d16dbc056..cf1326646 100755
--- a/.github/scripts/prepare.sh
+++ b/.github/scripts/prepare.sh
@@ -6,6 +6,6 @@ git clone --depth=1 --branch="$VERSION" https://github.com/python/cpython cpytho
 git clone --branch="$VERSION" https://github.com/"$GITHUB_REPOSITORY" docs
 
 pip3 install --user setuptools
-pip3 install --user transifex-client
+curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
 sudo apt-get update
 sudo apt-get install -y python3-venv
diff --git a/.github/scripts/transifex_pull.py b/.github/scripts/transifex_pull.py
deleted file mode 100755
index 66c4046d9..000000000
--- a/.github/scripts/transifex_pull.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-
-from txclib import project
-from txclib.utils import perform_parallel_requests
-
-
-def pull(path, lang):
-    skip_decode = False
-    params = {}
-    parallel = True
-
-    prj = project.Project(path)
-    resource_list = prj.get_chosen_resources([])
-    for resource in resource_list:
-        project_slug, resource_slug = resource.split(".", 1)
-        host = prj.get_resource_host(resource)
-        prj._set_url_info(host=host, project=project_slug, resource=resource_slug)
-
-        files = prj.get_resource_files(resource)
-        url = prj._get_url_by_pull_mode(None)
-        local_file = files.get(lang)
-        prj.do_url_request(
-            url,
-            language=lang,
-            skip_decode=skip_decode,
-            params=params,
-            parallel=parallel,
-            callback=prj._save_file,
-            callback_args={"local_file": local_file},
-        )
-
-    perform_parallel_requests()
-
-
-if __name__ == "__main__":
-    import os
-
-    pull(os.getcwd(), os.getenv("LOCALE", "zh_CN"))
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index 544a31ae5..bcdb2d7d9 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,18 +1,5 @@
 #!/bin/bash
 
-set -ex
-
-script_dir="$(dirname "$(realpath "$0")")"
-
-if [[ -n "$TRANSIFEX_APIKEY" ]]; then
-  cat > ~/.transifexrc << EOF
-[https://www.transifex.com]
-api_hostname = https://api.transifex.com
-hostname = https://www.transifex.com
-password = $TRANSIFEX_APIKEY
-username = api
-EOF
-fi
-
+tx=$(realpath ./tx)
 cd docs || exit 1
-"$script_dir"/transifex_pull.py
+$tx pull --languages "$LOCALE" -t --use-git-timestamps
diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 54037983e..5524337ef 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
new file mode 100644
index 000000000..d2f7aee35
--- /dev/null
+++ b/.github/workflows/python-311.yml
@@ -0,0 +1,29 @@
+name: python-311
+
+on:
+  push:
+    branches:
+      - master
+  schedule:
+    - cron: "11 * * * *"
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    env:
+      LOCALE: zh_CN
+      VERSION: "3.11"
+    steps:
+      - uses: actions/checkout@v2
+      - name: prepare
+        run: .github/scripts/prepare.sh
+      - name: update
+        run: .github/scripts/update.sh
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: build
+        run: .github/scripts/build.sh
+      - name: commit
+        run: .github/scripts/commit.sh
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
new file mode 100644
index 000000000..51c5b3f6a
--- /dev/null
+++ b/.github/workflows/python-312.yml
@@ -0,0 +1,29 @@
+name: python-312
+
+on:
+  push:
+    branches:
+      - master
+  schedule:
+    - cron: "42 * * * *"
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    env:
+      LOCALE: zh_CN
+      VERSION: "3.12"
+    steps:
+      - uses: actions/checkout@v2
+      - name: prepare
+        run: .github/scripts/prepare.sh
+      - name: update
+        run: .github/scripts/update.sh
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: build
+        run: .github/scripts/build.sh
+      - name: commit
+        run: .github/scripts/commit.sh
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/python-37.yml b/.github/workflows/python-37.yml
index c35d61d2b..6864df933 100644
--- a/.github/workflows/python-37.yml
+++ b/.github/workflows/python-37.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index a99f0e20e..35948544c 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 76a6793bb..4b16958a5 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -20,7 +20,7 @@ jobs:
       - name: update
         run: .github/scripts/update.sh
         env:
-          TRANSIFEX_APIKEY: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
       - name: commit
diff --git a/README.rst b/README.rst
index 4ff062bc4..604acc8ba 100644
--- a/README.rst
+++ b/README.rst
@@ -12,26 +12,36 @@ Maintained versions:
    * - Version
      - Sync status
      - Translation progress
+   * - `3.12 <https://github.com/python/python-docs-zh-cn/tree/3.12>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-312/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-312
+     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/312
+          :target: https://app.transifex.com/python-doc/python-newest/
+   * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.11>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311
+     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/311
+          :target: https://app.transifex.com/python-doc/python-311/
    * - `3.10 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-310
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/310
-          :target: https://www.transifex.com/python-doc/python-39/
+          :target: https://app.transifex.com/python-doc/python-310/
    * - `3.9 <https://github.com/python/python-docs-zh-cn/tree/3.9>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-39/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-39
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/39
-          :target: https://www.transifex.com/python-doc/python-39/
+          :target: https://app.transifex.com/python-doc/python-39/
    * - `3.8 <https://github.com/python/python-docs-zh-cn/tree/3.8>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-38/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/38
-          :target: https://www.transifex.com/python-doc/python-38/
+          :target: https://app.transifex.com/python-doc/python-38/
    * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/37
-          :target: https://www.transifex.com/python-doc/python-37/
+          :target: https://app.transifex.com/python-doc/python-37/
 
 Documentation Contribution Agreement
 ------------------------------------

From c6da1da3c831474afeb129c8c3106345ebb310d7 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 15:40:47 +0800
Subject: [PATCH 21/46] Add reusable workflow

---
 .github/workflows/python-312.yml | 31 ++++--------------------
 .github/workflows/sync.yml       | 41 ++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 27 deletions(-)
 create mode 100644 .github/workflows/sync.yml

diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index bc9a5b47b..44a05ee9e 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -9,30 +9,7 @@ on:
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.12"
-    steps:
-      - uses: actions/checkout@v3
-      - name: Checkout CPython
-        uses: actions/checkout@v3
-        with:
-          repository: 'python/cpython'
-          ref: ${{env.VERSION}}
-          path: cpython
-      - name: Checkout Current Branch
-        uses: actions/checkout@v3
-        with:
-          ref: ${{env.VERSION}}
-          path: docs
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.12"
+    secrets: inherit
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
new file mode 100644
index 000000000..a5a126e20
--- /dev/null
+++ b/.github/workflows/sync.yml
@@ -0,0 +1,41 @@
+name: Reusable workflow example
+
+on:
+  workflow_call:
+    inputs:
+      version:
+        required: true
+        type: string
+    secrets:
+      TRANSIFEX_APIKEY:
+        required: true
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    env:
+      LOCALE: zh_CN
+      VERSION: ${{ inputs.version }}
+    steps:
+      - uses: actions/checkout@v3
+      - name: Checkout CPython
+        uses: actions/checkout@v3
+        with:
+          repository: 'python/cpython'
+          ref: ${{env.VERSION}}
+          path: cpython
+      - name: Checkout Current Branch
+        uses: actions/checkout@v3
+        with:
+          ref: ${{env.VERSION}}
+          path: docs
+      - name: prepare
+        run: .github/scripts/prepare.sh
+      - name: update
+        run: .github/scripts/update.sh
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: build
+        run: .github/scripts/build.sh
+      - name: commit
+        run: .github/scripts/commit.sh
\ No newline at end of file

From 2200481fe14145cca4e85fd04c6455eb792a2953 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 15:53:53 +0800
Subject: [PATCH 22/46] Update all workflows

---
 .github/workflows/python-310.yml | 23 +++++------------------
 .github/workflows/python-311.yml | 23 +++++------------------
 .github/workflows/python-37.yml  | 22 ++++------------------
 .github/workflows/python-38.yml  | 22 ++++------------------
 .github/workflows/python-39.yml  | 23 +++++------------------
 5 files changed, 23 insertions(+), 90 deletions(-)

diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 5524337ef..84b9c7ff6 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -9,21 +9,8 @@ on:
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.10"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.10"
+    secrets: inherit
+    
\ No newline at end of file
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index d2f7aee35..4c3cf79f1 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -9,21 +9,8 @@ on:
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.11"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.11"
+    secrets: inherit
+    
diff --git a/.github/workflows/python-37.yml b/.github/workflows/python-37.yml
index 6864df933..9aa726015 100644
--- a/.github/workflows/python-37.yml
+++ b/.github/workflows/python-37.yml
@@ -9,21 +9,7 @@ on:
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.7"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.7"
+    secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index 35948544c..41fa86e01 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -9,21 +9,7 @@ on:
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.8"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.8"
+    secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 4b16958a5..0d0e60aa4 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -9,21 +9,8 @@ on:
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.9"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.9"
+    secrets: inherit
+    
\ No newline at end of file

From 7ab7c930930663095f6d41e3683b8c57a5b8523d Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 15:59:37 +0800
Subject: [PATCH 23/46] Update workflows schedule

---
 .github/workflows/python-310.yml | 2 +-
 .github/workflows/python-311.yml | 2 +-
 .github/workflows/python-312.yml | 2 +-
 .github/workflows/python-37.yml  | 2 +-
 .github/workflows/python-38.yml  | 2 +-
 .github/workflows/python-39.yml  | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 84b9c7ff6..10e299b45 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "8 * * * *"
+    - cron: "26 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index 4c3cf79f1..3ac6cf1ba 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "11 * * * *"
+    - cron: "38 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 44a05ee9e..228e64d78 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "42 * * * *"
+    - cron: "50 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-37.yml b/.github/workflows/python-37.yml
index 9aa726015..867c77ad3 100644
--- a/.github/workflows/python-37.yml
+++ b/.github/workflows/python-37.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "53 * * * *"
+    - cron: "0 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index 41fa86e01..e3725dc36 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "38 * * * *"
+    - cron: "2 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 0d0e60aa4..458459371 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "23 * * * *"
+    - cron: "14 * * * *"
 
 jobs:
   sync:

From 0147e2bd42249a90a3c342bc3d77b5ccc9ea0807 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:00:16 +0800
Subject: [PATCH 24/46] Use docsbuild-scripts to build

---
 .github/scripts/build.sh   | 5 ++++-
 .github/workflows/sync.yml | 5 +++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 2cbcb8e11..bb8e643b3 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,5 +13,8 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
+
+cd ../../docsbuild/
 pip3 install -q -r requirements.txt
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
+python3 ./build_docs.py --quick --build-root ./build_root --www-root ./www --skip-cache-invalidation --language $LOCALE --branch $VERSION
+# make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index a5a126e20..2508339d2 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -29,6 +29,11 @@ jobs:
         with:
           ref: ${{env.VERSION}}
           path: docs
+      - name: Checkout Build Scripts
+        uses: actions/checkout@v3
+        with:
+          ref: ${{env.VERSION}}
+          path: docsbuild
       - name: prepare
         run: .github/scripts/prepare.sh
       - name: update

From 345361d30218cd9fda030cbb52dc027535665081 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:06:08 +0800
Subject: [PATCH 25/46] install python docs packages

---
 .github/scripts/build.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index bb8e643b3..3bc169765 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,6 +13,7 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
+pip3 install -q -r requirements.txt
 
 cd ../../docsbuild/
 pip3 install -q -r requirements.txt

From 8bb7d448ee695d765d3913716086a1fefc1e816f Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:08:32 +0800
Subject: [PATCH 26/46] Add docsbuild-scripts repo

---
 .github/workflows/sync.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index 2508339d2..ef04046ac 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -32,6 +32,7 @@ jobs:
       - name: Checkout Build Scripts
         uses: actions/checkout@v3
         with:
+          repository: 'python/docsbuild-scripts'
           ref: ${{env.VERSION}}
           path: docsbuild
       - name: prepare

From 0aa564649b0b67235e0092f24cc36d7046360c37 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:30:14 +0800
Subject: [PATCH 27/46] remvoe docsbuild-scripts

---
 .github/scripts/build.sh   | 7 +------
 .github/workflows/sync.yml | 6 ------
 2 files changed, 1 insertion(+), 12 deletions(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 3bc169765..8d420e12f 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,9 +13,4 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
-pip3 install -q -r requirements.txt
-
-cd ../../docsbuild/
-pip3 install -q -r requirements.txt
-python3 ./build_docs.py --quick --build-root ./build_root --www-root ./www --skip-cache-invalidation --language $LOCALE --branch $VERSION
-# make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
+make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index ef04046ac..a5a126e20 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -29,12 +29,6 @@ jobs:
         with:
           ref: ${{env.VERSION}}
           path: docs
-      - name: Checkout Build Scripts
-        uses: actions/checkout@v3
-        with:
-          repository: 'python/docsbuild-scripts'
-          ref: ${{env.VERSION}}
-          path: docsbuild
       - name: prepare
         run: .github/scripts/prepare.sh
       - name: update

From c2b3e9648a026e2677b3d5ff5a9ddd8709db6bb2 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:32:56 +0800
Subject: [PATCH 28/46] Add env setup

---
 .github/scripts/build.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 8d420e12f..2cbcb8e11 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,4 +13,5 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
+pip3 install -q -r requirements.txt
 make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)

From 4592fcd942df8b9e5ebc9bd4ccfdd34f3d256e1a Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:43:09 +0800
Subject: [PATCH 29/46] Update workflow and make it reusable (#315)

* Update workflow definition and dependencies version.
* Simplify the code structure.
* Make workflow reusable across versions.
---
 .github/scripts/build.sh         |  4 ++--
 .github/scripts/commit.sh        |  3 +--
 .github/scripts/prepare.sh       |  8 +------
 .github/scripts/update.sh        |  3 +--
 .github/workflows/python-310.yml | 25 +++++--------------
 .github/workflows/python-311.yml | 25 +++++--------------
 .github/workflows/python-312.yml | 24 ++++---------------
 .github/workflows/python-37.yml  | 24 ++++---------------
 .github/workflows/python-38.yml  | 24 ++++---------------
 .github/workflows/python-39.yml  | 25 +++++--------------
 .github/workflows/sync.yml       | 41 ++++++++++++++++++++++++++++++++
 11 files changed, 79 insertions(+), 127 deletions(-)
 create mode 100644 .github/workflows/sync.yml

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index bbf4eb060..2cbcb8e11 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -13,5 +13,5 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
-make venv
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going -j2" 2> >(error)
+pip3 install -q -r requirements.txt
+make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
diff --git a/.github/scripts/commit.sh b/.github/scripts/commit.sh
index ae7d04096..878c0d57e 100755
--- a/.github/scripts/commit.sh
+++ b/.github/scripts/commit.sh
@@ -11,5 +11,4 @@ if ! git status -s|grep '\.po'; then
 fi
 git add .
 git commit -m '[po] auto sync'
-header="$(echo -n token:"$GITHUB_TOKEN" | base64)"
-git -c http.extraheader="AUTHORIZATION: basic $header" push
+git push
diff --git a/.github/scripts/prepare.sh b/.github/scripts/prepare.sh
index cf1326646..1ca5daab0 100755
--- a/.github/scripts/prepare.sh
+++ b/.github/scripts/prepare.sh
@@ -2,10 +2,4 @@
 
 set -ex
 
-git clone --depth=1 --branch="$VERSION" https://github.com/python/cpython cpython
-git clone --branch="$VERSION" https://github.com/"$GITHUB_REPOSITORY" docs
-
-pip3 install --user setuptools
-curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
-sudo apt-get update
-sudo apt-get install -y python3-venv
+curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
\ No newline at end of file
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index bcdb2d7d9..d2f6f13be 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,5 +1,4 @@
 #!/bin/bash
 
-tx=$(realpath ./tx)
 cd docs || exit 1
-$tx pull --languages "$LOCALE" -t --use-git-timestamps
+$(realpath ../tx) pull --languages "$LOCALE" -t --use-git-timestamps --workers 25 --silent
diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 5524337ef..10e299b45 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -5,25 +5,12 @@ on:
     branches:
       - master
   schedule:
-    - cron: "8 * * * *"
+    - cron: "26 * * * *"
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.10"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.10"
+    secrets: inherit
+    
\ No newline at end of file
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index d2f7aee35..3ac6cf1ba 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -5,25 +5,12 @@ on:
     branches:
       - master
   schedule:
-    - cron: "11 * * * *"
+    - cron: "38 * * * *"
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.11"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.11"
+    secrets: inherit
+    
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 51c5b3f6a..228e64d78 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -5,25 +5,11 @@ on:
     branches:
       - master
   schedule:
-    - cron: "42 * * * *"
+    - cron: "50 * * * *"
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.12"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.12"
+    secrets: inherit
diff --git a/.github/workflows/python-37.yml b/.github/workflows/python-37.yml
index 6864df933..867c77ad3 100644
--- a/.github/workflows/python-37.yml
+++ b/.github/workflows/python-37.yml
@@ -5,25 +5,11 @@ on:
     branches:
       - master
   schedule:
-    - cron: "53 * * * *"
+    - cron: "0 * * * *"
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.7"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.7"
+    secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index 35948544c..e3725dc36 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -5,25 +5,11 @@ on:
     branches:
       - master
   schedule:
-    - cron: "38 * * * *"
+    - cron: "2 * * * *"
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.8"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.8"
+    secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 4b16958a5..458459371 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -5,25 +5,12 @@ on:
     branches:
       - master
   schedule:
-    - cron: "23 * * * *"
+    - cron: "14 * * * *"
 
 jobs:
   sync:
-    runs-on: ubuntu-latest
-    env:
-      LOCALE: zh_CN
-      VERSION: "3.9"
-    steps:
-      - uses: actions/checkout@v2
-      - name: prepare
-        run: .github/scripts/prepare.sh
-      - name: update
-        run: .github/scripts/update.sh
-        env:
-          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - name: build
-        run: .github/scripts/build.sh
-      - name: commit
-        run: .github/scripts/commit.sh
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.9"
+    secrets: inherit
+    
\ No newline at end of file
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
new file mode 100644
index 000000000..a5a126e20
--- /dev/null
+++ b/.github/workflows/sync.yml
@@ -0,0 +1,41 @@
+name: Reusable workflow example
+
+on:
+  workflow_call:
+    inputs:
+      version:
+        required: true
+        type: string
+    secrets:
+      TRANSIFEX_APIKEY:
+        required: true
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    env:
+      LOCALE: zh_CN
+      VERSION: ${{ inputs.version }}
+    steps:
+      - uses: actions/checkout@v3
+      - name: Checkout CPython
+        uses: actions/checkout@v3
+        with:
+          repository: 'python/cpython'
+          ref: ${{env.VERSION}}
+          path: cpython
+      - name: Checkout Current Branch
+        uses: actions/checkout@v3
+        with:
+          ref: ${{env.VERSION}}
+          path: docs
+      - name: prepare
+        run: .github/scripts/prepare.sh
+      - name: update
+        run: .github/scripts/update.sh
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - name: build
+        run: .github/scripts/build.sh
+      - name: commit
+        run: .github/scripts/commit.sh
\ No newline at end of file

From 2f78e1957c2b7c8cd8e3e5d0e522b079b60583b2 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:55:13 +0800
Subject: [PATCH 30/46] Update 3.7 to EOL

---
 .github/workflows/python-37.yml | 7 +------
 README.rst                      | 2 +-
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/python-37.yml b/.github/workflows/python-37.yml
index 867c77ad3..47c224c3b 100644
--- a/.github/workflows/python-37.yml
+++ b/.github/workflows/python-37.yml
@@ -1,11 +1,6 @@
 name: python-37
 
-on:
-  push:
-    branches:
-      - master
-  schedule:
-    - cron: "0 * * * *"
+on: workflow_dispatch
 
 jobs:
   sync:
diff --git a/README.rst b/README.rst
index 604acc8ba..33129de16 100644
--- a/README.rst
+++ b/README.rst
@@ -37,7 +37,7 @@ Maintained versions:
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/38
           :target: https://app.transifex.com/python-doc/python-38/
-   * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_
+   * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_ [EOL]
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/37

From 0ce16a079ffdf51ae1d99daf70f2486f5e71c2a9 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 22:57:10 +0800
Subject: [PATCH 31/46] Add EOL table

---
 README.rst | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index 33129de16..3d791ca4a 100644
--- a/README.rst
+++ b/README.rst
@@ -37,7 +37,16 @@ Maintained versions:
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/38
           :target: https://app.transifex.com/python-doc/python-38/
-   * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_ [EOL]
+
+EOL versions:
+
+.. list-table::
+   :header-rows: 1
+
+   * - Version
+     - Sync status
+     - Translation progress
+   * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37
      - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/37

From fdb12f61705a81ca2ea163964702f277c1054400 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Thu, 3 Aug 2023 23:50:45 +0800
Subject: [PATCH 32/46] Add issue template (#317)

---
 .github/ISSUE_TEMPLATE/translation.yml | 46 ++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 .github/ISSUE_TEMPLATE/translation.yml

diff --git a/.github/ISSUE_TEMPLATE/translation.yml b/.github/ISSUE_TEMPLATE/translation.yml
new file mode 100644
index 000000000..6ed458362
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/translation.yml
@@ -0,0 +1,46 @@
+name: Translation Issue Report
+description: File a translation issue report
+title: "[Typo]: "
+labels: ["translation"]
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thanks for taking the time to fill out this translation issue report!
+  - type: input
+    id: version
+    attributes:
+      label: Python Version
+      description: Which version of Python docs contains the issue?
+      placeholder: ex. 3.12
+    validations:
+      required: true
+  - type: input
+    id: url
+    attributes:
+      label: Docs Page
+      description: What is the url of the page contains the issue?
+      placeholder: https://docs.python.org/3/about.html
+    validations:
+      required: true
+  - type: textarea
+    id: zh-original
+    attributes:
+      label: Original Translation
+      description: Which translated paragraph in Chinese contains the issue?
+    validations:
+      required: true
+  - type: textarea
+    id: en-original
+    attributes:
+      label: Original Docs Paragraph
+      description: Which original paragraph in English contains the issue?
+    validations:
+      required: false
+  - type: textarea
+    id: zh-suggested
+    attributes:
+      label: Suggested Fix
+      description: What is you suggeest fix?
+    validations:
+      required: true
\ No newline at end of file

From 09da4827a6030168c1144721195b236baabd3f19 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Fri, 4 Aug 2023 13:15:38 +0800
Subject: [PATCH 33/46] Fix translation progress badges (#318)

Create a new `.stat.json` file for each sync. A badge will be generated based on this stat file.
---
 .github/ISSUE_TEMPLATE/translation.yml |  6 ++---
 .github/scripts/tx_stat.py             | 33 ++++++++++++++++++++++++++
 .github/workflows/python-310.yml       |  1 +
 .github/workflows/python-311.yml       |  1 +
 .github/workflows/python-312.yml       |  1 +
 .github/workflows/python-38.yml        |  1 +
 .github/workflows/python-39.yml        |  1 +
 .github/workflows/sync.yml             |  8 +++++++
 README.rst                             | 12 +++++-----
 9 files changed, 55 insertions(+), 9 deletions(-)
 create mode 100644 .github/scripts/tx_stat.py

diff --git a/.github/ISSUE_TEMPLATE/translation.yml b/.github/ISSUE_TEMPLATE/translation.yml
index 6ed458362..780ebc722 100644
--- a/.github/ISSUE_TEMPLATE/translation.yml
+++ b/.github/ISSUE_TEMPLATE/translation.yml
@@ -11,7 +11,7 @@ body:
     id: version
     attributes:
       label: Python Version
-      description: Which version of Python docs contains the issue?
+      description: Which version of the Python documentation covers this issue?
       placeholder: ex. 3.12
     validations:
       required: true
@@ -19,7 +19,7 @@ body:
     id: url
     attributes:
       label: Docs Page
-      description: What is the url of the page contains the issue?
+      description: What is the url of the page containing the issue?
       placeholder: https://docs.python.org/3/about.html
     validations:
       required: true
@@ -41,6 +41,6 @@ body:
     id: zh-suggested
     attributes:
       label: Suggested Fix
-      description: What is you suggeest fix?
+      description: What is your suggested fix?
     validations:
       required: true
\ No newline at end of file
diff --git a/.github/scripts/tx_stat.py b/.github/scripts/tx_stat.py
new file mode 100644
index 000000000..00dcf965c
--- /dev/null
+++ b/.github/scripts/tx_stat.py
@@ -0,0 +1,33 @@
+import json
+import os
+import urllib.request
+from datetime import datetime
+
+key = os.environ.get('TX_TOKEN')
+project = os.environ.get('TX_PROJECT')
+
+url = "https://rest.api.transifex.com/resource_language_stats?filter[project]=o%3Apython-doc%3Ap%3A{}&filter[language]=l%3Azh_CN".format(project)
+
+headers = {
+    "accept": "application/vnd.api+json",
+    "authorization": "Bearer " + key
+}
+
+total = 0
+translated = 0
+
+while(url):
+    request = urllib.request.Request(url=url,headers=headers)
+
+    with urllib.request.urlopen(request) as response:
+        data = json.loads(response.read().decode("utf-8"))
+        url = data['links'].get('next')
+        for resourse in data['data']:
+            translated = translated + resourse['attributes']['translated_strings']
+            total =  total + resourse['attributes']['total_strings']
+
+p = '{:.2%}'.format(translated/total)
+print(json.dumps({
+    'translation':p,
+    'updated_at':datetime.utcnow().isoformat(timespec='seconds') + 'Z',
+    }))
\ No newline at end of file
diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 10e299b45..6607518d7 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -12,5 +12,6 @@ jobs:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.10"
+      tx_project: "python-310"
     secrets: inherit
     
\ No newline at end of file
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index 3ac6cf1ba..9566d743f 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -12,5 +12,6 @@ jobs:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.11"
+      tx_project: "python-311"
     secrets: inherit
     
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 228e64d78..d1bb99d95 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -12,4 +12,5 @@ jobs:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.12"
+      tx_project: "python-newest"
     secrets: inherit
diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index e3725dc36..4da2959f9 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -12,4 +12,5 @@ jobs:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.8"
+      tx_project: "python-38"
     secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 458459371..3d6e5da9a 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -12,5 +12,6 @@ jobs:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.9"
+      tx_project: "python-39"
     secrets: inherit
     
\ No newline at end of file
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index a5a126e20..3d2741421 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -6,6 +6,9 @@ on:
       version:
         required: true
         type: string
+      tx_project:
+        required: true
+        type: string
     secrets:
       TRANSIFEX_APIKEY:
         required: true
@@ -37,5 +40,10 @@ jobs:
           TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
       - name: build
         run: .github/scripts/build.sh
+      - name: stat
+        run: python .github/scripts/tx_stat.py > ./docs/.stat.json
+        env:
+          TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+          TX_PROJECT: ${{ inputs.tx_project }}
       - name: commit
         run: .github/scripts/commit.sh
\ No newline at end of file
diff --git a/README.rst b/README.rst
index 3d791ca4a..5c38d3110 100644
--- a/README.rst
+++ b/README.rst
@@ -15,27 +15,27 @@ Maintained versions:
    * - `3.12 <https://github.com/python/python-docs-zh-cn/tree/3.12>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-312/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-312
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/312
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.12%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-newest/
    * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.11>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/311
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.11%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-311/
    * - `3.10 <https://github.com/python/python-docs-zh-cn/tree/3.10>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-310
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/310
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.10%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-310/
    * - `3.9 <https://github.com/python/python-docs-zh-cn/tree/3.9>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-39/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-39
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/39
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.9%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-39/
    * - `3.8 <https://github.com/python/python-docs-zh-cn/tree/3.8>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-38/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/38
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.8%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-38/
 
 EOL versions:
@@ -49,7 +49,7 @@ EOL versions:
    * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37
-     - .. image:: https://img.shields.io/badge/dynamic/json.svg?label=zh_CN&query=%24.zh_CN&url=http://gce.zhsj.me/python/37
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.7%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-37/
 
 Documentation Contribution Agreement

From adcbce5bf4dd045a767e2b692ac20e628962c16e Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Fri, 4 Aug 2023 18:18:40 +0800
Subject: [PATCH 34/46] optimize build time (#319)

- Add a GitHub action cache layer
- Refill files modified time to use incremental build
- Change from html builder to dummy builder
---
 .github/scripts/build.sh   |  2 +-
 .github/scripts/update.sh  | 16 ++++++++++++++++
 .github/workflows/sync.yml |  9 +++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 2cbcb8e11..4e9b1556c 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -14,4 +14,4 @@ cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
 pip3 install -q -r requirements.txt
-make html SPHINXOPTS="-D language=$LOCALE -D gettext_compact=0 -W --keep-going" 2> >(error)
+sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -W --keep-going -W . build/html 2> >(error)
\ No newline at end of file
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index d2f6f13be..4a15d3095 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,4 +1,20 @@
 #!/bin/bash
 
+cd cpython || exit 1
+
+# Restore git timestamp for enabling build cache
+rev=HEAD
+for f in $(git ls-tree -r -t --full-name --name-only "$rev" Doc) ; do
+    touch -d $(git log --pretty=format:%cI -1 "$rev" -- "$f") "$f";
+done
+
+cd ..
 cd docs || exit 1
+
+# Restore git timestamp for enabling build cache
+rev=HEAD
+for f in $(git ls-tree -r -t --full-name --name-only "$rev") ; do
+    touch -d $(git log --pretty=format:%cI -1 "$rev" -- "$f") "$f";
+done
+
 $(realpath ../tx) pull --languages "$LOCALE" -t --use-git-timestamps --workers 25 --silent
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index 3d2741421..83a51080a 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -38,8 +38,17 @@ jobs:
         run: .github/scripts/update.sh
         env:
           TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
+      - uses: actions/cache/restore@v3
+        with:
+          path: cpython/Doc/build
+          key: cache-${{ inputs.version }}-${{ github.run_id }}
+          restore-keys: cache-${{ inputs.version }}-
       - name: build
         run: .github/scripts/build.sh
+      - uses: actions/cache/save@v3
+        with:
+          path: cpython/Doc/build
+          key: cache-${{ inputs.version }}-${{ github.run_id }}
       - name: stat
         run: python .github/scripts/tx_stat.py > ./docs/.stat.json
         env:

From 12fad780e73dc3fc3e5fcf326ffde2241b4b5561 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Mon, 7 Aug 2023 00:04:41 +0800
Subject: [PATCH 35/46] cache .mo files for build time optimization (#320)

* Cache .mo files

* Avoid clean cache
---
 .github/workflows/sync.yml | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index 83a51080a..3fed1aca7 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -27,11 +27,19 @@ jobs:
           repository: 'python/cpython'
           ref: ${{env.VERSION}}
           path: cpython
+      - uses: actions/cache/restore@v3
+        with:
+          path: |
+            cpython/Doc/build
+            docs
+          key: cache-${{ inputs.version }}-${{ github.run_id }}
+          restore-keys: cache-${{ inputs.version }}-
       - name: Checkout Current Branch
         uses: actions/checkout@v3
         with:
           ref: ${{env.VERSION}}
           path: docs
+          clean: false
       - name: prepare
         run: .github/scripts/prepare.sh
       - name: update
@@ -47,7 +55,9 @@ jobs:
         run: .github/scripts/build.sh
       - uses: actions/cache/save@v3
         with:
-          path: cpython/Doc/build
+          path: |
+            cpython/Doc/build
+            docs
           key: cache-${{ inputs.version }}-${{ github.run_id }}
       - name: stat
         run: python .github/scripts/tx_stat.py > ./docs/.stat.json

From 2797f58ed3f6debf1e35019121889eb85fbc54b4 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Date: Wed, 29 Nov 2023 08:43:49 -0300
Subject: [PATCH 36/46] Error on unset variable in scritps (#339)

* Error on unset variable in build.sh

* Error on unset variable in update.sh
---
 .github/scripts/build.sh  | 3 ++-
 .github/scripts/update.sh | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 4e9b1556c..64b6cc9fc 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -1,6 +1,7 @@
 #!/bin/bash
 
 set -e
+set -u
 set -o pipefail
 
 error() {
@@ -14,4 +15,4 @@ cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
 pip3 install -q -r requirements.txt
-sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -W --keep-going -W . build/html 2> >(error)
\ No newline at end of file
+sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -W --keep-going -W . build/html 2> >(error)
diff --git a/.github/scripts/update.sh b/.github/scripts/update.sh
index 4a15d3095..0f2231d9f 100755
--- a/.github/scripts/update.sh
+++ b/.github/scripts/update.sh
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+set -u
+
 cd cpython || exit 1
 
 # Restore git timestamp for enabling build cache

From 4a41046a506f8af897175cf2077df6c02cac36e7 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Sat, 2 Mar 2024 01:53:49 +0800
Subject: [PATCH 37/46] Update the tx config format

---
 .github/scripts/generate_tx_config.py | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.github/scripts/generate_tx_config.py b/.github/scripts/generate_tx_config.py
index ca3bb39e4..ebcc3b2dd 100755
--- a/.github/scripts/generate_tx_config.py
+++ b/.github/scripts/generate_tx_config.py
@@ -59,6 +59,10 @@ def patch_config(path: str):
     cwd = os.getcwd()
     os.chdir(path)
     config_content = FILTER_PATTERN.sub(name_replacer, config_content)
+    config_content = re.sub(r'replace_edited_strings.*\n','', config_content)
+    config_content = re.sub(r'keep_translations.*\n','', config_content)
+    config_content = re.sub(r'0\ntrans\.zh_CN.*\n','0\n', config_content)
+    config_content = config_content.replace('         =','=')
     os.chdir(cwd)
 
     tx_config_path.write_text(config_content, "utf-8")

From 2507666cf0a92e240ee936aca44182c06269ef95 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Sat, 2 Mar 2024 01:55:34 +0800
Subject: [PATCH 38/46] Update actions deps

---
 .github/workflows/sync.yml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
index 3fed1aca7..0788a37c0 100644
--- a/.github/workflows/sync.yml
+++ b/.github/workflows/sync.yml
@@ -20,14 +20,14 @@ jobs:
       LOCALE: zh_CN
       VERSION: ${{ inputs.version }}
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Checkout CPython
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           repository: 'python/cpython'
           ref: ${{env.VERSION}}
           path: cpython
-      - uses: actions/cache/restore@v3
+      - uses: actions/cache/restore@v4
         with:
           path: |
             cpython/Doc/build
@@ -35,7 +35,7 @@ jobs:
           key: cache-${{ inputs.version }}-${{ github.run_id }}
           restore-keys: cache-${{ inputs.version }}-
       - name: Checkout Current Branch
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           ref: ${{env.VERSION}}
           path: docs
@@ -46,14 +46,14 @@ jobs:
         run: .github/scripts/update.sh
         env:
           TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }}
-      - uses: actions/cache/restore@v3
+      - uses: actions/cache/restore@v4
         with:
           path: cpython/Doc/build
           key: cache-${{ inputs.version }}-${{ github.run_id }}
           restore-keys: cache-${{ inputs.version }}-
       - name: build
         run: .github/scripts/build.sh
-      - uses: actions/cache/save@v3
+      - uses: actions/cache/save@v4
         with:
           path: |
             cpython/Doc/build

From 5de9a3a57dc9b9887122a3c8edc4dd347815f737 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Sat, 11 May 2024 04:43:40 +0000
Subject: [PATCH 39/46] Add version 3.13

---
 .github/workflows/python-310.yml |  2 +-
 .github/workflows/python-311.yml |  2 +-
 .github/workflows/python-312.yml |  4 ++--
 .github/workflows/python-313.yml | 16 ++++++++++++++++
 .github/workflows/python-39.yml  |  2 +-
 README.rst                       |  7 ++++++-
 6 files changed, 27 insertions(+), 6 deletions(-)
 create mode 100644 .github/workflows/python-313.yml

diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 6607518d7..84950aa6a 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "26 * * * *"
+    - cron: "22 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index 9566d743f..2fd788f9f 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "38 * * * *"
+    - cron: "32 * * * *"
 
 jobs:
   sync:
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index d1bb99d95..289d6e577 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -5,12 +5,12 @@ on:
     branches:
       - master
   schedule:
-    - cron: "50 * * * *"
+    - cron: "42 * * * *"
 
 jobs:
   sync:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.12"
-      tx_project: "python-newest"
+      tx_project: "python-312"
     secrets: inherit
diff --git a/.github/workflows/python-313.yml b/.github/workflows/python-313.yml
new file mode 100644
index 000000000..9391d7e23
--- /dev/null
+++ b/.github/workflows/python-313.yml
@@ -0,0 +1,16 @@
+name: python-313
+
+on:
+  push:
+    branches:
+      - master
+  schedule:
+    - cron: "52 * * * *"
+
+jobs:
+  sync:
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.13"
+      tx_project: "python-newest"
+    secrets: inherit
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 3d6e5da9a..4284b55b7 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -5,7 +5,7 @@ on:
     branches:
       - master
   schedule:
-    - cron: "14 * * * *"
+    - cron: "12 * * * *"
 
 jobs:
   sync:
diff --git a/README.rst b/README.rst
index 5c38d3110..c18935a85 100644
--- a/README.rst
+++ b/README.rst
@@ -12,11 +12,16 @@ Maintained versions:
    * - Version
      - Sync status
      - Translation progress
+   * - `3.13 <https://github.com/python/python-docs-zh-cn/tree/3.13>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-313/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-313
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.13%2F.stat.json&query=%24.translation&label=zh-CN
+          :target: https://app.transifex.com/python-doc/python-newest/
    * - `3.12 <https://github.com/python/python-docs-zh-cn/tree/3.12>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-312/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-312
      - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.12%2F.stat.json&query=%24.translation&label=zh-CN
-          :target: https://app.transifex.com/python-doc/python-newest/
+          :target: https://app.transifex.com/python-doc/python-312/
    * - `3.11 <https://github.com/python/python-docs-zh-cn/tree/3.11>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311

From c6514dd2d9f205de8509d4c78c4020ec7d73b2e6 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Wed, 21 Aug 2024 20:34:56 +0800
Subject: [PATCH 40/46] update build command to use fresh environment

Attempt to resolve the environment cache cause building stuck issues.
---
 .github/scripts/build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 64b6cc9fc..46c229e10 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -15,4 +15,4 @@ cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
 pip3 install -q -r requirements.txt
-sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -W --keep-going -W . build/html 2> >(error)
+sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -E --keep-going -W . build/html 2> >(error)

From d9be07d661527b849d9ce617470f3dc9e535946c Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Fri, 11 Oct 2024 18:52:38 +0800
Subject: [PATCH 41/46] Remove python3.8 as it has reached EOL

---
 .github/workflows/python-38.yml |  7 +------
 README.rst                      | 10 +++++-----
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/python-38.yml b/.github/workflows/python-38.yml
index 4da2959f9..9d0bc6daf 100644
--- a/.github/workflows/python-38.yml
+++ b/.github/workflows/python-38.yml
@@ -1,11 +1,6 @@
 name: python-38
 
-on:
-  push:
-    branches:
-      - master
-  schedule:
-    - cron: "2 * * * *"
+on: workflow_dispatch
 
 jobs:
   sync:
diff --git a/README.rst b/README.rst
index c18935a85..a4eb6ee9a 100644
--- a/README.rst
+++ b/README.rst
@@ -37,11 +37,6 @@ Maintained versions:
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-39
      - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.9%2F.stat.json&query=%24.translation&label=zh-CN
           :target: https://app.transifex.com/python-doc/python-39/
-   * - `3.8 <https://github.com/python/python-docs-zh-cn/tree/3.8>`_
-     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-38/badge.svg
-          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
-     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.8%2F.stat.json&query=%24.translation&label=zh-CN
-          :target: https://app.transifex.com/python-doc/python-38/
 
 EOL versions:
 
@@ -51,6 +46,11 @@ EOL versions:
    * - Version
      - Sync status
      - Translation progress
+   * - `3.8 <https://github.com/python/python-docs-zh-cn/tree/3.8>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-38/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.8%2F.stat.json&query=%24.translation&label=zh-CN
+          :target: https://app.transifex.com/python-doc/python-38/
    * - `3.7 <https://github.com/python/python-docs-zh-cn/tree/3.7>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37

From 8e0a0fd29f68b83c8e1d24660a329a382102362b Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Fri, 11 Oct 2024 19:20:11 +0800
Subject: [PATCH 42/46] Fix error: externally-managed-environment in GitHub
 Actions runner

---
 .github/scripts/build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index 46c229e10..e811371e6 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -14,5 +14,5 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
-pip3 install -q -r requirements.txt
+pip3 install -q -r requirements.txt --break-system-packages
 sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -E --keep-going -W . build/html 2> >(error)

From 2928f3045178da9ca2c6a088d8cd5ae319c53444 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Sun, 13 Oct 2024 08:16:11 +0000
Subject: [PATCH 43/46] add workflow dispatch triggers

---
 .github/workflows/python-310.yml | 1 +
 .github/workflows/python-311.yml | 1 +
 .github/workflows/python-312.yml | 1 +
 .github/workflows/python-313.yml | 1 +
 .github/workflows/python-39.yml  | 1 +
 5 files changed, 5 insertions(+)

diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 84950aa6a..27c0ef443 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -1,6 +1,7 @@
 name: python-310
 
 on:
+  workflow_dispatch
   push:
     branches:
       - master
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index 2fd788f9f..166ca8bfc 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -1,6 +1,7 @@
 name: python-311
 
 on:
+  workflow_dispatch
   push:
     branches:
       - master
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 289d6e577..02ee39a5b 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -1,6 +1,7 @@
 name: python-312
 
 on:
+  workflow_dispatch
   push:
     branches:
       - master
diff --git a/.github/workflows/python-313.yml b/.github/workflows/python-313.yml
index 9391d7e23..5c13ff70f 100644
--- a/.github/workflows/python-313.yml
+++ b/.github/workflows/python-313.yml
@@ -1,6 +1,7 @@
 name: python-313
 
 on:
+  workflow_dispatch
   push:
     branches:
       - master
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index 4284b55b7..bec73ca6b 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -1,6 +1,7 @@
 name: python-39
 
 on:
+  workflow_dispatch
   push:
     branches:
       - master

From 294909422abfb96d7be9f4c89e6ad437c0793aa5 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Sun, 13 Oct 2024 08:19:10 +0000
Subject: [PATCH 44/46] add workflow dispatch triggers

---
 .github/workflows/python-310.yml | 2 +-
 .github/workflows/python-311.yml | 2 +-
 .github/workflows/python-312.yml | 2 +-
 .github/workflows/python-313.yml | 2 +-
 .github/workflows/python-39.yml  | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/python-310.yml b/.github/workflows/python-310.yml
index 27c0ef443..35a148f47 100644
--- a/.github/workflows/python-310.yml
+++ b/.github/workflows/python-310.yml
@@ -1,7 +1,7 @@
 name: python-310
 
 on:
-  workflow_dispatch
+  workflow_dispatch:
   push:
     branches:
       - master
diff --git a/.github/workflows/python-311.yml b/.github/workflows/python-311.yml
index 166ca8bfc..4fa85bb77 100644
--- a/.github/workflows/python-311.yml
+++ b/.github/workflows/python-311.yml
@@ -1,7 +1,7 @@
 name: python-311
 
 on:
-  workflow_dispatch
+  workflow_dispatch:
   push:
     branches:
       - master
diff --git a/.github/workflows/python-312.yml b/.github/workflows/python-312.yml
index 02ee39a5b..75cc1d35e 100644
--- a/.github/workflows/python-312.yml
+++ b/.github/workflows/python-312.yml
@@ -1,7 +1,7 @@
 name: python-312
 
 on:
-  workflow_dispatch
+  workflow_dispatch:
   push:
     branches:
       - master
diff --git a/.github/workflows/python-313.yml b/.github/workflows/python-313.yml
index 5c13ff70f..657d53443 100644
--- a/.github/workflows/python-313.yml
+++ b/.github/workflows/python-313.yml
@@ -1,7 +1,7 @@
 name: python-313
 
 on:
-  workflow_dispatch
+  workflow_dispatch:
   push:
     branches:
       - master
diff --git a/.github/workflows/python-39.yml b/.github/workflows/python-39.yml
index bec73ca6b..39305f585 100644
--- a/.github/workflows/python-39.yml
+++ b/.github/workflows/python-39.yml
@@ -1,7 +1,7 @@
 name: python-39
 
 on:
-  workflow_dispatch
+  workflow_dispatch:
   push:
     branches:
       - master

From ac84487938688e71d42f5b64b431d866a453ebe4 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Tue, 26 Nov 2024 21:18:41 +0800
Subject: [PATCH 45/46] remove the break-system-packages option to fix the
 build

---
 .github/scripts/build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
index e811371e6..46c229e10 100755
--- a/.github/scripts/build.sh
+++ b/.github/scripts/build.sh
@@ -14,5 +14,5 @@ error() {
 cd cpython/Doc || exit 1
 mkdir -p locales/"$LOCALE"/
 ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES
-pip3 install -q -r requirements.txt --break-system-packages
+pip3 install -q -r requirements.txt
 sphinx-build -b dummy -d build/doctrees  -j auto -D language=$LOCALE -D gettext_compact=0 -E --keep-going -W . build/html 2> >(error)

From d0a223a5bc1cd5d896d223478211c45ec79352b5 Mon Sep 17 00:00:00 2001
From: A <5249513+Dumeng@users.noreply.github.com>
Date: Sat, 10 May 2025 14:03:34 +0800
Subject: [PATCH 46/46] Add version 3.14

---
 .github/workflows/python-313.yml |  2 +-
 .github/workflows/python-314.yml | 17 +++++++++++++++++
 README.rst                       |  7 ++++++-
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 .github/workflows/python-314.yml

diff --git a/.github/workflows/python-313.yml b/.github/workflows/python-313.yml
index 657d53443..5cf9c8340 100644
--- a/.github/workflows/python-313.yml
+++ b/.github/workflows/python-313.yml
@@ -13,5 +13,5 @@ jobs:
     uses: ./.github/workflows/sync.yml
     with:
       version: "3.13"
-      tx_project: "python-newest"
+      tx_project: "python-313"
     secrets: inherit
diff --git a/.github/workflows/python-314.yml b/.github/workflows/python-314.yml
new file mode 100644
index 000000000..9118a8ce8
--- /dev/null
+++ b/.github/workflows/python-314.yml
@@ -0,0 +1,17 @@
+name: python-314
+
+on:
+  workflow_dispatch:
+  push:
+    branches:
+      - master
+  schedule:
+    - cron: "2 * * * *"
+
+jobs:
+  sync:
+    uses: ./.github/workflows/sync.yml
+    with:
+      version: "3.14"
+      tx_project: "python-newest"
+    secrets: inherit
diff --git a/README.rst b/README.rst
index a4eb6ee9a..f17ac8294 100644
--- a/README.rst
+++ b/README.rst
@@ -12,11 +12,16 @@ Maintained versions:
    * - Version
      - Sync status
      - Translation progress
+   * - `3.14 <https://github.com/python/python-docs-zh-cn/tree/3.14>`_
+     - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-314/badge.svg
+          :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-314
+     - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.14%2F.stat.json&query=%24.translation&label=zh-CN
+          :target: https://app.transifex.com/python-doc/python-newest/
    * - `3.13 <https://github.com/python/python-docs-zh-cn/tree/3.13>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-313/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-313
      - .. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpython%2Fpython-docs-zh-cn%2F3.13%2F.stat.json&query=%24.translation&label=zh-CN
-          :target: https://app.transifex.com/python-doc/python-newest/
+          :target: https://app.transifex.com/python-doc/python-313/
    * - `3.12 <https://github.com/python/python-docs-zh-cn/tree/3.12>`_
      - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-312/badge.svg
           :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-312
