Coverage for language_utils.py: 78%
9 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
1"""
2Language-code utilities shared across all apps and wrappers.
4Internal standard: ISO 639-1 codes (e.g. "en", "es", "fr") as returned by
5Whisper. Engine-specific codes are mapped to/from ISO 639-1 via the
6dictionaries below. Human-readable language names are resolved through the
7``langcodes`` library so the mapping stays in sync with the IANA language
8subtag registry.
9"""
11import langcodes
13# Maps Whisper / ISO 639-1 language codes to Kokoro TTS single-letter codes.
14# Kokoro codes:
15# 'a' => American English (en-US) 'b' => British English (en-GB)
16# 'e' => Spanish (es) 'f' => French (fr)
17# 'g' => German (de) 'h' => Hindi (hi)
18# 'i' => Italian (it) 'j' => Japanese (ja)
19# 'k' => Korean (ko) 'p' => Brazilian Portuguese (pt-BR)
20# 'r' => Russian (ru) 'z' => Mandarin Chinese (zh)
21WHISPER_TO_KOKORO: dict[str, str] = {
22 "en": "a", # American English (default; use "b" for British)
23 "es": "e",
24 "fr": "f",
25 "de": "g",
26 "hi": "h",
27 "it": "i",
28 "ja": "j",
29 "ko": "k",
30 "pt": "p",
31 "ru": "r",
32 "zh": "z",
33}
35# Reverse mapping: Kokoro single-letter codes → BCP 47 / ISO 639-1 tags.
36KOKORO_TO_ISO: dict[str, str] = {
37 "a": "en-US",
38 "b": "en-GB",
39 "e": "es",
40 "f": "fr",
41 "g": "de",
42 "h": "hi",
43 "i": "it",
44 "j": "ja",
45 "k": "ko",
46 "p": "pt-BR",
47 "r": "ru",
48 "z": "zh",
49}
52def to_language(lang_code: str) -> str:
53 """Return a human-readable language name for an ISO 639-1 or Kokoro code.
55 Kokoro single-letter codes (e.g. ``"a"``, ``"e"``) are first translated to
56 their BCP 47 equivalents via :data:`KOKORO_TO_ISO`; ISO codes are passed
57 directly to ``langcodes``. Returns a descriptive ``"Unknown language"``
58 string for codes that ``langcodes`` cannot resolve, and falls back to the
59 original *lang_code* if an unexpected exception occurs.
60 """
61 iso = KOKORO_TO_ISO.get(lang_code.lower(), lang_code)
62 try:
63 return langcodes.get(iso).display_name()
64 except Exception:
65 return lang_code