和文摩斯码字典与转换设计
目标
本阶段为现有转换器增加和文摩斯码支持,同时把字典模块统一为足以支持后续文字体系、但不过度配置化的结构。
完成后:
international与wabun使用相同的字典模块接口。- 和文编码接受片假名、平假名、半角片假名、浊音、半浊音、数字及支持的和文符号。
- 和文解码输出易读的组合片假名,例如
カ゛显示为ガ。 - 转换器和字母表组件从同一注册表解析字典。
- 字典选择与页面语言解耦;
ja不隐式代表wabun。
本阶段范围
- 将
international.ts从平面映射改为统一字典定义。 - 新增
wabun.ts,包含规范字典、编码输入规范化和解码结果格式化。 - 调整通用编码、解码和校验流程以调用字典钩子。
- 调整字母表组件,使其通过统一注册表展示不同字典。
- 完成
docs/ja/alphabet/wabun.md,提供和文表、转换器和必要的规则说明。 - 为字典注册、规范化、格式化、编码、解码和校验增加测试。
延后范围
以下内容留到字母表信息架构的下一阶段:
docs/ja/alphabet/index.md聚合页及/ja/alphabet/的类型介绍内容。- 将当前
docs/ja/alphabet.md的国际摩斯码内容迁移到docs/ja/alphabet/international.md。 - 旧
/ja/alphabet地址到新/ja/alphabet/地址的部署层重定向。 - 其他国家或文字体系的摩斯码页面。
- 罗马字转片假名输入。
本阶段保留现有 docs/ja/alphabet.md,避免在聚合页尚未完成时制造重复的 International 页面。
字典模块契约
字典模块使用一个轻量、统一的结构:
type AlphabetMap = Readonly<Record<string, string>>;
type AlphabetDefinition = {
dict: AlphabetMap;
normalize?: (text: string) => string;
format?: (text: string) => string;
};dict是规范字符到摩斯码的唯一映射,也是表格展示和反向解码的唯一数据源。normalize在编码和文本校验前运行,将用户输入转换为字典规范字符。format在解码完成后运行,将规范字符序列转换为易读文本。
normalize 和 format 不是互逆函数。输入的书写形式可能在编码时丢失,例如平假名 が 和片假名 ガ 都规范化为 カ゛,解码后统一显示为 ガ。
实现应满足以下稳定性:
normalize(normalize(input)) = normalize(input)
normalize(format(canonicalText)) = canonicalText
decode(encode(validInput)) = format(normalize(validInput))International 字典
international.ts 改为 AlphabetDefinition:
- 现有字符和摩斯码迁入
dict,不改变码值。 normalize将英文输入转换为大写。- 不提供
format,解码结果保持规范大写形式。
通用编码器不再调用 char.toUpperCase()。大小写规则属于具体字典,不属于摩斯编码引擎。
不保留 en 别名或 en.ts;注册表只使用明确的 international ID。
Wabun 字典
wabun.ts 自包含以下三部分:
dict
dict 按日本《無線局運用規則》别表第一号保存规范编码单元,包括:
- 基础片假名,包括规范表中的历史假名。
- ASCII 数字
0至9,其码值与规范表中的数字一致。 - 浊点
゛和半浊点゜。 - 长音
ー。 - 规范表列出的和文标点及括号。
平假名、组合浊音、半角片假名、输入别名不得加入 dict,否则相同摩斯码会在反向字典中互相覆盖。
normalize
规范化按固定顺序执行:
- 只对明确支持的兼容输入做定向规范化:对半角片假名片段使用 NFKC,将全角数字转换为 ASCII 数字,并统一 ASCII/全角括号。不得对整段输入执行 NFKC,以免把带圈片假名、带圈数字等未声明别名转换为合法字符。
- 将平假名转换为片假名。
- 将组合浊音和半浊音分解为基础片假名加规范符号,例如
ガ转为カ゛、パ转为ハ゜。 - 将小假名
ァィゥェォッャュョヮヵヶ分别转换为アイウエオツヤユヨワカケ,因为和文码表不为其提供独立码值。 - 将 NFKC 产生的 ASCII
(、)转回dict使用的规范全角括号(、)。
normalize 不得删除不支持的字符。未识别字符必须保留,使校验逻辑能够向用户报告。
例如 ㋐、① 不属于本阶段支持的输入别名,规范化后仍应保持原字符并被校验报告。
本阶段不把 。 自动映射为 、 或段落符号,也不接受汉字数字别名。两者都包含额外语义取舍,应在有明确需求时单独增加。
format
format 只组合合法的片假名与浊点、半浊点序列:
カ゛ -> ガ
ハ゜ -> パ它不把片假名恢复为平假名,也不恢复半角或小假名。无法合法组合的独立符号保持原样,避免静默丢失解码信息。
注册与解析
注册表仅包含明确的字典 ID:
const alphabets = {
international,
wabun,
};组件通过 international 或 wabun 显式选择字典。页面 locale 不参与字典推断,因此日文页面可以安全使用任意已注册字典。
未知字典 ID 延续当前行为,回退到 international。测试需要覆盖该行为。
数据流
文本编码:
原始输入
-> 字典 normalize(没有则保持原值)
-> 对规范化结果执行字符校验
-> 使用 dict 编码摩斯解码:
摩斯输入
-> 使用 dict 的反向映射校验和解码
-> 字典 format(没有则保持原值)
-> 显示文本字符校验与编码必须复用同一规范化入口,避免平假名在实际可编码时仍被报告为非法。摩斯校验只使用 dict 的反向映射,不调用 format。
组件调整
Convertor.vue继续传递字典 ID,具体转换规则由通用编码模块处理。Alphabet.vue不再硬编码International,而是从统一解析函数取得目标定义,并展示其dict。- 表格展示规范编码单元,不展示平假名、组合浊音等输入别名。
wabun.md显式传入alphabet="wabun",不依赖当前页面语言。
页面内容
docs/ja/alphabet/wabun.md 应围绕 モールス符号 和文、モールス信号 日本語 一覧 等意图组织,包含:
- 清晰且唯一的和文页面标题与介绍。
- 和文字典表。
- 使用
wabun字典的双向转换器。 - 平假名可以输入但解码统一输出片假名的说明。
- 浊音、半浊音由两个编码单元发送的说明。
- 支持的数字、长音和标点范围。
- 和文与国际摩斯码不可自动混合解码的说明。
- 包括但不限于 https://laws.e-gov.go.jp/law/325M50080000017 等权威引用
- SEO友好的title/description和各级标题
页面不复制现有 International 完整表,只链接到当前国际摩斯码页面。
错误处理
- 文本经过
normalize后仍不在dict中的字符作为无效字符报告。 - 无效字符不应在严格转换操作中被静默跳过。
- 不在反向字典中的点划 token 继续作为无效摩斯码报告。
- 同一
dict中出现重复摩斯码时,测试应失败,防止反向映射产生不确定输出。
测试策略
单元测试覆盖:
- International 小写输入规范化及大写解码输出。
- 平假名、片假名、半角片假名的和文规范化。
- 浊音、半浊音的分解与易读组合输出。
- 小假名、全角数字和支持标点的规范化。
- 带圈片假名、带圈数字等未声明兼容字符不会被全量 NFKC 意外接受。
- 65 项和文码表逐项与权威期望映射一致,而不只检查数量和抽样码值。
- 不支持字符在规范化后仍可被校验发现。
- 和文编码与解码的代表性样例及多行、空格处理。
- International 与 Wabun 相同点划序列在显式字典下得到不同结果。
- 每个字典内部摩斯码值唯一。
- 未知字典 ID 回退到 International。
- 严格转换遇到无效文本或摩斯 token 时会报告错误,并保留另一侧已有结果。
集成验证包括 npm test 和 npm run docs:build,确保转换逻辑及 Markdown 组件均可构建。
后续扩展原则
新增字典时只需提供 dict;存在输入书写变体时增加 normalize,需要改善规范解码字符的可读性时增加 format。不得按页面语言自动选择字典,也不得通过向 dict 添加别名来实现输入兼容。