feat: 添加符文之语中文名称拉取脚本,更新 skill 文档
- 新增 fetch_runeword_names.py 脚本,从中文 Wiki 拉取 RWWeapons/RWChests/RWQuivers/RWShields/RWHelms 五个页面,提取 101 个符文之语的中英文名称保存为 runeword_names.json
- 更新 skill.md:新增 Step 1(拉取名称参考),步骤编号调整为 1-6
- 新增符文之语名称规则章节,要求 {{#lsth:}} 使用中英文名格式
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0349be8bcc
commit
8e003dd9c2
|
|
@ -20,7 +20,19 @@ description: 同步英文 MediaWiki 页面变更到中文翻译文档。当用
|
|||
|
||||
## 执行步骤
|
||||
|
||||
### Step 1: 运行同步脚本
|
||||
### Step 1: 更新符文之语名称参考
|
||||
|
||||
每次同步前先拉取最新的符文之语中文名称:
|
||||
|
||||
```bash
|
||||
cd /mnt/d/code/sync-pd2-wiki
|
||||
source venv/bin/activate
|
||||
python .claude/skills/wiki-sync-translate/scripts/fetch_runeword_names.py
|
||||
```
|
||||
|
||||
此脚本从中文 Wiki 拉取 RWWeapons、RWChests、RWQuivers、RWShields、RWHelms 五个页面,提取所有符文之语的中英文名称,保存到 `references/runeword_names.json`。翻译符文之语相关页面时必须参考此文件。
|
||||
|
||||
### Step 2: 运行同步脚本
|
||||
|
||||
使用 skill 目录下的专用脚本获取变更:
|
||||
|
||||
|
|
@ -36,7 +48,7 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
|||
- `--since`: 起始时间,格式如 `2026-01-02T12:07:05Z`
|
||||
- `--run`: 必须提供此参数才会执行
|
||||
|
||||
### Step 2: 读取输出文件
|
||||
### Step 3: 读取输出文件
|
||||
|
||||
脚本会在 `wiki_sync_output/<时间戳>/changed_pages/` 目录下生成:
|
||||
|
||||
|
|
@ -50,7 +62,7 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
|||
**重要:** 只读取 `comparison.json`,不要读取整个 `*.cn.txt` 文件以节省 token。
|
||||
|
||||
|
||||
### Step 3: 解析 comparison.json
|
||||
### Step 4: 解析 comparison.json
|
||||
`comparison.json` 格式:
|
||||
|
||||
```json
|
||||
|
|
@ -88,7 +100,7 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
|||
|
||||
**注意:** 如果 `old_line` 和 `new_line` 差距很大但内容相似(如行号从171变到193),这通常意味着中间有其他行被插入或删除,需要仔细检查变更是否真的相关。
|
||||
|
||||
### Step 4: 更新中文文档
|
||||
### Step 5: 更新中文文档
|
||||
|
||||
**核心原则:行号必须完全一致,使用增量修改减少 token 消耗**
|
||||
|
||||
|
|
@ -117,7 +129,7 @@ cp wiki_sync_output/<时间戳>/changed_pages/*.cn.txt wiki_sync_output/<时间
|
|||
// 3. 只读取该行附近内容确认,然后用 Edit 修改
|
||||
```
|
||||
|
||||
### Step 5: 输出结果
|
||||
### Step 6: 输出结果
|
||||
|
||||
更新后的文档位于 `wiki_sync_output/<时间戳>/result_pages/<页面名>.cn.txt`,用户可直接复制到 Wiki。
|
||||
|
||||
|
|
@ -167,6 +179,11 @@ cp wiki_sync_output/<时间戳>/changed_pages/*.cn.txt wiki_sync_output/<时间
|
|||
|
||||
翻译时参考 `references/PD2_glossary.md` 中的标准术语对照表,确保技能名称、灵气名称和通用术语的翻译一致。优先级高于模型自身的翻译选择。
|
||||
|
||||
## 翻译术语表
|
||||
## 符文之语名称规则
|
||||
|
||||
翻译时参考 `references/PD2_glossary.md` 中的标准术语对照表,确保所有技能名称、灵气名称和通用术语的翻译一致。
|
||||
**`{{#lsth:}}` 模板必须使用中文+英文格式**,因为中文 Wiki 页面中每个符文之语的章节标题是 `=== 中文名 英文名 ===` 格式。例如:
|
||||
|
||||
- 正确:`{{#lsth:RWWeapons|力量 Strength}}`
|
||||
- 错误:`{{#lsth:RWWeapons|Strength}}` (只写英文名无法匹配中文页面的章节)
|
||||
|
||||
**名称来源:** 翻译时必须查阅 `references/runeword_names.json`(由 Step 1 的脚本从中文 Wiki 实时拉取生成)。该 JSON 的 key 是英文原名,value 是 `中文名 英文名`。不得自行猜测或翻译符文之语名称。
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"Steel": "钢铁 Steel",
|
||||
"Malice": "怨恨 Malice",
|
||||
"Leaf": "叶子 Leaf",
|
||||
"Pattern": "图纹 Pattern",
|
||||
"Zephyr": "和风 Zephyr",
|
||||
"Holy Thunder": "神圣雷击 Holy Thunder",
|
||||
"Neophyte": "新教徒 Neophyte",
|
||||
"Strength": "力量 Strength",
|
||||
"Edge": "边缘 Edge",
|
||||
"King's Grace": "王者的慈悲 King's Grace",
|
||||
"Spirit": "精神 Spirit",
|
||||
"Purity": "纯洁 Purity",
|
||||
"Insight": "眼光 Insight",
|
||||
"Honor": "荣耀 Honor",
|
||||
"Rampage": "狂暴 Rampage",
|
||||
"Echo": "回响 Echo",
|
||||
"Black": "黑色 Black",
|
||||
"White": "白色 White",
|
||||
"Memory": "记忆 Memory",
|
||||
"Harmony": "和谐 Harmony",
|
||||
"Melody": "旋律 Melody",
|
||||
"Unbending Will": "坚定意志 Unbending Will",
|
||||
"Obedience": "遵从 Obedience",
|
||||
"Passion": "热情 Passion",
|
||||
"Voice of Reason": "思考之声 Voice of Reason",
|
||||
"Lawbringer": "执法者 Lawbringer",
|
||||
"Loyalty": "忠诚 Loyalty",
|
||||
"Crescent Moon": "新月 Crescent Moon",
|
||||
"Venom": "毒牙 Venom",
|
||||
"Oath": "誓约 Oath",
|
||||
"Rift": "裂缝 Rift",
|
||||
"Kingslayer": "弑王者 Kingslayer",
|
||||
"Heart of the Oak": "橡树之心 Heart of the Oak",
|
||||
"Silence": "寂静 Silence",
|
||||
"Death": "死神 Death",
|
||||
"Chaos": "混沌 Chaos",
|
||||
"Call to Arms": "战争召唤 Call to Arms",
|
||||
"Fortitude": "刚毅 Fortitude",
|
||||
"Grief": "悔恨 Grief",
|
||||
"Wind": "轻风 Wind",
|
||||
"Wrath": "愤怒 Wrath",
|
||||
"Beast": "野兽 Beast",
|
||||
"Eternity": "永恒 Eternity",
|
||||
"Infinity": "无限 Infinity",
|
||||
"Fury": "狂怒 Fury",
|
||||
"Famine": "饥荒 Famine",
|
||||
"Faith": "信心 Faith",
|
||||
"Ice": "冰冻 Ice",
|
||||
"Brand": "烙印 Brand",
|
||||
"Phoenix": "凤凰 Phoenix",
|
||||
"Destruction": "毁灭 Destruction",
|
||||
"Last Wish": "最后希望 Last Wish",
|
||||
"Rapture": "狂喜 Rapture",
|
||||
"Plague": "瘟疫 Plague",
|
||||
"Mist": "迷雾 Mist",
|
||||
"Dominion": "圣域 Dominion",
|
||||
"Doom": "末日 Doom",
|
||||
"Hand of Justice": "正义之手 Hand of Justice",
|
||||
"Pride": "骄傲 Pride",
|
||||
"Asylum": "庇护 Asylum",
|
||||
"Obsession": "着魔 Obsession",
|
||||
"Breath of the Dying": "死亡呼吸 Breath of the Dying",
|
||||
"Zenith": "天顶 Zenith",
|
||||
"Stealth": "隐密 Stealth",
|
||||
"Peace": "和平 Peace",
|
||||
"Myth": "神话 Myth",
|
||||
"Smoke": "烟雾 Smoke",
|
||||
"Hustle": "催促 Hustle",
|
||||
"Lionheart": "狮子心 Lionheart",
|
||||
"Treachery": "背信 Treachery",
|
||||
"Wealth": "财富 Wealth",
|
||||
"Enlightenment": "教化 Enlightenment",
|
||||
"Duress": "强制 Duress",
|
||||
"Stone": "石块 Stone",
|
||||
"Gloom": "幽暗 Gloom",
|
||||
"Bone": "白骨 Bone",
|
||||
"Prudence": "慎重 Prudence",
|
||||
"Rain": "降雨 Rain",
|
||||
"Principle": "原理 Principle",
|
||||
"Bramble": "野蔷薇 Bramble",
|
||||
"Dragon": "飞龙 Dragon",
|
||||
"Chains of Honor": "荣耀之链 Chains of Honor",
|
||||
"Enigma": "谜团 Enigma",
|
||||
"Innocence": "纯真 Innocence",
|
||||
"Ancient's Scripture": "远古圣痕 Ancient's Scripture",
|
||||
"Ancient's Foresight": "远古预兆 Ancient's Foresight",
|
||||
"Ancients' Pledge": "古代人的契约 Ancients' Pledge",
|
||||
"Rhyme": "押韵 Rhyme",
|
||||
"Splendor": "灿烂 Splendor",
|
||||
"Sanctuary": "圣堂 Sanctuary",
|
||||
"Exile": "流亡 Exile",
|
||||
"Epiphany": "顿悟 Epiphany",
|
||||
"Dream": "梦境 Dream",
|
||||
"Shattered Wall": "破碎之墙 Shattered Wall",
|
||||
"Nadir": "天底 Nadir",
|
||||
"Radiance": "光辉 Radiance",
|
||||
"Lore": "知识 Lore",
|
||||
"Wisdom": "智慧 Wisdom",
|
||||
"Delirium": "迪勒瑞姆 Delirium",
|
||||
"Flickering Flame": "闪烁火焰 Flickering Flame",
|
||||
"Ferocity": "残暴 Ferocity"
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
从中文 Wiki 拉取所有符文之语页面,提取符文之语的中英文名称并保存为 JSON。
|
||||
供 wiki-sync-translate skill 在翻译符文之语相关页面时参考使用。
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
# ==================== 配置区 ====================
|
||||
WIKI_API_URL_CN = os.getenv("WIKI_API_URL_CN", "https://wiki.projectdiablo2.cn/w/api.php")
|
||||
|
||||
SESSION_CN = requests.Session()
|
||||
SESSION_CN.headers.update({
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
||||
})
|
||||
SESSION_CN.trust_env = False
|
||||
|
||||
# 符文之语页面列表(按装备部位)
|
||||
RUNEWORD_PAGES = [
|
||||
"RWWeapons",
|
||||
"RWChests",
|
||||
"RWQuivers",
|
||||
"RWShields",
|
||||
"RWHelms",
|
||||
]
|
||||
|
||||
# 输出路径
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
REFERENCES_DIR = SCRIPT_DIR.parent / "references"
|
||||
OUTPUT_FILE = REFERENCES_DIR / "runeword_names.json"
|
||||
# ================================================
|
||||
|
||||
|
||||
def get_page_content(title):
|
||||
"""从中文 Wiki 获取页面完整内容"""
|
||||
params = {
|
||||
"action": "query",
|
||||
"prop": "revisions",
|
||||
"titles": title,
|
||||
"rvprop": "content",
|
||||
"rvslots": "main",
|
||||
"format": "json"
|
||||
}
|
||||
try:
|
||||
r = SESSION_CN.get(WIKI_API_URL_CN, params=params)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
pages = data["query"]["pages"]
|
||||
page = next(iter(pages.values()))
|
||||
if "revisions" in page:
|
||||
return page["revisions"][0]["slots"]["main"]["*"]
|
||||
except Exception as e:
|
||||
print(f" 获取页面 '{title}' 时出错: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def extract_runeword_names(wikitext):
|
||||
"""从 wikitext 中提取所有三级标题作为符文之语名称"""
|
||||
if not wikitext:
|
||||
return []
|
||||
return re.findall(r'===\s*(.+?)\s*===', wikitext)
|
||||
|
||||
|
||||
def split_cn_en(full_name):
|
||||
"""
|
||||
分割 "中文名 英文名" 格式的标题。
|
||||
英文名可能包含多个单词(如 "Flickering Flame", "King's Grace"),
|
||||
所以需要从尾部向前匹配连续的英文单词序列。
|
||||
"""
|
||||
match = re.search(r'((?:[A-Za-z][A-Za-z\']*(?:\'[A-Za-z]+)*)(?:\s+[A-Za-z][A-Za-z\']*(?:\'[A-Za-z]+)*)*)\s*$', full_name)
|
||||
if match:
|
||||
en_name = match.group(1)
|
||||
cn_part = full_name[:match.start()].strip()
|
||||
if cn_part:
|
||||
return cn_part, en_name
|
||||
# 纯英文或无法分割
|
||||
return None, full_name
|
||||
|
||||
|
||||
def build_lookup(names):
|
||||
"""
|
||||
构建查找表:英文原名 -> 完整中英文名称
|
||||
标题格式为 "中文名 英文名",英文名可含多个单词
|
||||
"""
|
||||
lookup = {}
|
||||
for full_name in names:
|
||||
cn_name, en_name = split_cn_en(full_name)
|
||||
lookup[en_name] = full_name
|
||||
return lookup
|
||||
|
||||
|
||||
def main():
|
||||
REFERENCES_DIR.mkdir(exist_ok=True)
|
||||
|
||||
all_lookup = {}
|
||||
page_stats = {}
|
||||
|
||||
for page_title in RUNEWORD_PAGES:
|
||||
print(f"拉取: {page_title} ...", end=" ")
|
||||
wikitext = get_page_content(page_title)
|
||||
names = extract_runeword_names(wikitext)
|
||||
lookup = build_lookup(names)
|
||||
all_lookup.update(lookup)
|
||||
page_stats[page_title] = len(names)
|
||||
print(f"找到 {len(names)} 个符文之语")
|
||||
|
||||
# 保存 JSON
|
||||
with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(all_lookup, f, ensure_ascii=False, indent=2)
|
||||
|
||||
total = len(all_lookup)
|
||||
print(f"\n总计 {total} 个符文之语名称已保存到 {OUTPUT_FILE}")
|
||||
for page, count in page_stats.items():
|
||||
print(f" {page}: {count}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue