adding-normalizer
remsky/Kokoro-FastAPI/.claude/skills/adding-normalizer/SKILL.md
Adding a language normalizer to Kokoro-FastAPI: the Normalizer contract, registry, and test expectations. Use when adding or changing text normalization under api/src/services/text_processing/normalization/.
Skill5.5k starsChanged 30 days ago
What's in it
- Adding a language normalizer
- Where things live
- Adding one
- Testing
--- name: adding-normalizer description: "Adding a language normalizer to Kokoro-FastAPI: the Normalizer contract, registry, and test expectations. Use when adding or changing text normalization under api/src/services/text_processing/normalization/." --- Read [AGENTS.md](../../../AGENTS.md) and [CONTRIBUTING.md](../../../CONTRIBUTING.md) first, house rules live there. # Adding a language normalizer Text normalization (numbers, money, time, URLs, etc. spelled out before phonemization) is per language. Only English is implemented; other languages skip normalization and rely on the phonemizer. ## Where things live `api/src/services/text_processing/normalization/`: - `base.py`: `Normalizer`, the contract. `pass_order()` is the pass order, `normalize()` runs it. The language-neutral passes (quotes, CJK punctuation, whitespace) are implemented; every other pass is a hook that returns its input unchanged until overridden. Override `pass_order()` if a language needs a different order. - `english.py`: `EnglishNormalizer`, the reference implementation. - `english_data.py`: the English tables, TLDs, units, symbol readings, currencies. - `__init__.py`: `LANGUAGES`, the registry. Lang codes come from `lang_codes` on each class. ## Adding one 1. Create `normalization/<language>.py` with a `Normalizer` subclass. Set `lang_codes` to the Kokoro pipeline codes it serves (`p` for Portuguese, `e` for Spanish, etc.). Override the hooks you need, `numbers` first (money is spelled out there too); espeak already reads bare digits, so the value is in currency, time, and units. `num2words` is in the lock and covers cardinals for most languages. 2. Add an instance to `LANGUAGES` in `__init__.py`. 3. Add `api/tests/test_normalizer_<language>.py` with a `CASES` table of `(input, expected)` rows, mirroring `test_normalizer.py`. `test_normalizer_contract.py` runs the never-raises and idempotence properties on every registered language automatically. ## Testing - Keep regexes linear. `test_normalizer_redos.py` shows the flood inputs that have bitten before. - `uv run pytest api/tests/test_normalizer*.py`, then `ruff format .` and `ruff check . --fix` before staging.
More agent context in remsky/Kokoro-FastAPI
5 other files this repository gives its agents.
AGENTS.md
Skill
- api-contrib.claude/skills/api-contrib/SKILL.md
- integration-tests.claude/skills/integration-tests/SKILL.md
- readme-benchmarks.claude/skills/readme-benchmarks/SKILL.md
- web-contrib.claude/skills/web-contrib/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool registry_write, action report. How to connect one.

