新增学习资料生成器模块(learner),从权威库生成多维日语学习资料: - 拼音/假名/汉字/熟字训四类索引,带拼音↔假名↔汉字交叉跳转 - 逐字音训分类(KANJIDIC2 精确查表 + 启发式回退 + 排序键) - 音变标注体系:浊化(連濁)、半浊化、促音变(促音便)、连声(れんじょう) 独立配色 + 合并逻辑 + 音变规律说明 - 显式标注表:rendaku_marks(连用形连浊)、renjou_marks(连声) - 每索引独立例词数配置(jlearn.toml + --config) - HTML 单页应用 + 静态 HTML + PDF(playwright) 清洗工具增强: - 拼音校验器(pinyin_checker)集成到 jclean - 多音字拼音校正、ます形サ変動詞转原型 数据: - 权威库补充连声词(反応/天皇/陰陽/観音/因縁/三位/輪廻/安穏) - KANJIDIC2 音训分类表、拼音校正字典 整理 .gitignore:忽略生成产物(output/study_materials)、词典数据库、 任务运行日志、备份文件
66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
"""拼音校验模块测试。"""
|
||
from pl_japanese.cleaner.pinyin_checker import (
|
||
check_line, check_segment, is_valid_syllable, _split_into_syllables,
|
||
)
|
||
|
||
|
||
class TestSyllableValidity:
|
||
def test_valid_syllables(self):
|
||
for py in ['xue', 'jue', 'que', 'lv', 'nv', 'yun', 'zhi', 'shi',
|
||
'bao', 'shang', 'hai', 'xian', 'er', 'n', 'ng']:
|
||
assert is_valid_syllable(py), f'{py} 应为合法音节'
|
||
|
||
def test_invalid_syllables(self):
|
||
for py in ['bap', 'ijao', 'qina', 'hue', 'xyz', 'blah']:
|
||
assert not is_valid_syllable(py), f'{py} 应为非法音节'
|
||
|
||
|
||
class TestSegmentCheck:
|
||
def test_illegal_syllable_flagged(self):
|
||
# 保 标成 bap(非法音节)
|
||
problem = check_segment('保', 'bap')
|
||
assert problem is not None
|
||
assert 'bap' in problem
|
||
assert 'bao' in problem # 给出正确建议
|
||
|
||
def test_wrong_reading_flagged(self):
|
||
# 保 标成 xian(合法音节但非该字读音)
|
||
problem = check_segment('保', 'xian')
|
||
assert problem is not None
|
||
assert 'bao' in problem
|
||
|
||
def test_correct_reading_passes(self):
|
||
assert check_segment('保', 'bao') is None
|
||
assert check_segment('中', 'zhong') is None
|
||
|
||
def test_non_hanzi_skipped(self):
|
||
# 假名/字母分段拼音为空,跳过
|
||
assert check_segment('める', '') is None
|
||
assert check_segment('Q', '') is None
|
||
|
||
|
||
class TestLineCheck:
|
||
def test_bad_line_flagged(self):
|
||
line = '上|海|保|険:シャン|ハイ|ほ|けん:shang|hai|bap|xian'
|
||
problems = check_line(line)
|
||
assert len(problems) == 1
|
||
assert 'bap' in problems[0]
|
||
|
||
def test_good_lines_pass(self):
|
||
for good in [
|
||
'学|生:がく|せい:xue|sheng',
|
||
'中|国:ちゅう|ごく:zhong|guo',
|
||
'決|める:き|める:jue|',
|
||
'血|液:けつ|えき:xue|ye',
|
||
]:
|
||
assert check_line(good) == [], f'{good} 不应有告警'
|
||
|
||
|
||
class TestSyllableSplit:
|
||
def test_connected_pinyin_splits(self):
|
||
assert _split_into_syllables('jinri') == ['jin', 'ri']
|
||
assert _split_into_syllables('nvjiang') == ['nv', 'jiang']
|
||
|
||
def test_unsplittable_returns_none(self):
|
||
assert _split_into_syllables('bapxian') is None
|