From 92cc4adc48a856e239be7449a81d4b07974a30d8 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:53:10 +0800 Subject: [PATCH 1/7] =?UTF-8?q?ci(ISSUE=5FTEMPLATE):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=AE=AE=E9=A2=98=E6=A8=A1=E6=9D=BF=E8=AF=AD=E7=A7=8D=E7=BA=AF?= =?UTF-8?q?=E5=BA=A6=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用 OpenCC 转换比对校验繁体模板未混入简体字、简体模板未混入繁体字;议题模板或检查脚本变更时由工作流自动运行。 --- .../workflows/check_issue_template_purity.yml | 33 +++++ script/check_issue_template_purity.py | 137 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 .github/workflows/check_issue_template_purity.yml create mode 100644 script/check_issue_template_purity.py diff --git a/.github/workflows/check_issue_template_purity.yml b/.github/workflows/check_issue_template_purity.yml new file mode 100644 index 000000000..8310fa5e8 --- /dev/null +++ b/.github/workflows/check_issue_template_purity.yml @@ -0,0 +1,33 @@ +name: 议题模板语种纯度 + +on: + pull_request: + paths: + - '.github/ISSUE_TEMPLATE/**' + - '.github/workflows/check_issue_template_purity.yml' + - 'script/check_issue_template_purity.py' + push: + paths: + - '.github/ISSUE_TEMPLATE/**' + - '.github/workflows/check_issue_template_purity.yml' + - 'script/check_issue_template_purity.py' + workflow_dispatch: + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: 安装依赖 + run: pip install pyyaml opencc-python-reimplemented + + - name: 检查议题模板语种纯度 + run: python script/check_issue_template_purity.py diff --git a/script/check_issue_template_purity.py b/script/check_issue_template_purity.py new file mode 100644 index 000000000..d260d45b3 --- /dev/null +++ b/script/check_issue_template_purity.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +"""议题模板语种纯度检查。 + +简体模板中不得混入繁体字,繁体模板中不得混入简体字(用 OpenCC 转换比对字形)。 + +用法: + python script/check_issue_template_purity.py # 检查全部已登记模板 + python script/check_issue_template_purity.py 文件名... # 仅检查指定模板 +""" + +from __future__ import annotations + +import re +import sys +from difflib import SequenceMatcher +from pathlib import Path +from typing import Any, Callable, Iterator + +try: + import opencc + import yaml +except ModuleNotFoundError as exc: # 缺依赖时给出可执行的提示 + raise SystemExit( + f"缺少依赖 {exc.name},请先安装:pip install pyyaml opencc-python-reimplemented" + ) from exc + +TEMPLATE_DIR = ( + Path(__file__).resolve().parents[1] / ".github" / "ISSUE_TEMPLATE" +) + +# 模板文件 → 期望语种(新增模板需在此登记) +TEMPLATES: dict[str, str] = { + "bug-提交-简体中文-.yml": "CN", + "bug-提交-繁體中文-.yml": "TW", +} + + +def _walk_strings(node: Any, path: str = "") -> Iterator[tuple[str, str]]: + """递归产出 (字段路径, 字符串值)。""" + if isinstance(node, dict): + for key, value in node.items(): + yield from _walk_strings( + value, f"{path}.{key}" if path else str(key) + ) + elif isinstance(node, list): + for index, item in enumerate(node): + yield from _walk_strings(item, f"{path}[{index}]") + elif isinstance(node, str) and node: + yield path, node + + +def main(argv: list[str]) -> int: + # Windows 管道重定向时强制 UTF-8,避免中文输出触发 UnicodeEncodeError + sys.stdout.reconfigure(encoding="utf-8") + + converter: dict[str, Callable[[str], str]] = { + "CN": opencc.OpenCC("t2s").convert, + "TW": opencc.OpenCC("s2tw").convert, + } + + if argv: + names = [Path(arg).name for arg in argv] + else: + found = sorted(p.name for p in TEMPLATE_DIR.glob("*.yml")) + unregistered = [ + name + for name in found + if name not in TEMPLATES and name != "config.yml" + ] + if unregistered: + print(f"❌ 发现未登记的模板:{'、'.join(unregistered)}", file=sys.stderr) + print( + " 请在本脚本的 TEMPLATES 中登记其语种(config.yml 无需登记)。", + file=sys.stderr, + ) + return 1 + names = [name for name in found if name in TEMPLATES] + + failed = False + for name in names: + lang = TEMPLATES.get(name) + path = TEMPLATE_DIR / name + if lang is None: + print(f"❌ 未登记的模板:{name}", file=sys.stderr) + failed = True + elif not path.is_file(): + print(f"❌ 模板文件不存在:{path}", file=sys.stderr) + failed = True + else: + # 收集纯度问题(字段路径 + 改动明细) + issues: list[str] = [] + for field, value in _walk_strings( + yaml.safe_load(path.read_text(encoding="utf-8")) + ): + # 代码块与行内代码不参与检查(内容可能保留原文形式) + text = re.sub(r"```.*?```", "", value, flags=re.DOTALL) + text = re.sub(r"`[^`]+`", "", text) + converted = converter[lang](text) + # 列出转换前后被改动的字(形如 x→y) + changes: list[str] = [] + for tag, i1, i2, j1, j2 in SequenceMatcher( + None, text, converted, autojunk=False + ).get_opcodes(): + if tag == "replace" and i2 - i1 == j2 - j1: + changes.extend( + f"{a}→{b}" + for a, b in zip(text[i1:i2], converted[j1:j2]) + if a != b + ) + elif tag != "equal": + changes.append( + f"{text[i1:i2] or ''}→{converted[j1:j2] or ''}" + ) + if changes: + issues.append( + f"{field}:" + + "、".join(changes[:8]) + + (f" 等共 {len(changes)} 处" if len(changes) > 8 else "") + ) + if issues: + failed = True + kind = "繁体" if lang == "CN" else "简体" + print(f"❌ {name}:混入{kind}字({len(issues)} 个字段)") + for issue in issues: + print(f" 🈴 {issue}") + else: + print(f"✅ {name}:通过") + + if failed: + print("\n提示:请把混入的字改回本模板对应的字形。") + return 1 + print("\n✅ 议题模板语种纯度检查通过") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) From ad217c33683a1258ac9f63bef25a1b4c85bff4a8 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 01:11:57 +0800 Subject: [PATCH 2/7] =?UTF-8?q?test(ISSUE=5FTEMPLATE):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=AE=AE=E9=A2=98=E6=A8=A1=E6=9D=BF=E8=AF=AD=E7=A7=8D?= =?UTF-8?q?=E7=BA=AF=E5=BA=A6=E6=A3=80=E6=9F=A5=E7=9A=84=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 覆盖简繁字形混入、代码块与行内代码豁免、未登记模板、已登记模板缺失,以及仓库内真实模板的回归保护。 --- .gitignore | 3 + test/test_check_issue_template_purity.py | 119 +++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 test/test_check_issue_template_purity.py diff --git a/.gitignore b/.gitignore index 48c72717b..9c3530d2c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ main(local).js # logs *.log + +# python +__pycache__/ diff --git a/test/test_check_issue_template_purity.py b/test/test_check_issue_template_purity.py new file mode 100644 index 000000000..29337b520 --- /dev/null +++ b/test/test_check_issue_template_purity.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""script/check_issue_template_purity.py 的单元测试。 + +覆盖场景: +- 纯简/繁模板通过; +- 繁体模板混入简体字、简体模板混入繁体字时报错; +- 代码块与行内代码中的字形不参与检查; +- 未登记的模板文件、缺失的已登记模板都会失败; +- 仓库内真实模板必须通过检查。 +""" + +from __future__ import annotations + +import shutil +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + +SCRIPT = Path(__file__).resolve().parents[1] / "script" / "check_issue_template_purity.py" + +CN_NAME = "bug-提交-简体中文-.yml" +TW_NAME = "bug-提交-繁體中文-.yml" + + +def _template(name: str, value: str) -> str: + """构造一个最小的议题模板 YAML。 + + 块标量的内容必须比 `value:` 键缩进更深,故用 6 空格。 + """ + body = ( + " value: |\n" + "\n".join(f" {line}" for line in value.splitlines()) + "\n" + if "\n" in value + else f" value: {value}\n" + ) + return f"name: {name}\ndescription: 提交 BUG\nbody:\n- type: markdown\n attributes:\n{body}" + + +def _cn(value: str = "欢迎") -> str: + return _template("Bug 提交(简体中文)", value) + + +def _tw(value: str = "歡迎") -> str: + return _template("Bug 提交(繁體中文)", value) + + +def _output(result: "subprocess.CompletedProcess[str]") -> str: + """容错拼接子进程输出:读取线程解码失败时 stdout/stderr 可能为 None。""" + return (result.stdout or "") + (result.stderr or "") + + +class PurityCheckTest(unittest.TestCase): + def setUp(self) -> None: + self._tmp = tempfile.TemporaryDirectory() + self.root = Path(self._tmp.name) + + def tearDown(self) -> None: + self._tmp.cleanup() + + def run_check(self, templates: dict[str, str], *args: str) -> "subprocess.CompletedProcess[str]": + """把脚本复制进临时仓库骨架后运行,模拟真实目录结构。""" + (self.root / "script").mkdir(parents=True, exist_ok=True) + shutil.copy2(SCRIPT, self.root / "script" / SCRIPT.name) + template_dir = self.root / ".github" / "ISSUE_TEMPLATE" + template_dir.mkdir(parents=True, exist_ok=True) + for filename, content in templates.items(): + (template_dir / filename).write_text(content, encoding="utf-8") + return subprocess.run( + [sys.executable, str(self.root / "script" / SCRIPT.name), *args], + capture_output=True, text=True, encoding="utf-8", errors="replace", + ) + + def test_pure_templates_pass(self) -> None: + result = self.run_check({CN_NAME: _cn(), TW_NAME: _tw()}) + self.assertEqual(0, result.returncode, _output(result)) + + def test_simplified_char_in_traditional_template_is_reported(self) -> None: + result = self.run_check({CN_NAME: _cn(), TW_NAME: _tw("步骤")}) + self.assertEqual(1, result.returncode, _output(result)) + self.assertIn("骤→驟", _output(result)) + self.assertIn(TW_NAME, _output(result)) + + def test_traditional_char_in_simplified_template_is_reported(self) -> None: + result = self.run_check({CN_NAME: _cn("步驟"), TW_NAME: _tw()}) + self.assertEqual(1, result.returncode, _output(result)) + self.assertIn("驟→骤", _output(result)) + self.assertIn(CN_NAME, _output(result)) + + def test_code_block_and_code_span_are_ignored(self) -> None: + value = "示例:\n\n```\n步驟與歡迎\n```\n\n还有 `繁體` 这个词\n\n欢迎" + result = self.run_check({CN_NAME: _cn(value), TW_NAME: _tw()}) + self.assertEqual(0, result.returncode, _output(result)) + + def test_unregistered_template_is_rejected(self) -> None: + result = self.run_check({ + CN_NAME: _cn(), + TW_NAME: _tw(), + "feature-request.yml": _template("功能请求", "欢迎大家"), + }) + self.assertEqual(1, result.returncode, _output(result)) + self.assertIn("未登记", _output(result)) + + def test_missing_registered_template_is_rejected(self) -> None: + result = self.run_check({CN_NAME: _cn()}) + self.assertEqual(1, result.returncode, _output(result)) + self.assertIn(TW_NAME, _output(result)) + + def test_repo_templates_pass(self) -> None: + """仓库内真实模板必须通过检查(回归保护)。""" + result = subprocess.run( + [sys.executable, str(SCRIPT)], + capture_output=True, text=True, encoding="utf-8", errors="replace", + ) + self.assertEqual(0, result.returncode, _output(result)) + + +if __name__ == "__main__": + unittest.main() From e48200c3661046fd5bbb978353b072b0e12ff301 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 01:12:05 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix(ISSUE=5FTEMPLATE):=20=E7=BA=AF=E5=BA=A6?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E6=A0=A1=E9=AA=8C=E5=B7=B2=E7=99=BB=E8=AE=B0?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E7=BC=BA=E5=A4=B1=E5=B9=B6=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 无参数检查时,names 只取自实际存在的文件,已登记的模板若缺失会被静默跳过;现补充缺失校验并退 1。另把 stderr 也强制为 UTF-8,避免 Windows 管道重定向下中文提示触发 UnicodeEncodeError。 --- script/check_issue_template_purity.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/script/check_issue_template_purity.py b/script/check_issue_template_purity.py index d260d45b3..449fbbcc5 100644 --- a/script/check_issue_template_purity.py +++ b/script/check_issue_template_purity.py @@ -51,7 +51,8 @@ def _walk_strings(node: Any, path: str = "") -> Iterator[tuple[str, str]]: def main(argv: list[str]) -> int: # Windows 管道重定向时强制 UTF-8,避免中文输出触发 UnicodeEncodeError - sys.stdout.reconfigure(encoding="utf-8") + for stream in (sys.stdout, sys.stderr): + stream.reconfigure(encoding="utf-8", errors="replace") converter: dict[str, Callable[[str], str]] = { "CN": opencc.OpenCC("t2s").convert, @@ -74,6 +75,14 @@ def main(argv: list[str]) -> int: file=sys.stderr, ) return 1 + missing = [name for name in TEMPLATES if name not in found] + if missing: + print(f"❌ 已登记的模板不存在:{'、'.join(missing)}", file=sys.stderr) + print( + " 请确认模板文件路径,或从本脚本的 TEMPLATES 中移除对应条目。", + file=sys.stderr, + ) + return 1 names = [name for name in found if name in TEMPLATES] failed = False From 0ca396f76dd666e4fcba76ace1ec173ddf4752d7 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:53:09 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix(ISSUE=5FTEMPLATE):=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E7=B9=81=E4=BD=93=E6=A8=A1=E6=9D=BF=E6=B7=B7=E5=85=A5=E7=9A=84?= =?UTF-8?q?=E7=AE=80=E4=BD=93=E5=AD=97=E5=B9=B6=E7=BB=9F=E4=B8=80=E7=AE=80?= =?UTF-8?q?=E7=B9=81=E4=B8=A4=E7=89=88=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正「Bug 提交(繁體中文)」模板中混入的简体字(欢迎、步骤、并、对、相关、選择、扩展、源码),并把两版模板的字段 id、说明文案与链接排版对齐。 --- ...\344\275\223\344\270\255\346\226\207-.yml" | 31 +++++----- ...\351\253\224\344\270\255\346\226\207-.yml" | 57 ++++++++++--------- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git "a/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\256\200\344\275\223\344\270\255\346\226\207-.yml" "b/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\256\200\344\275\223\344\270\255\346\226\207-.yml" index 9d989a36e..7033a0ff8 100644 --- "a/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\256\200\344\275\223\344\270\255\346\226\207-.yml" +++ "b/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\256\200\344\275\223\344\270\255\346\226\207-.yml" @@ -1,7 +1,6 @@ name: Bug 提交(简体中文) description: 提交 BUG labels: bug - body: - type: markdown attributes: @@ -10,6 +9,7 @@ body: attributes: value: | 感谢您提交议题!请补充以下内容,以便我们能更好地协助您。 + 提交议题前确保您已阅读[常见问题(FAQ)](https://github.com/maboloshi/github-chinese/issues/493)。 - type: textarea id: description @@ -26,14 +26,14 @@ body: validations: required: true - type: textarea - id: expectation + id: expected attributes: label: 预期 description: 请描述你对本插件行为的预期。 validations: required: true - type: textarea - id: realization + id: real attributes: label: 实际 description: 请描述本插件的实际行为。 @@ -52,9 +52,9 @@ body: label: 浏览器名称 description: 请选择运行本插件的浏览器的名称。 options: - - Microsoft Edge - - Google Chrome - - Others + - Microsoft Edge + - Google Chrome + - Others validations: required: true - type: input @@ -63,8 +63,9 @@ body: label: 浏览器版本 description: | 请填入运行本插件的浏览器的版本。 - [Microsoft Edge 版本](https://support.microsoft.com/zh-cn/microsoft-edge/c726bee8-c42e-e472-e954-4cf5123497eb) - [Google Chrome 版本](chrome://settings/help) + + [Microsoft Edge](https://support.microsoft.com/zh-cn/microsoft-edge/c726bee8-c42e-e472-e954-4cf5123497eb) · + [Google Chrome](chrome://settings/help) placeholder: 版本 146.0.3856.62 (正式版本) (arm64) validations: required: true @@ -74,8 +75,8 @@ body: label: 脚本管理器名称 description: 请选择管理本插件的脚本管理器的名称。 options: - - 篡改猴(Tampermonkey) - - Others + - 篡改猴(Tampermonkey) + - Others validations: required: true - type: input @@ -84,8 +85,9 @@ body: label: 脚本管理器版本 description: | 请填入管理本插件的脚本管理器的版本。 + [Microsoft Edge 扩展](https://support.microsoft.com/zh-cn/topic/a3ae1ebb-8e7f-49df-a5f8-8c3f56c8078b) - placeholder: "5.4.1" + placeholder: 5.4.1 validations: required: true - type: input @@ -94,7 +96,10 @@ body: label: 插件版本 description: | 请填入 GitHub 中文化插件的版本。 - 见 [GitHub 中文化插件](extension://iikmkjmpaadaobahmlepeloendndfphd/options.html#nav=49f369f3-16e7-423f-86d9-1aa23aa2fd1c)源码中 `@version` 的值(不再接受 1.9.2 版本反馈)。 - placeholder: "1.9.3" + + 见本插件源码中 `@version` 的值(不再接受 1.9.2 版本反馈)。 + + [Microsoft Edge](extension://iikmkjmpaadaobahmlepeloendndfphd/options.html) + placeholder: 1.9.3 validations: required: true diff --git "a/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\271\201\351\253\224\344\270\255\346\226\207-.yml" "b/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\271\201\351\253\224\344\270\255\346\226\207-.yml" index 8353dca3c..724934a95 100644 --- "a/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\271\201\351\253\224\344\270\255\346\226\207-.yml" +++ "b/.github/ISSUE_TEMPLATE/bug-\346\217\220\344\272\244-\347\271\201\351\253\224\344\270\255\346\226\207-.yml" @@ -1,16 +1,16 @@ name: Bug 提交(繁體中文) description: 提交 BUG labels: bug - body: - type: markdown attributes: - value: "### 欢迎!" + value: "### 歡迎!" - type: markdown attributes: value: | - 感謝您提交議題!請補充以下內容,以便我們能更好地協助您: - 提交議題前確保您已閲讀[常見問題(FAQ)](https://github.com/maboloshi/github-chinese/issues/493)。 + 感謝您提交議題!請補充以下內容,以便我們能更好地協助您。 + + 提交議題前確保您已閱讀[常見問題(FAQ)](https://github.com/maboloshi/github-chinese/issues/493)。 - type: textarea id: description attributes: @@ -21,40 +21,40 @@ body: - type: textarea id: steps attributes: - label: 步骤 - description: 請逐步描述你遇到的問題,并帶上測試連結(如有)。 + label: 步驟 + description: 請逐步描述你遇到的問題,並帶上測試連結(如有)。 validations: required: true - type: textarea - id: expectation + id: expected attributes: label: 預期 - description: 請描述你对本插件行為的預期。 + description: 請描述你對本插件行為的預期。 validations: required: true - type: textarea - id: realization + id: real attributes: - label: 實際表現 - description: 請描述本插件的實際表現。 + label: 實際 + description: 請描述本插件的實際行為。 validations: required: true - type: textarea id: evidence attributes: label: 附件 - description: 請提供相关相關截圖或附件(如有)。 + description: 請提供相關截圖或附件(如有)。 validations: required: false - type: dropdown id: browser-name attributes: label: 瀏覽器名稱 - description: 請選择運行本插件的瀏覽器的名稱。 + description: 請選擇運行本插件的瀏覽器的名稱。 options: - - Microsoft Edge - - Google Chrome - - Others + - Microsoft Edge + - Google Chrome + - Others validations: required: true - type: input @@ -63,19 +63,20 @@ body: label: 瀏覽器版本 description: | 請填入運行本插件的瀏覽器的版本。 - [Microsoft Edge 版本](https://support.microsoft.com/zh-cn/microsoft-edge/c726bee8-c42e-e472-e954-4cf5123497eb) - [Google Chrome 版本](chrome://settings/help) - placeholder: 版本 146.0.3856.62 (正式版本) (arm64) + + [Microsoft Edge](https://support.microsoft.com/zh-cn/microsoft-edge/c726bee8-c42e-e472-e954-4cf5123497eb) · + [Google Chrome](chrome://settings/help) + placeholder: 版本 146.0.3856.62 (正式組建) (arm64) validations: required: true - type: dropdown id: script-manager-name attributes: label: 腳本管理器名稱 - description: 請選择管理本插件的腳本管理器的名稱。 + description: 請選擇管理本插件的腳本管理器的名稱。 options: - - 篡改猴(Tampermonkey) - - Others + - 篡改猴(Tampermonkey) + - Others validations: required: true - type: input @@ -84,17 +85,21 @@ body: label: 腳本管理器版本 description: | 請填入管理本插件的腳本管理器的版本。 - [Microsoft Edge 扩展](https://support.microsoft.com/zh-cn/topic/a3ae1ebb-8e7f-49df-a5f8-8c3f56c8078b) + + [Microsoft Edge 擴展](https://support.microsoft.com/zh-cn/topic/a3ae1ebb-8e7f-49df-a5f8-8c3f56c8078b) placeholder: 5.4.1 validations: required: true - type: input id: plugin-version attributes: - label: 插件版本 + label: 外掛版本 description: | - 請填入 GitHub 中文化插件的版本。 - 見 [GitHub 中文化插件](extension://iikmkjmpaadaobahmlepeloendndfphd/options.html#nav=49f369f3-16e7-423f-86d9-1aa23aa2fd1c)源码中 `@version` 的值(不再接受 1.9.2 版本反饋)。 + 請填入 GitHub 中文化外掛的版本。 + + 見本外掛原始碼中 `@version` 的值(不再接受 1.9.2 版本回饋)。 + + [Microsoft Edge](extension://iikmkjmpaadaobahmlepeloendndfphd/options.html) placeholder: 1.9.3 validations: required: true From a90ce556a66e36f59709ed2b5ad3bd60c108dfed Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 01:55:43 +0800 Subject: [PATCH 5/7] =?UTF-8?q?test(ISSUE=5FTEMPLATE):=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=8F=B0=E6=B9=BE=E7=94=A8=E8=AF=AD=E6=8A=A4=E6=A0=8F?= =?UTF-8?q?=E4=B8=8E=20.yaml=20=E6=96=87=E4=BB=B6=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 台湾用语用例用于防回归:一旦所用 OpenCC 配置带上词汇表(如 s2twp),「插件/腳本/設定」会被改写而误报,此用例会立刻变红。.yaml 用例当前失败:模板目录下的 .yaml 会被 GitHub 忽略,脚本却静默跳过。 --- test/test_check_issue_template_purity.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/test_check_issue_template_purity.py b/test/test_check_issue_template_purity.py index 29337b520..b4bffdfff 100644 --- a/test/test_check_issue_template_purity.py +++ b/test/test_check_issue_template_purity.py @@ -88,10 +88,28 @@ def test_traditional_char_in_simplified_template_is_reported(self) -> None: self.assertIn(CN_NAME, _output(result)) def test_code_block_and_code_span_are_ignored(self) -> None: - value = "示例:\n\n```\n步驟與歡迎\n```\n\n还有 `繁體` 这个词\n\n欢迎" - result = self.run_check({CN_NAME: _cn(value), TW_NAME: _tw()}) + result = self.run_check({ + CN_NAME: _cn("示例:\n\n```\n步驟與歡迎\n```\n\n还有 `繁體` 这个词\n\n欢迎"), + TW_NAME: _tw(), + }) self.assertEqual(0, result.returncode, _output(result)) + def test_taiwan_vocabulary_is_not_reported(self) -> None: + """合法的台湾用语(插件/腳本/設定…)属于词汇差异,不算字形混用。""" + value = "本插件支援繁體,請在腳本管理員中設定" + result = self.run_check({CN_NAME: _cn(), TW_NAME: _tw(value)}) + self.assertEqual(0, result.returncode, _output(result)) + + def test_yaml_extension_is_rejected(self) -> None: + """模板目录下只认 .yml;.yaml 会被 GitHub 忽略,应报错而非静默跳过。""" + result = self.run_check({ + CN_NAME: _cn(), + TW_NAME: _tw(), + "bug-提交-简体中文-.yaml": _cn(), + }) + self.assertEqual(1, result.returncode, _output(result)) + self.assertIn(".yaml", _output(result)) + def test_unregistered_template_is_rejected(self) -> None: result = self.run_check({ CN_NAME: _cn(), From acdea3dc80dcbf1b0641ca5194cc435cbac529f6 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 01:58:23 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix(ISSUE=5FTEMPLATE):=20=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E4=B8=8B=E7=9A=84=20.yaml=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=94=B9=E4=B8=BA=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 议题表单按平台约定必须是 .yml(config.yml 亦然),此前 .yaml 会被静默跳过:既不检查也不提示,登记进 TEMPLATES 还会被误报为缺失。现在显式报错并退出 1。同时注明转换配置只取字形级(s2tw 无词汇表),避免换成 s2twp 后把词汇差异当字形混用。 --- script/check_issue_template_purity.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/script/check_issue_template_purity.py b/script/check_issue_template_purity.py index 449fbbcc5..34e9e8d66 100644 --- a/script/check_issue_template_purity.py +++ b/script/check_issue_template_purity.py @@ -54,6 +54,9 @@ def main(argv: list[str]) -> int: for stream in (sys.stdout, sys.stderr): stream.reconfigure(encoding="utf-8", errors="replace") + # 只比较字形:opencc-python-reimplemented 的 s2tw 不含台湾词汇表; + # 带词汇表的 s2twp 会把「插件」改成「外掛」、「腳本」改成「指令碼」, + # 那是词汇差异而非字形混用,会造成误报(见 test_taiwan_vocabulary_is_not_reported)。 converter: dict[str, Callable[[str], str]] = { "CN": opencc.OpenCC("t2s").convert, "TW": opencc.OpenCC("s2tw").convert, @@ -62,7 +65,26 @@ def main(argv: list[str]) -> int: if argv: names = [Path(arg).name for arg in argv] else: + # GitHub 只识别 .yml;.yaml 会被静默忽略,故显式报错而非跳过 + yaml_named = sorted(p.name for p in TEMPLATE_DIR.glob("*.yaml")) + if yaml_named: + print( + f"❌ 模板目录下存在 .yaml 文件:{'、'.join(yaml_named)}", + file=sys.stderr, + ) + print(" GitHub 只识别 .yml,请将这些文件改名为 .yml。", file=sys.stderr) + return 1 found = sorted(p.name for p in TEMPLATE_DIR.glob("*.yml")) + # 议题表单必须是 .yml(config.yml 亦然),.yaml 会被 GitHub 忽略 + odd = sorted( + p.name for p in TEMPLATE_DIR.glob("*.y*ml") if p.suffix != ".yml" + ) + if odd: + print( + f"❌ 议题表单必须是 .yml(.yaml 不会被 GitHub 读取):{'、'.join(odd)}", + file=sys.stderr, + ) + return 1 unregistered = [ name for name in found From 64d87fb250739be89332ea636ff7eafb17533c47 Mon Sep 17 00:00:00 2001 From: PtJade Ceramic <185668489+PtJade-Ceramic@users.noreply.github.com> Date: Tue, 22 Sep 2026 01:58:24 +0800 Subject: [PATCH 7/7] =?UTF-8?q?ci(ISSUE=5FTEMPLATE):=20=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC=E5=B9=B6=E5=9C=A8=20CI=20?= =?UTF-8?q?=E4=B8=AD=E8=BF=90=E8=A1=8C=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 此前 pip install 不带版本,转换行为由包内词典决定,换包/升级可能引入词汇级误报;现固定 pyyaml==6.0.3、opencc-python-reimplemented==0.1.7。另外补一步 unittest,让本地与 CI 使用同一套用例。 --- .github/workflows/check_issue_template_purity.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check_issue_template_purity.yml b/.github/workflows/check_issue_template_purity.yml index 8310fa5e8..f90a17b13 100644 --- a/.github/workflows/check_issue_template_purity.yml +++ b/.github/workflows/check_issue_template_purity.yml @@ -6,11 +6,13 @@ on: - '.github/ISSUE_TEMPLATE/**' - '.github/workflows/check_issue_template_purity.yml' - 'script/check_issue_template_purity.py' + - 'test/test_check_issue_template_purity.py' push: paths: - '.github/ISSUE_TEMPLATE/**' - '.github/workflows/check_issue_template_purity.yml' - 'script/check_issue_template_purity.py' + - 'test/test_check_issue_template_purity.py' workflow_dispatch: permissions: @@ -26,8 +28,12 @@ jobs: with: python-version: '3.12' + # 固定版本:字形级转换的行为取决于包内词典,升级前先看单元测试 - name: 安装依赖 - run: pip install pyyaml opencc-python-reimplemented + run: pip install pyyaml==6.0.3 opencc-python-reimplemented==0.1.7 - name: 检查议题模板语种纯度 run: python script/check_issue_template_purity.py + + - name: 运行单元测试 + run: python -m unittest discover -s test -p 'test_check_issue_template_purity.py'