2026-10-20 TUE UTC 12:42 PM TPE 8:42 PM 每小時自動更新 中文 EN
LIVE 快訊
← 返回網站更新紀錄 Site Changelog

提交原始紀錄

阻擋簡體字進入公開中文內容 (#217) 新增 OpenCC 發布前驗證、回歸測試,並修正 2026-09-22 公開文章與晨間快報。

SHA
f9628128302d0aeb5e0f7e8d6f9c5ad0a4c6eeb2
提交時間
作者
nnneeeooo-nnneeeooo
提交者
web-flow

變更檔案 (5)

  • data/articles/2026-09-22T00.json modified · +2 / −2
  • data/briefings/2026-09-22-morning.json modified · +2 / −2
  • pipeline/write.py modified · +36 / −0
  • requirements.txt modified · +1 / −0
  • tests/test_write_offline.py modified · +8 / −0

完整差異

@@ -8,8 +8,8 @@\n       "image": null,\n       "sourceImageCandidates": [],\n       "zh": {\n-        "title": "美航空公司反对中国国航增飞纽约华盛顿",\n-        "summary": "美航空公司反对中国国航增飞纽约与华盛顿航班",\n+        "title": "美國航空業者反對中國國際航空增飛紐約、華盛頓",\n+        "summary": "美國航空業者反對中國國際航空增飛紐約與華盛頓航班",\n         "body": [\n           "美國主要航空公司正反對中國國際航空(Air China)申請增加北京往返紐約與華盛頓的航班,理由是中國航空公司可使用俄羅斯領空,形成美國競爭對手無法比擬的優勢。",\n           "路透社報導指出,這些航班與中國國家主席習近平計劃訪問美國有關,屬暫時性安排,而非永久增加航班;習近平預定於2026年9月23日至25日訪問美國,與總統川普會談。",\n@@ -135,8 +135,8 @@\n         "item_type": "new",\n         "previous_event_id": null,\n         "category": "aviation_industry",\n-        "headline": "美航空公司反对中国国航增飞纽约华盛顿",\n-        "summary": "美航空公司反对中国国航增飞纽约与华盛顿航班",\n+        "headline": "美國航空業者反對中國國際航空增飛紐約、華盛頓",\n+        "summary": "美國航空業者反對中國國際航空增飛紐約與華盛頓航班",\n         "headline_en": "US airlines oppose Air China request for extra New York and Washington flights",\n         "summary_en": "US airlines oppose Air China's bid for extra New York Washington flights",\n         "event_time": null,\n@@ -37,6 +37,8 @@\n from difflib import SequenceMatcher\n from pathlib import Path\n \n+from opencc import OpenCC\n+\n from common import (\n     ARTICLES_DIR,\n     BASE_PATH,\n@@ -87,6 +89,37 @@\n EN_BRIEF_MIN_WORDS = 90\n EN_BRIEF_MAX_WORDS = 150\n \n+_S2T = OpenCC("s2t")\n+\n+\n+def simplified_chinese_error(draft: dict) -> str | None:\n+    """Reject reader-facing Chinese copy that still contains simplified glyphs."""\n+    fields: list[tuple[str, object]] = []\n+    zh = draft.get("zh")\n+    if isinstance(zh, dict):\n+        fields.extend([\n+            ("zh.title", zh.get("title")),\n+            ("zh.summary", zh.get("summary")),\n+        ])\n+        body = zh.get("body")\n+        if isinstance(body, list):\n+            fields.extend((f"zh.body[{index}]", paragraph)\n+                          for index, paragraph in enumerate(body))\n+    flash = draft.get("flash")\n+    if isinstance(flash, dict):\n+        fields.append(("flash.zh", flash.get("zh")))\n+    incident = draft.get("incident")\n+    if isinstance(incident, dict):\n+        for key in ("phase", "location", "desc"):\n+            bilingual = incident.get(key)\n+            if isinstance(bilingual, dict):\n+                fields.append((f"incident.{key}.zh", bilingual.get("zh")))\n+    for field, value in fields:\n+        if isinstance(value, str) and _S2T.convert(value) != value:\n+            return f"{field} contains Simplified Chinese characters"\n+    return None\n+\n+\n _EDITORIAL_PROCESS_RE = re.compile(\n     r"(?:本文|本報導|這篇(?:文章|報導)).{0,60}"\n     r"(?:採用|使用|引用|補足|補充|核對|交叉確認|資料來源|來源資料)"\n@@ -1023,6 +1056,9 @@ def validate_draft(draft):\n         if len(body) > MAX_BODY_PARAGRAPHS:\n             return (f"{lang}.body has {len(body)} paragraphs; maximum is "\n                     f"{MAX_BODY_PARAGRAPHS}")\n+    language_error = simplified_chinese_error(draft)\n+    if language_error:\n+        return language_error\n     process_error = editorial_process_error(draft)\n     if process_error:\n         return process_error\n@@ -6,3 +6,4 @@ lxml>=5.0,<6\n jinja2>=3.1,<4\n cryptography>=45,<47\n airportsdata==20260315\n+opencc-python-reimplemented>=0.1.7,<1\n@@ -533,6 +533,14 @@ def test_extract_json_and_validate_draft():\n \n     check(write.validate_draft(DRAFT_SAFETY) is None, "safety draft validates")\n     check(write.validate_draft(DRAFT_BIZ) is None, "biz draft validates")\n+    broken = json.loads(json.dumps(DRAFT_BIZ))\n+    broken["zh"]["title"] = "美航空公司反对中国国航增飞纽约华盛顿"\n+    check("Simplified Chinese" in (write.validate_draft(broken) or ""),\n+          "simplified Chinese title is rejected before publication")\n+    broken = json.loads(json.dumps(DRAFT_BIZ))\n+    broken["flash"]["zh"] = "中国国航增飞纽约航班"\n+    check("Simplified Chinese" in (write.validate_draft(broken) or ""),\n+          "simplified Chinese flash is rejected before publication")\n     check(write.zh_body_character_count(DRAFT_BIZ["zh"]["body"])\n           >= write.ZH_BODY_MIN_CHARS, "zh test fixture clears body floor")\n     check(write.en_body_word_count(DRAFT_BIZ["en"]["body"])

你發現了隱藏主題!

8-bit 主題已解鎖。重新整理後,就能在主題選單選擇 8-bit。