├── .github ├── ISSUE_TEMPLATE │ └── translation.yml ├── scripts │ ├── build.sh │ ├── commit.sh │ ├── generate_tx_config.py │ ├── prepare.sh │ ├── tx_stat.py │ └── update.sh └── workflows │ ├── python-310.yml │ ├── python-311.yml │ ├── python-312.yml │ ├── python-313.yml │ ├── python-314.yml │ ├── python-37.yml │ ├── python-38.yml │ ├── python-39.yml │ └── sync.yml ├── README.rst └── TRANSLATORS /.github/ISSUE_TEMPLATE/translation.yml: -------------------------------------------------------------------------------- 1 | name: Translation Issue Report 2 | description: File a translation issue report 3 | title: "[Typo]: " 4 | labels: ["translation"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this translation issue report! 10 | - type: input 11 | id: version 12 | attributes: 13 | label: Python Version 14 | description: Which version of the Python documentation covers this issue? 15 | placeholder: ex. 3.12 16 | validations: 17 | required: true 18 | - type: input 19 | id: url 20 | attributes: 21 | label: Docs Page 22 | description: What is the url of the page containing the issue? 23 | placeholder: https://docs.python.org/3/about.html 24 | validations: 25 | required: true 26 | - type: textarea 27 | id: zh-original 28 | attributes: 29 | label: Original Translation 30 | description: Which translated paragraph in Chinese contains the issue? 31 | validations: 32 | required: true 33 | - type: textarea 34 | id: en-original 35 | attributes: 36 | label: Original Docs Paragraph 37 | description: Which original paragraph in English contains the issue? 38 | validations: 39 | required: false 40 | - type: textarea 41 | id: zh-suggested 42 | attributes: 43 | label: Suggested Fix 44 | description: What is your suggested fix? 45 | validations: 46 | required: true -------------------------------------------------------------------------------- /.github/scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | error() { 8 | while read -r line; do 9 | echo 10 | echo ::error::"$line" 11 | done 12 | } 13 | 14 | cd cpython/Doc || exit 1 15 | mkdir -p locales/"$LOCALE"/ 16 | ln -sfn "$(realpath ../../docs)" locales/"$LOCALE"/LC_MESSAGES 17 | pip3 install -q -r requirements.txt 18 | sphinx-build -b dummy -d build/doctrees -j auto -D language=$LOCALE -D gettext_compact=0 -E --keep-going -W . build/html 2> >(error) 19 | -------------------------------------------------------------------------------- /.github/scripts/commit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | cd docs || exit 1 6 | git config user.email "github-actions[bot]@users.noreply.github.com" 7 | git config user.name "github-actions[bot]" 8 | if ! git status -s|grep '\.po'; then 9 | echo "Nothing to commit" 10 | exit 0 11 | fi 12 | git add . 13 | git commit -m '[po] auto sync' 14 | git push 15 | -------------------------------------------------------------------------------- /.github/scripts/generate_tx_config.py: -------------------------------------------------------------------------------- 1 | """Please note that this script requires a Transifex API token to run.""" 2 | import glob 3 | import subprocess 4 | from functools import partial 5 | from pathlib import Path 6 | import re 7 | import os 8 | 9 | run = partial(subprocess.run, check=True) 10 | 11 | 12 | def init_project(): 13 | run(["tx", "init"]) 14 | 15 | 16 | def add_files(project_name: str): 17 | run( 18 | [ 19 | "tx", 20 | "add", 21 | "remote", 22 | "--file-filter", 23 | "trans//.", 24 | f"https://www.transifex.com/python-doc/{project_name}/dashboard/", 25 | ] 26 | ) 27 | 28 | 29 | FILTER_PATTERN = re.compile( 30 | r"^(?Pfile_filter( *)=( *))(?P.+)$", re.MULTILINE 31 | ) 32 | 33 | 34 | def name_replacer(match: re.Match[str]): 35 | prefix, resource = match.group("prefix", "resource") 36 | override_prefix = prefix.replace("file_filter", "trans.zh_CN") 37 | pattern = ( 38 | resource.replace("trans//", "") 39 | .replace("glossary_", "glossary") 40 | .replace("--", "/") 41 | .replace("_", "?") 42 | ) 43 | matches = list(glob.glob(pattern.replace(".po", ".rst"))) 44 | if not matches: 45 | print("missing", pattern) 46 | return f"{prefix}{resource}\n{override_prefix}{pattern.replace('?', '_')}" 47 | elif len(matches) == 1: 48 | filename = matches[0].replace(".rst", ".po").replace("\\", "/") 49 | else: 50 | raise ValueError("multi match", resource, pattern, matches) 51 | return f"{prefix}{resource}\n{override_prefix}{filename}" 52 | 53 | 54 | def patch_config(path: str): 55 | tx_config_path = Path(".tx", "config") 56 | 57 | config_content = tx_config_path.read_text("utf-8") 58 | 59 | cwd = os.getcwd() 60 | os.chdir(path) 61 | config_content = FILTER_PATTERN.sub(name_replacer, config_content) 62 | config_content = re.sub(r'replace_edited_strings.*\n','', config_content) 63 | config_content = re.sub(r'keep_translations.*\n','', config_content) 64 | config_content = re.sub(r'0\ntrans\.zh_CN.*\n','0\n', config_content) 65 | config_content = config_content.replace(' =','=') 66 | os.chdir(cwd) 67 | 68 | tx_config_path.write_text(config_content, "utf-8") 69 | 70 | 71 | if __name__ == "__main__": 72 | from argparse import ArgumentParser 73 | 74 | parser = ArgumentParser() 75 | 76 | parser.add_argument("--token", default="") 77 | parser.add_argument("--project-name", required=True) 78 | parser.add_argument("--doc-path", required=True) 79 | 80 | params = parser.parse_args() 81 | 82 | if params.token: 83 | os.environ["TX_TOKEN"] = params.token 84 | 85 | init_project() 86 | add_files(params.project_name) 87 | patch_config(params.doc_path) 88 | -------------------------------------------------------------------------------- /.github/scripts/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash -------------------------------------------------------------------------------- /.github/scripts/tx_stat.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import urllib.request 4 | from datetime import datetime 5 | 6 | key = os.environ.get('TX_TOKEN') 7 | project = os.environ.get('TX_PROJECT') 8 | 9 | url = "https://rest.api.transifex.com/resource_language_stats?filter[project]=o%3Apython-doc%3Ap%3A{}&filter[language]=l%3Azh_CN".format(project) 10 | 11 | headers = { 12 | "accept": "application/vnd.api+json", 13 | "authorization": "Bearer " + key 14 | } 15 | 16 | total = 0 17 | translated = 0 18 | 19 | while(url): 20 | request = urllib.request.Request(url=url,headers=headers) 21 | 22 | with urllib.request.urlopen(request) as response: 23 | data = json.loads(response.read().decode("utf-8")) 24 | url = data['links'].get('next') 25 | for resourse in data['data']: 26 | translated = translated + resourse['attributes']['translated_strings'] 27 | total = total + resourse['attributes']['total_strings'] 28 | 29 | p = '{:.2%}'.format(translated/total) 30 | print(json.dumps({ 31 | 'translation':p, 32 | 'updated_at':datetime.utcnow().isoformat(timespec='seconds') + 'Z', 33 | })) -------------------------------------------------------------------------------- /.github/scripts/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -u 4 | 5 | cd cpython || exit 1 6 | 7 | # Restore git timestamp for enabling build cache 8 | rev=HEAD 9 | for f in $(git ls-tree -r -t --full-name --name-only "$rev" Doc) ; do 10 | touch -d $(git log --pretty=format:%cI -1 "$rev" -- "$f") "$f"; 11 | done 12 | 13 | cd .. 14 | cd docs || exit 1 15 | 16 | # Restore git timestamp for enabling build cache 17 | rev=HEAD 18 | for f in $(git ls-tree -r -t --full-name --name-only "$rev") ; do 19 | touch -d $(git log --pretty=format:%cI -1 "$rev" -- "$f") "$f"; 20 | done 21 | 22 | $(realpath ../tx) pull --languages "$LOCALE" -t --use-git-timestamps --workers 25 --silent 23 | -------------------------------------------------------------------------------- /.github/workflows/python-310.yml: -------------------------------------------------------------------------------- 1 | name: python-310 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "22 * * * *" 10 | 11 | jobs: 12 | sync: 13 | uses: ./.github/workflows/sync.yml 14 | with: 15 | version: "3.10" 16 | tx_project: "python-310" 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /.github/workflows/python-311.yml: -------------------------------------------------------------------------------- 1 | name: python-311 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "32 * * * *" 10 | 11 | jobs: 12 | sync: 13 | uses: ./.github/workflows/sync.yml 14 | with: 15 | version: "3.11" 16 | tx_project: "python-311" 17 | secrets: inherit 18 | 19 | -------------------------------------------------------------------------------- /.github/workflows/python-312.yml: -------------------------------------------------------------------------------- 1 | name: python-312 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "42 * * * *" 10 | 11 | jobs: 12 | sync: 13 | uses: ./.github/workflows/sync.yml 14 | with: 15 | version: "3.12" 16 | tx_project: "python-312" 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /.github/workflows/python-313.yml: -------------------------------------------------------------------------------- 1 | name: python-313 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "52 * * * *" 10 | 11 | jobs: 12 | sync: 13 | uses: ./.github/workflows/sync.yml 14 | with: 15 | version: "3.13" 16 | tx_project: "python-313" 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /.github/workflows/python-314.yml: -------------------------------------------------------------------------------- 1 | name: python-314 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "2 * * * *" 10 | 11 | jobs: 12 | sync: 13 | uses: ./.github/workflows/sync.yml 14 | with: 15 | version: "3.14" 16 | tx_project: "python-newest" 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /.github/workflows/python-37.yml: -------------------------------------------------------------------------------- 1 | name: python-37 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | sync: 7 | uses: ./.github/workflows/sync.yml 8 | with: 9 | version: "3.7" 10 | secrets: inherit -------------------------------------------------------------------------------- /.github/workflows/python-38.yml: -------------------------------------------------------------------------------- 1 | name: python-38 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | sync: 7 | uses: ./.github/workflows/sync.yml 8 | with: 9 | version: "3.8" 10 | tx_project: "python-38" 11 | secrets: inherit -------------------------------------------------------------------------------- /.github/workflows/python-39.yml: -------------------------------------------------------------------------------- 1 | name: python-39 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "12 * * * *" 10 | 11 | jobs: 12 | sync: 13 | uses: ./.github/workflows/sync.yml 14 | with: 15 | version: "3.9" 16 | tx_project: "python-39" 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: Reusable workflow example 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | version: 7 | required: true 8 | type: string 9 | tx_project: 10 | required: true 11 | type: string 12 | secrets: 13 | TRANSIFEX_APIKEY: 14 | required: true 15 | 16 | jobs: 17 | sync: 18 | runs-on: ubuntu-latest 19 | env: 20 | LOCALE: zh_CN 21 | VERSION: ${{ inputs.version }} 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Checkout CPython 25 | uses: actions/checkout@v4 26 | with: 27 | repository: 'python/cpython' 28 | ref: ${{env.VERSION}} 29 | path: cpython 30 | - uses: actions/cache/restore@v4 31 | with: 32 | path: | 33 | cpython/Doc/build 34 | docs 35 | key: cache-${{ inputs.version }}-${{ github.run_id }} 36 | restore-keys: cache-${{ inputs.version }}- 37 | - name: Checkout Current Branch 38 | uses: actions/checkout@v4 39 | with: 40 | ref: ${{env.VERSION}} 41 | path: docs 42 | clean: false 43 | - name: prepare 44 | run: .github/scripts/prepare.sh 45 | - name: update 46 | run: .github/scripts/update.sh 47 | env: 48 | TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }} 49 | - uses: actions/cache/restore@v4 50 | with: 51 | path: cpython/Doc/build 52 | key: cache-${{ inputs.version }}-${{ github.run_id }} 53 | restore-keys: cache-${{ inputs.version }}- 54 | - name: build 55 | run: .github/scripts/build.sh 56 | - uses: actions/cache/save@v4 57 | with: 58 | path: | 59 | cpython/Doc/build 60 | docs 61 | key: cache-${{ inputs.version }}-${{ github.run_id }} 62 | - name: stat 63 | run: python .github/scripts/tx_stat.py > ./docs/.stat.json 64 | env: 65 | TX_TOKEN: ${{ secrets.TRANSIFEX_APIKEY }} 66 | TX_PROJECT: ${{ inputs.tx_project }} 67 | - name: commit 68 | run: .github/scripts/commit.sh -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | zh_CN Translation of the Python Documentation 2 | ============================================= 3 | 4 | All translations are done on transifex. 5 | https://www.transifex.com/python-doc/public/ 6 | 7 | Maintained versions: 8 | 9 | .. list-table:: 10 | :header-rows: 1 11 | 12 | * - Version 13 | - Sync status 14 | - Translation progress 15 | * - `3.14 `_ 16 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-314/badge.svg 17 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-314 18 | - .. 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 19 | :target: https://app.transifex.com/python-doc/python-newest/ 20 | * - `3.13 `_ 21 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-313/badge.svg 22 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-313 23 | - .. 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 24 | :target: https://app.transifex.com/python-doc/python-313/ 25 | * - `3.12 `_ 26 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-312/badge.svg 27 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-312 28 | - .. 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 29 | :target: https://app.transifex.com/python-doc/python-312/ 30 | * - `3.11 `_ 31 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-311/badge.svg 32 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-311 33 | - .. 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 34 | :target: https://app.transifex.com/python-doc/python-311/ 35 | * - `3.10 `_ 36 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-310/badge.svg 37 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-310 38 | - .. 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 39 | :target: https://app.transifex.com/python-doc/python-310/ 40 | * - `3.9 `_ 41 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-39/badge.svg 42 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-39 43 | - .. 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 44 | :target: https://app.transifex.com/python-doc/python-39/ 45 | 46 | EOL versions: 47 | 48 | .. list-table:: 49 | :header-rows: 1 50 | 51 | * - Version 52 | - Sync status 53 | - Translation progress 54 | * - `3.8 `_ 55 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-38/badge.svg 56 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-38 57 | - .. 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 58 | :target: https://app.transifex.com/python-doc/python-38/ 59 | * - `3.7 `_ 60 | - .. image:: https://github.com/python/python-docs-zh-cn/workflows/python-37/badge.svg 61 | :target: https://github.com/python/python-docs-zh-cn/actions?workflow=python-37 62 | - .. 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 63 | :target: https://app.transifex.com/python-doc/python-37/ 64 | 65 | Documentation Contribution Agreement 66 | ------------------------------------ 67 | 68 | NOTE REGARDING THE LICENSE FOR TRANSLATIONS: Python's documentation is 69 | maintained using a global network of volunteers. By posting this 70 | project on Transifex, GitHub, and other public places, and inviting 71 | you to participate, we are proposing an agreement that you will 72 | provide your improvements to Python's documentation or the translation 73 | of Python's documentation for the PSF's use under the CC0 license 74 | (available at 75 | https://creativecommons.org/publicdomain/zero/1.0/legalcode). In 76 | return, you may publicly claim credit for the portion of the 77 | translation you contributed and if your translation is accepted by the 78 | PSF, you may (but are not required to) submit a patch including an 79 | appropriate annotation in the Misc/ACKS or TRANSLATORS file. Although 80 | nothing in this Documentation Contribution Agreement obligates the PSF 81 | to incorporate your textual contribution, your participation in the 82 | Python community is welcomed and appreciated. 83 | 84 | You signify acceptance of this agreement by submitting your work to 85 | the PSF for inclusion in the documentation. 86 | 87 | Contributing to the Translation 88 | ------------------------------- 89 | 90 | Join the Chinese (China) team on transifex to get start. 91 | 92 | You're recommended to read 93 | `大陆简中自由软件本地化工作指南:Free Software Localization Guide for Chinese (China)`__ first. 94 | 95 | __ http://mirrors.ustc.edu.cn/anthon/aosc-l10n/zh_CN_l10n.pdf 96 | -------------------------------------------------------------------------------- /TRANSLATORS: -------------------------------------------------------------------------------- 1 | # The latest translators list is in each po file. 2 | # Following are the names that translators set at Transifex. 3 | # Generated by: 4 | # grep -ohP '(?<=^# )(.+)(?=, \d+$)' -r .|sed 's| <.*>||g' | sort -u 5 | 6 | 3vilive D 7 | 443 8 | ailin zhang 9 | allenjuly7 10 | Aloxaf 11 | ausaki 12 | banxi 13 | cdarlint 14 | chen_chao 15 | Chengeng Ning 16 | ChenYuan 17 | chordy 18 | cissoid 19 | CommonZ 20 | c pan 21 | Danny Vi 22 | dgy18787 23 | dhcn 24 | dykai 25 | emrich 26 | eric R 27 | Fei Yin 28 | focusheart 29 | Fred 30 | Freesand Leo 31 | gashero liu 32 | hanfeng 33 | Hanxi Fu 34 | Harry Z 35 | Henry Zhu 36 | isaced 37 | isombyt 38 | Jack Wu 39 | Jann Li 40 | Jarry Shaw 41 | Jerry Chen 42 | Josh Ouyang 43 | jsgang 44 | Junkai Shao 45 | Kaizhao Zhang 46 | Kder 47 | keelii 48 | kevin wong 49 | Larry wang 50 | Larry Wang 51 | Madlee 52 | Meng Du 53 | Menghua Xiao 54 | Ming Jia 55 | musan cheng 56 | MuSheng Chen 57 | Nasy 58 | Natasha Li 59 | Pandaaaa906 60 | Pan Felix 61 | Pikachu 62 | QR Wang 63 | RSNOW 64 | ryohei 65 | Saiyang Gou 66 | sgqy 67 | Shengjing Zhu 68 | shiyu Peng 69 | Siyuan Xu 70 | SKY H. 71 | SonnyZhang 72 | Steve Ni 73 | sunsol s 74 | Thomas ZHANG 75 | tom smith 76 | Tony Tong 77 | Trim21 78 | TX Lee 79 | walkinrain 80 | Wang Saul 81 | wenhui 82 | wevsty 83 | Woko 84 | Woostundy 85 | Wu Pipi 86 | wwj402 87 | ww song 88 | xiao xu 89 | Yan Gao 90 | Yinuo Huang 91 | Yiyi Python 92 | YIZHU LIN 93 | yuan chen 94 | yuxin wang 95 | zc Jin 96 | Zephyr Waitzman 97 | Zhe He 98 | Ziqi Wang 99 | zkonge 100 | Zombie110year 101 | 付裕如 102 | 兴然 刘 103 | 刘士 104 | 叶浚安 105 | 启迪 吴 106 | 吴彬 107 | 开 方 108 | 张俊(fighting) 109 | 志正 韩 110 | 操旭 111 | 林行众 112 | 梁启凡 113 | 欢 王 114 | 殷平乐 115 | 汇民 王 116 | 演奏王 117 | 非法操作 118 | 马强 119 | --------------------------------------------------------------------------------