Skip to content

Add experimental German (lang_code=d) scaffolding for community voices#326

Open
isaaclins wants to merge 2 commits into
hexgrad:mainfrom
isaaclins:feat/german-lang-scaffolding
Open

Add experimental German (lang_code=d) scaffolding for community voices#326
isaaclins wants to merge 2 commits into
hexgrad:mainfrom
isaaclins:feat/german-lang-scaffolding

Conversation

@isaaclins

Copy link
Copy Markdown

Summary

Addresses community demand in #290 by adding first-class German pipeline support without claiming to ship official trained German weights:

  • lang_code='d' with espeak-ng German G2P (de)
  • kokoro.de_text.normalize_german() for EUR amounts, decimal units (kWh, etc.), and common abbreviations
  • docs/german.md — how to use community .pt voice packs (Hugging Face)
  • examples/german_tts.py demo
  • Unit tests for normalization

This does not replace custom training data for an official hexgrad German release; it unblocks integrators using community checkpoints (e.g. Tundragoon/Kokoro-German, ONNX German voices) with consistent normalization and docs.

Test plan

  • normalize_german unit cases (EUR, kWh, zzgl.)
  • Manual: KPipeline(lang_code='d') + community .pt on a machine with espeak-ng

Closes #290 only in the sense of integration scaffolding; funding/training remains separate.

Adds espeak-based German G2P, text normalization for EUR/units/abbrevs,
docs for community voice packs, and a small demo script — toward hexgrad#290.
Copilot AI review requested due to automatic review settings May 26, 2026 11:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR introduces experimental German support to the Kokoro pipeline by adding a German language alias/code, a German text normalization helper, and accompanying docs/examples/tests.

Changes:

  • Add lang_code='d' (German) and aliases (de, de-de, german) to KPipeline.
  • Introduce kokoro.de_text.normalize_german() for German abbreviations and numeric/unit normalization, invoked during pipeline processing for German.
  • Add German usage documentation, a runnable example, and unit tests for normalization.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/test_de_text.py Adds unit tests for German normalization behaviors (EUR, decimal units, abbreviations).
kokoro/pipeline.py Adds German aliases and runs German normalization when lang_code == 'd'.
kokoro/de_text.py Implements German normalization for abbreviations, EUR amounts, and decimal+unit constructs.
examples/german_tts.py Adds a CLI demo script for German TTS using community German voice packs.
docs/german.md Documents experimental German support and how to use community voices.
README.md Documents the new German lang_code='d' option.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread kokoro/de_text.py
Comment on lines +39 to +65
out = text
for src, dst in _ABBREV.items():
out = re.sub(rf"\b{re.escape(src)}", dst, out, flags=re.IGNORECASE)

def _eur_sub(m: re.Match[str]) -> str:
whole = m.group(1).replace(".", "")
cents = m.group(2)
return f"{whole} Euro {cents}"

out = _EUR_RE.sub(_eur_sub, out)

def _dec_unit_sub(m: re.Match[str]) -> str:
whole, frac, unit = m.group(1), m.group(2), m.group(3)
unit_word = {
"kwh": "Kilowattstunden",
"kw": "Kilowatt",
"mah": "Milliamperestunden",
"ma": "Milliampere",
"g": "Gramm",
"kg": "Kilogramm",
"mb": "Megabyte",
"gb": "Gigabyte",
}.get(unit.lower(), unit)
return f"{whole} Komma {frac} {unit_word}"

out = _DECIMAL_UNIT_RE.sub(_dec_unit_sub, out)
return out
Comment thread kokoro/de_text.py Outdated
Comment on lines +40 to +41
for src, dst in _ABBREV.items():
out = re.sub(rf"\b{re.escape(src)}", dst, out, flags=re.IGNORECASE)
Comment thread kokoro/pipeline.py
Comment on lines +389 to +391
if self.lang_code == 'd':
from .de_text import normalize_german
graphemes = normalize_german(graphemes)
Comment thread tests/test_de_text.py
Comment on lines +15 to +17
def test_abbreviation(self):
out = normalize_german("zzgl. Versand, ca. 3 Tage.")
self.assertIn("zuzüglich", out)
Apply decimal+unit expansion before abbreviations, remove units from
the abbreviation table, use token lookarounds, and sort keys longest-first.
Add regression test for max. vs ma overlap.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Donation/funding for german language

2 participants