Coverage for language_utils.py: 78%

9 statements  

« 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. 

3 

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""" 

10 

11import langcodes 

12 

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} 

34 

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} 

50 

51 

52def to_language(lang_code: str) -> str: 

53 """Return a human-readable language name for an ISO 639-1 or Kokoro code. 

54 

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