| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,56 @@ | |||
| 1 | + --- | ||
| 2 | + name: اشکال در واژهیاب | ||
| 3 | + about: گزارش مشکل یا رفتار نادرست در ابزار واژهیاب | ||
| 4 | + title: "[واژهیاب] " | ||
| 5 | + labels: bug | ||
| 6 | + assignees: '' | ||
| 7 | + --- | ||
| 8 | + | ||
| 9 | + ## توضیح مشکل | ||
| 10 | + | ||
| 11 | + <!-- | ||
| 12 | + لطفاً مشکل مشاهدهشده را بهطور کامل توضیح دهید. | ||
| 13 | + اگر ممکن است، مراحل لازم برای بازتولید مشکل را نیز بنویسید. | ||
| 14 | + --> | ||
| 15 | + | ||
| 16 | + ## مراحل بازتولید | ||
| 17 | + | ||
| 18 | + <!-- | ||
| 19 | + مراحل انجامشده برای مشاهدهی مشکل را بهترتیب وارد کنید. | ||
| 20 | + برای مثال: | ||
| 21 | + 1. به صفحهی واژهیاب بروید. | ||
| 22 | + 2. واژهی خاصی را جستوجو کنید. | ||
| 23 | + 3. نتیجهی نادرست یا خطا را مشاهده کنید. | ||
| 24 | + --> | ||
| 25 | + | ||
| 26 | + ## نتیجهی مورد انتظار | ||
| 27 | + | ||
| 28 | + <!-- | ||
| 29 | + توضیح دهید انتظار داشتید واژهیاب چه رفتاری داشته باشد. | ||
| 30 | + --> | ||
| 31 | + | ||
| 32 | + ## نتیجهی مشاهدهشده | ||
| 33 | + | ||
| 34 | + <!-- | ||
| 35 | + توضیح دهید واژهیاب در عمل چه رفتاری نشان داد. | ||
| 36 | + --> | ||
| 37 | + | ||
| 38 | + ## مرورگر و محیط مورد استفاده | ||
| 39 | + | ||
| 40 | + <!-- | ||
| 41 | + لطفاً اطلاعات مربوط به محیط اجرا را وارد کنید. | ||
| 42 | + برای مثال: | ||
| 43 | + - Firefox نسخهی x | ||
| 44 | + - Chrome نسخهی y | ||
| 45 | + - سیستمعامل (در صورت ارتباط) | ||
| 46 | + --> | ||
| 47 | + | ||
| 48 | + ## اسکرینشات یا اطلاعات تکمیلی | ||
| 49 | + | ||
| 50 | + <!-- | ||
| 51 | + در صورت امکان، تصویر، پیام خطا، یا هر اطلاعات دیگری که به بررسی مشکل کمک میکند را درج کنید. | ||
| 52 | + --> | ||
| 53 | + | ||
| 54 | + ## آییننامهی رفتاری | ||
| 55 | + | ||
| 56 | + - [ ] میپذیرم که از [آییننامهی رفتاری PSF](https://www.python.org/psf/conduct/) پیروی کنم. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,7 +19,7 @@ | |||
| 19 | 19 | - [ ] `msgfmt --check` روی پروندههای تغییر یافته با موفقیت اجرا شده است | |
| 20 | 20 | - [ ] `python3 scripts/check_markup.py` روی پروندههای تغییر یافته اجرا شده است | |
| 21 | 21 | - [ ] نشانهگذاریهای Sphinx (`:class:`، `:func:`، کد درونخطی) و جایگذارها (`%s`، `{name}`) دستنخورده ماندهاند | |
| 22 | - - [ ] ترجمهها با [واژهنامه (GLOSSARY.md)](https://github.com/python/python-docs-fa/blob/3.14/GLOSSARY.md) هماهنگ است | ||
| 22 | + - [ ] ترجمهها با [واژهنامه](http://python.github.io/python-docs-fa/glossary-searcher) هماهنگ است | ||
| 23 | 23 | - [ ] رشتههای `fuzzy` بررسی و در صورت لزوم بازنویسی شدهاند | |
| 24 | 24 | - [ ] پرونده [CONTRIBUTING.md](https://github.com/python/python-docs-fa/blob/3.14/CONTRIBUTING.md) با دقت خوانده شده است. | |
| 25 | 25 | <!-- یادآوری: بررسیهای خودکار (sphinx-lint ،msgfmt ،check_markup و ساخت کامل) در GitHub Actions روی پولریکوئست اجرا میشوند. --> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,10 +2,11 @@ name: Build and Deploy to GitHub Pages | |||
| 2 | 2 | ||
| 3 | 3 | on: | |
| 4 | 4 | schedule: | |
| 5 | - - cron: '0 2 * * *' | ||
| 5 | + - cron: '0 2 * * *' | ||
| 6 | 6 | push: | |
| 7 | 7 | branches: | |
| 8 | 8 | - 3.14 | |
| 9 | + paths-ignore: [] | ||
| 9 | 10 | workflow_dispatch: | |
| 10 | 11 | ||
| 11 | 12 | permissions: | |
@@ -26,21 +27,17 @@ jobs: | |||
| 26 | 27 | with: | |
| 27 | 28 | repository: python/cpython | |
| 28 | 29 | ref: v3.14.7 | |
| 29 | - | ||
| 30 | + | ||
| 30 | 31 | - name: Set up Python | |
| 31 | 32 | uses: actions/setup-python@v4 | |
| 32 | 33 | with: | |
| 33 | 34 | python-version: '3.12' | |
| 34 | - | ||
| 35 | + | ||
| 35 | 36 | - name: Setup virtual environment | |
| 36 | 37 | run: make venv | |
| 37 | 38 | working-directory: ./Doc | |
| 38 | 39 | ||
| 39 | 40 | - name: Pin Sphinx to 9.1.0 | |
| 40 | - # make venv may resolve an older Sphinx via requirements.txt; pin | ||
| 41 | - # explicitly so we get the reordered-ref / translated-display-text | ||
| 42 | - # i18n fixes (sphinx-doc/sphinx#14144). Bump this once #14162 lands | ||
| 43 | - # upstream and re-check whether the suppression below is still needed. | ||
| 44 | 41 | run: ./venv/bin/pip install "sphinx==9.1.0" | |
| 45 | 42 | working-directory: ./Doc | |
| 46 | 43 | ||
@@ -56,14 +53,39 @@ jobs: | |||
| 56 | 53 | ||
| 57 | 54 | - name: Setup problem matcher | |
| 58 | 55 | uses: sphinx-doc/github-problem-matcher@v1.1 | |
| 59 | - | ||
| 56 | + | ||
| 60 | 57 | - name: Build documentation | |
| 61 | 58 | run: make -e SPHINXERRORHANDLING="" SPHINXOPTS="--color -D language='fa' -D gettext_allow_fuzzy_translations=1 -D html_theme_options.is_rtl=true -D suppress_warnings=i18n.inconsistent_references --keep-going" html | |
| 62 | 59 | working-directory: ./Doc | |
| 63 | - | ||
| 60 | + | ||
| 61 | + # ---- Glossary searcher build starts here ---- | ||
| 62 | + - name: Install glossary build dependencies | ||
| 63 | + run: pip install -r glossary-searcher/scripts/requirements.txt | ||
| 64 | + working-directory: Doc/locales/fa/LC_MESSAGES | ||
| 65 | + | ||
| 66 | + - name: Build glossary corpus & glossary data | ||
| 67 | + run: | | ||
| 68 | + python glossary-searcher/scripts/build_corpus.py \ | ||
| 69 | + --repo-dir . \ | ||
| 70 | + --glossary-tsv glossary.tsv \ | ||
| 71 | + --out-dir glossary-searcher/data | ||
| 72 | + working-directory: Doc/locales/fa/LC_MESSAGES | ||
| 73 | + | ||
| 74 | + - name: Build glossary site | ||
| 75 | + run: | | ||
| 76 | + python glossary-searcher/scripts/build_site.py \ | ||
| 77 | + --site-dir glossary-searcher/site \ | ||
| 78 | + --data-dir glossary-searcher/data \ | ||
| 79 | + --out-dir glossary-searcher/dist | ||
| 80 | + working-directory: Doc/locales/fa/LC_MESSAGES | ||
| 81 | + | ||
| 82 | + - name: Merge glossary site into docs build | ||
| 83 | + run: cp -r Doc/locales/fa/LC_MESSAGES/glossary-searcher/dist Doc/build/html/glossary-searcher | ||
| 84 | + # ---- Glossary searcher build ends here ---- | ||
| 85 | + | ||
| 64 | 86 | - name: Setup Pages | |
| 65 | 87 | uses: actions/configure-pages@v4 | |
| 66 | - | ||
| 88 | + | ||
| 67 | 89 | - name: Upload artifact | |
| 68 | 90 | uses: actions/upload-pages-artifact@v3 | |
| 69 | 91 | with: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,8 @@ | |||
| 1 | 1 | # راهنمای مشارکت در ترجمهی مستندات پایتون | |
| 2 | 2 | ||
| 3 | - این راهنما مکمل [README.md](README.md) است و جزئیات فنی و فرایندهای پروژه را توضیح میدهد. پیش از شروع، حتماً [README.md](README.md) را بخوانید. | ||
| 3 | + این راهنما مکمل [README.md](README.md) است و جزئیات فنی و فرایندهای مربوط به مشارکت در پروژه را توضیح میدهد. پیش از شروع مشارکت، حتماً [README.md](README.md) را مطالعه کنید. | ||
| 4 | + | ||
| 5 | + همچنین واژهنامهی پروژه بهصورت یک وبگاه از طریق [این پیوند](http://python.github.io/python-docs-fa/glossary-searcher) در دسترس است. با جستوجوی واژهی انگلیسی مورد نظر، میتوانید در صورت وجود آن در واژهنامه، معادل فارسی ثبتشدهی آن را بههمراه نمونههای کاربرد آن در پیکرهی مستندات مشاهده کنید. | ||
| 4 | 6 | ||
| 5 | 7 | تمام مشارکتکنندگان موظفاند از [آییننامهی رفتاری PSF](https://www.python.org/psf/conduct/) پیروی کنند. این تعهد در همهی ایشیوها و پولریکوئستها بهصورت یک چکباکس ثبت میشود. | |
| 6 | 8 | ||
@@ -38,10 +40,11 @@ | |||
| 38 | 40 | ||
| 39 | 41 | ## انواع ایشیو | |
| 40 | 42 | ||
| 41 | - پیش از باز کردن ایشیوی جدید، قالب مناسب را از [صفحهی ایشیوهای پروژه](https://github.com/python/python-docs-fa/issues/new/choose) انتخاب کنید. دو قالب موجود است: | ||
| 43 | + پیش از باز کردن ایشیوی جدید، قالب مناسب را از [صفحهی ایشیوهای پروژه](https://github.com/python/python-docs-fa/issues/new/choose) انتخاب کنید. سه قالب موجود است: | ||
| 42 | 44 | ||
| 43 | 45 | - **اشکال در ترجمه:** برای گزارش ترجمهی نادرست یا مشکلدار در یک صفحهی منتشرشده. `msgid`، `msgstr` فعلی، و ترجمهی پیشنهادی خود را در قالب وارد کنید. | |
| 44 | 46 | - **پیشنهاد تغییرات در ترجمه:** برای پیشنهاد تغییر در یک واژه یا شیوهی نگارشِ ثابتشده (نه یک اشکال ساده). فرایند بررسی این نوع پیشنهاد در بخش [«پیشنهاد تغییر در واژه یا شیوهی نگارش»](#پیشنهاد-تغییر-در-واژه-یا-شیوهی-نگارش) توضیح داده شده است. | |
| 47 | + - **گزارش اشکال در واژهیاب:** برای گزارش اشکالات در واژهیاب، از این قالب استفاده کنید. | ||
| 45 | 48 | ||
| 46 | 49 | ## فرایند ترجمه | |
| 47 | 50 | ||
@@ -52,7 +55,7 @@ | |||
| 52 | 55 | ||
| 53 | 56 | 3. متن `msgid` را ترجمه کنید و در `msgstr` وارد کنید. | |
| 54 | 57 | ||
| 55 | - 4. برای پیدا کردن ترجمهی مناسب برای کلمات و عبارات تخصصی، از [این](https://sepehr-rs.github.io/python-docs-fa-glossary/) پیوند به واژهیاب پایتون رفته و واژه/عبارت موردنظر خود را جستجو کنید. | ||
| 58 | + 4. برای پیدا کردن ترجمهی مناسب برای کلمات و عبارات تخصصی، از [این پیوند](http://python.github.io/python-docs-fa/glossary-searcher) به واژهیاب پایتون رفته و واژه/عبارت موردنظر خود را جستجو کنید. | ||
| 56 | 59 | ||
| 57 | 60 | 5. **نشانهگذاریهای Sphinx** مثل `` :class:`int` ``، `` :func:`repr` ``، `` :ref:`...` ``، `` ``code`` `` و **جایگذارها** مثل `%s` یا `{name}` را دقیقاً بدون تغییر نگه دارید؛ فقط متن اطراف آنها ترجمه میشود. در `` :term:`target` ``، اگر عبارت داخل بکتیک با شناسهی واژهنامه یکی است، میتوانید آن را به شکل `` :term:`ترجمه <target>` `` بنویسید تا هم متن ترجمهشده نمایش داده شود و هم لینک درست کار کند؛ در این حالت فقط بخش نمایشی (پیش از `<`) ترجمه میشود و `target` داخل `<>` باید دقیقاً همان شناسهی انگلیسی اصلی (بدون تغییر) باقی بماند، چون تغییر آن لینک را خراب میکند. | |
| 58 | 61 | ||
@@ -190,5 +193,4 @@ python3 scripts/update_python_version.py v3.15.0 --keep-src | |||
| 190 | 193 | ||
| 191 | 194 | پیشنهادهای افزودن واژهی جدید نیز پس از بررسی اولیهی نگهدارندگان، در صورت نیاز از همان فرایند نظرسنجی توضیح داده شده در بالا استفاده خواهند کرد تا دربارهی پذیرش یا رد آن تصمیمگیری شود. | |
| 192 | 195 | ||
| 193 | - ## گزارش اشکال در واژهیاب | ||
| 194 | - لطفا برای گزارش اشکال در واژهیاب به مخزن [python-docs-fa-glossary](https://github.com/sepehr-rs/python-docs-fa-glossary) مراجعه کنید. | ||
| 196 | + مشارکتها به واژهنامه باید به پروندهی `glossary.tsv` انجام شوند. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,8 +19,11 @@ | |||
| 19 | 19 | پیش از شروع، حتماً نگاهی به این پروندهها بیندازید: | |
| 20 | 20 | ||
| 21 | 21 | - [CONTRIBUTING.md](CONTRIBUTING.md) — راهنمای کامل مشارکت: انواع ایشیو، نکات نگارشی و تایپوگرافی فارسی، سطح رسمیت و لحن نوشتار، اندازهی پولریکوئست، فرایند بازبینی و تأیید پولریکوئست، همگامسازی با نسخههای جدید پایتون (`scripts/update_python_version.py`)، پاکسازی رشتههای `fuzzy` و نگهداری اعتبار مترجمان در سرآیند پروندههای `.po`. | |
| 22 | - - [GLOSSARY.md](GLOSSARY.md) — واژهنامهی معادلهای فارسی اصطلاحات تخصصی؛ هنگام ترجمه باید به آن پایبند باشید. | ||
| 22 | + | ||
| 23 | + - [واژهیاب](http://python.github.io/python-docs-fa/glossary-searcher) — ابزار جستوجوی واژگان تخصصی مستندات پایتون؛ هنگام ترجمه میتوانید از آن برای یافتن معادلهای فارسی ثبتشده و مشاهدهی نمونههای کاربرد واژگان در پیکرهی مستندات استفاده کنید. | ||
| 24 | + | ||
| 23 | 25 | - [TEAM.md](TEAM.md) — فهرست هماهنگکنندهها، بازبینها و مترجمان بههمراه آمار مشارکت. | |
| 26 | + | ||
| 24 | 27 | - [STATUS.md](STATUS.md) — جدول وضعیت ترجمهی پروندهها که بهصورت خودکار بهروزرسانی میشود. | |
| 25 | 28 | ||
| 26 | 29 | ### شاخههای نسخه | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,150 @@ | |||
| 1 | + #!/usr/bin/env python3 | ||
| 2 | + """ | ||
| 3 | + Builds corpus.json and glossary.json from the python/python-docs-fa repository. | ||
| 4 | + | ||
| 5 | + corpus.json shape (consumed by the glossary searcher site): | ||
| 6 | + [ { "msgid": "...", "msgstr": "...", "file": "library/functions.po", "line": 123 }, ... ] | ||
| 7 | + | ||
| 8 | + glossary.json shape: | ||
| 9 | + [ { "en": "decorator", "fa": "دکوراتور، آراینده" }, ... ] | ||
| 10 | + | ||
| 11 | + Usage: | ||
| 12 | + python build_corpus.py --repo-dir ./python-docs-fa --glossary-tsv ./glossary.tsv --out-dir ./data | ||
| 13 | + """ | ||
| 14 | + import argparse | ||
| 15 | + import csv | ||
| 16 | + import json | ||
| 17 | + import os | ||
| 18 | + import sys | ||
| 19 | + | ||
| 20 | + try: | ||
| 21 | + import polib | ||
| 22 | + except ImportError: | ||
| 23 | + print("ERROR: polib is required. Install with: pip install polib", file=sys.stderr) | ||
| 24 | + sys.exit(1) | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + def find_po_files(repo_dir): | ||
| 28 | + po_files = [] | ||
| 29 | + for root, _dirs, files in os.walk(repo_dir): | ||
| 30 | + # skip VCS/meta directories | ||
| 31 | + if "/.git" in root or root.endswith("/.git"): | ||
| 32 | + continue | ||
| 33 | + for fname in files: | ||
| 34 | + if fname.endswith(".po"): | ||
| 35 | + full_path = os.path.join(root, fname) | ||
| 36 | + rel_path = os.path.relpath(full_path, repo_dir) | ||
| 37 | + po_files.append((full_path, rel_path)) | ||
| 38 | + return sorted(po_files, key=lambda x: x[1]) | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + def parse_po_files(repo_dir): | ||
| 42 | + """Parse every .po file into flattened msgid/msgstr corpus entries.""" | ||
| 43 | + entries = [] | ||
| 44 | + skipped = 0 | ||
| 45 | + po_files = find_po_files(repo_dir) | ||
| 46 | + | ||
| 47 | + if not po_files: | ||
| 48 | + print(f"WARNING: no .po files found under {repo_dir}", file=sys.stderr) | ||
| 49 | + | ||
| 50 | + for full_path, rel_path in po_files: | ||
| 51 | + try: | ||
| 52 | + po = polib.pofile(full_path) | ||
| 53 | + except Exception as e: | ||
| 54 | + print(f"WARNING: failed to parse {rel_path}: {e}", file=sys.stderr) | ||
| 55 | + skipped += 1 | ||
| 56 | + continue | ||
| 57 | + | ||
| 58 | + for entry in po: | ||
| 59 | + # Skip obsolete, fuzzy, or empty-translation entries -- they | ||
| 60 | + # aren't useful corpus results and fuzzy ones are unreviewed. | ||
| 61 | + if entry.obsolete: | ||
| 62 | + continue | ||
| 63 | + if "fuzzy" in entry.flags: | ||
| 64 | + continue | ||
| 65 | + if not entry.msgid or not entry.msgstr: | ||
| 66 | + continue | ||
| 67 | + | ||
| 68 | + entries.append( | ||
| 69 | + { | ||
| 70 | + "msgid": entry.msgid, | ||
| 71 | + "msgstr": entry.msgstr, | ||
| 72 | + "file": rel_path, | ||
| 73 | + "line": entry.linenum if hasattr(entry, "linenum") else 0, | ||
| 74 | + } | ||
| 75 | + ) | ||
| 76 | + | ||
| 77 | + print( | ||
| 78 | + f"Parsed {len(po_files)} .po files ({skipped} skipped), " | ||
| 79 | + f"{len(entries)} translated entries", | ||
| 80 | + file=sys.stderr, | ||
| 81 | + ) | ||
| 82 | + return entries | ||
| 83 | + | ||
| 84 | + | ||
| 85 | + def parse_glossary_tsv(tsv_path): | ||
| 86 | + """Parse the glossary TSV (English<TAB>Persian) into glossary.json entries.""" | ||
| 87 | + entries = [] | ||
| 88 | + with open(tsv_path, "r", encoding="utf-8") as f: | ||
| 89 | + reader = csv.reader(f, delimiter="\t") | ||
| 90 | + rows = list(reader) | ||
| 91 | + | ||
| 92 | + if not rows: | ||
| 93 | + return entries | ||
| 94 | + | ||
| 95 | + # Skip header row if it looks like one | ||
| 96 | + start_idx = 1 if rows[0][:2] == ["English", "Persian"] else 0 | ||
| 97 | + | ||
| 98 | + for row in rows[start_idx:]: | ||
| 99 | + if len(row) < 2: | ||
| 100 | + continue | ||
| 101 | + en, fa = row[0].strip(), row[1].strip() | ||
| 102 | + if en and fa: | ||
| 103 | + entries.append({"en": en, "fa": fa}) | ||
| 104 | + | ||
| 105 | + print(f"Parsed {len(entries)} glossary entries", file=sys.stderr) | ||
| 106 | + return entries | ||
| 107 | + | ||
| 108 | + | ||
| 109 | + def main(): | ||
| 110 | + parser = argparse.ArgumentParser(description=__doc__) | ||
| 111 | + parser.add_argument( | ||
| 112 | + "--repo-dir", required=True, help="Path to the cloned python-docs-fa checkout" | ||
| 113 | + ) | ||
| 114 | + parser.add_argument( | ||
| 115 | + "--glossary-tsv", | ||
| 116 | + required=True, | ||
| 117 | + help="Path to the glossary TSV file (English<TAB>Persian)", | ||
| 118 | + ) | ||
| 119 | + parser.add_argument( | ||
| 120 | + "--out-dir", | ||
| 121 | + required=True, | ||
| 122 | + help="Directory to write corpus.json and glossary.json into", | ||
| 123 | + ) | ||
| 124 | + args = parser.parse_args() | ||
| 125 | + | ||
| 126 | + os.makedirs(args.out_dir, exist_ok=True) | ||
| 127 | + | ||
| 128 | + corpus = parse_po_files(args.repo_dir) | ||
| 129 | + glossary = parse_glossary_tsv(args.glossary_tsv) | ||
| 130 | + | ||
| 131 | + corpus_path = os.path.join(args.out_dir, "corpus.json") | ||
| 132 | + glossary_path = os.path.join(args.out_dir, "glossary.json") | ||
| 133 | + | ||
| 134 | + with open(corpus_path, "w", encoding="utf-8") as f: | ||
| 135 | + json.dump(corpus, f, ensure_ascii=False, separators=(",", ":")) | ||
| 136 | + | ||
| 137 | + with open(glossary_path, "w", encoding="utf-8") as f: | ||
| 138 | + json.dump(glossary, f, ensure_ascii=False, separators=(",", ":")) | ||
| 139 | + | ||
| 140 | + print( | ||
| 141 | + f"Wrote {corpus_path} ({os.path.getsize(corpus_path):,} bytes)", file=sys.stderr | ||
| 142 | + ) | ||
| 143 | + print( | ||
| 144 | + f"Wrote {glossary_path} ({os.path.getsize(glossary_path):,} bytes)", | ||
| 145 | + file=sys.stderr, | ||
| 146 | + ) | ||
| 147 | + | ||
| 148 | + | ||
| 149 | + if __name__ == "__main__": | ||
| 150 | + main() | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments