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,15 +20,27 @@ description: 同步英文 MediaWiki 页面变更到中文翻译文档。当用
|
||||||
|
|
||||||
## 执行步骤
|
## 执行步骤
|
||||||
|
|
||||||
### Step 1: 运行同步脚本
|
### Step 1: 更新符文之语名称参考
|
||||||
|
|
||||||
|
每次同步前先拉取最新的符文之语中文名称:
|
||||||
|
|
||||||
使用 skill 目录下的专用脚本获取变更:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /mnt/d/code/sync-pd2-wiki
|
cd /mnt/d/code/sync-pd2-wiki
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
python .claude/skills/wiki-sync-translate/
|
python .claude/skills/wiki-sync-translate/scripts/fetch_runeword_names.py
|
||||||
scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
```
|
||||||
|
|
||||||
|
此脚本从中文 Wiki 拉取 RWWeapons、RWChests、RWQuivers、RWShields、RWHelms 五个页面,提取所有符文之语的中英文名称,保存到 `references/runeword_names.json`。翻译符文之语相关页面时必须参考此文件。
|
||||||
|
|
||||||
|
### Step 2: 运行同步脚本
|
||||||
|
|
||||||
|
使用 skill 目录下的专用脚本获取变更:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /mnt/d/code/sync-pd2-wiki
|
||||||
|
source venv/bin/activate
|
||||||
|
python .claude/skills/wiki-sync-translate/
|
||||||
|
scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
||||||
```
|
```
|
||||||
|
|
||||||
参数说明:
|
参数说明:
|
||||||
|
|
@ -36,7 +48,7 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
||||||
- `--since`: 起始时间,格式如 `2026-01-02T12:07:05Z`
|
- `--since`: 起始时间,格式如 `2026-01-02T12:07:05Z`
|
||||||
- `--run`: 必须提供此参数才会执行
|
- `--run`: 必须提供此参数才会执行
|
||||||
|
|
||||||
### Step 2: 读取输出文件
|
### Step 3: 读取输出文件
|
||||||
|
|
||||||
脚本会在 `wiki_sync_output/<时间戳>/changed_pages/` 目录下生成:
|
脚本会在 `wiki_sync_output/<时间戳>/changed_pages/` 目录下生成:
|
||||||
|
|
||||||
|
|
@ -50,7 +62,7 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
||||||
**重要:** 只读取 `comparison.json`,不要读取整个 `*.cn.txt` 文件以节省 token。
|
**重要:** 只读取 `comparison.json`,不要读取整个 `*.cn.txt` 文件以节省 token。
|
||||||
|
|
||||||
|
|
||||||
### Step 3: 解析 comparison.json
|
### Step 4: 解析 comparison.json
|
||||||
`comparison.json` 格式:
|
`comparison.json` 格式:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
@ -88,7 +100,7 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
|
||||||
|
|
||||||
**注意:** 如果 `old_line` 和 `new_line` 差距很大但内容相似(如行号从171变到193),这通常意味着中间有其他行被插入或删除,需要仔细检查变更是否真的相关。
|
**注意:** 如果 `old_line` 和 `new_line` 差距很大但内容相似(如行号从171变到193),这通常意味着中间有其他行被插入或删除,需要仔细检查变更是否真的相关。
|
||||||
|
|
||||||
### Step 4: 更新中文文档
|
### Step 5: 更新中文文档
|
||||||
|
|
||||||
**核心原则:行号必须完全一致,使用增量修改减少 token 消耗**
|
**核心原则:行号必须完全一致,使用增量修改减少 token 消耗**
|
||||||
|
|
||||||
|
|
@ -117,7 +129,7 @@ cp wiki_sync_output/<时间戳>/changed_pages/*.cn.txt wiki_sync_output/<时间
|
||||||
// 3. 只读取该行附近内容确认,然后用 Edit 修改
|
// 3. 只读取该行附近内容确认,然后用 Edit 修改
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 5: 输出结果
|
### Step 6: 输出结果
|
||||||
|
|
||||||
更新后的文档位于 `wiki_sync_output/<时间戳>/result_pages/<页面名>.cn.txt`,用户可直接复制到 Wiki。
|
更新后的文档位于 `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` 中的标准术语对照表,确保技能名称、灵气名称和通用术语的翻译一致。优先级高于模型自身的翻译选择。
|
||||||
|
|
||||||
## 翻译术语表
|
## 符文之语名称规则
|
||||||
|
|
||||||
翻译时参考 `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