Skip to content

和文摩斯码字典与转换设计

目标

本阶段为现有转换器增加和文摩斯码支持,同时把字典模块统一为足以支持后续文字体系、但不过度配置化的结构。

完成后:

  • internationalwabun 使用相同的字典模块接口。
  • 和文编码接受片假名、平假名、半角片假名、浊音、半浊音、数字及支持的和文符号。
  • 和文解码输出易读的组合片假名,例如 カ゛ 显示为
  • 转换器和字母表组件从同一注册表解析字典。
  • 字典选择与页面语言解耦;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 页面。

字典模块契约

字典模块使用一个轻量、统一的结构:

ts
type AlphabetMap = Readonly<Record<string, string>>;

type AlphabetDefinition = {
  dict: AlphabetMap;
  normalize?: (text: string) => string;
  format?: (text: string) => string;
};
  • dict 是规范字符到摩斯码的唯一映射,也是表格展示和反向解码的唯一数据源。
  • normalize 在编码和文本校验前运行,将用户输入转换为字典规范字符。
  • format 在解码完成后运行,将规范字符序列转换为易读文本。

normalizeformat 不是互逆函数。输入的书写形式可能在编码时丢失,例如平假名 和片假名 都规范化为 カ゛,解码后统一显示为

实现应满足以下稳定性:

text
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 数字 09,其码值与规范表中的数字一致。
  • 浊点 和半浊点
  • 长音
  • 规范表列出的和文标点及括号。

平假名、组合浊音、半角片假名、输入别名不得加入 dict,否则相同摩斯码会在反向字典中互相覆盖。

normalize

规范化按固定顺序执行:

  1. 只对明确支持的兼容输入做定向规范化:对半角片假名片段使用 NFKC,将全角数字转换为 ASCII 数字,并统一 ASCII/全角括号。不得对整段输入执行 NFKC,以免把带圈片假名、带圈数字等未声明别名转换为合法字符。
  2. 将平假名转换为片假名。
  3. 将组合浊音和半浊音分解为基础片假名加规范符号,例如 转为 カ゛ 转为 ハ゜
  4. 将小假名 ァィゥェォッャュョヮヵヶ 分别转换为 アイウエオツヤユヨワカケ,因为和文码表不为其提供独立码值。
  5. 将 NFKC 产生的 ASCII () 转回 dict 使用的规范全角括号

normalize 不得删除不支持的字符。未识别字符必须保留,使校验逻辑能够向用户报告。

例如 不属于本阶段支持的输入别名,规范化后仍应保持原字符并被校验报告。

本阶段不把 自动映射为 或段落符号,也不接受汉字数字别名。两者都包含额外语义取舍,应在有明确需求时单独增加。

format

format 只组合合法的片假名与浊点、半浊点序列:

text
カ゛ -> ガ
ハ゜ -> パ

它不把片假名恢复为平假名,也不恢复半角或小假名。无法合法组合的独立符号保持原样,避免静默丢失解码信息。

注册与解析

注册表仅包含明确的字典 ID:

ts
const alphabets = {
  international,
  wabun,
};

组件通过 internationalwabun 显式选择字典。页面 locale 不参与字典推断,因此日文页面可以安全使用任意已注册字典。

未知字典 ID 延续当前行为,回退到 international。测试需要覆盖该行为。

数据流

文本编码:

text
原始输入
-> 字典 normalize(没有则保持原值)
-> 对规范化结果执行字符校验
-> 使用 dict 编码

摩斯解码:

text
摩斯输入
-> 使用 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 testnpm run docs:build,确保转换逻辑及 Markdown 组件均可构建。

后续扩展原则

新增字典时只需提供 dict;存在输入书写变体时增加 normalize,需要改善规范解码字符的可读性时增加 format。不得按页面语言自动选择字典,也不得通过向 dict 添加别名来实现输入兼容。