diff --git a/internal/language/language.go b/internal/language/language.go index a821a4f..eeaed99 100644 --- a/internal/language/language.go +++ b/internal/language/language.go @@ -118,3 +118,49 @@ func IsValidCode(code string) bool { _, ok := codeIndex[code] return ok } + +// ToProviderFormat converts a canonical language code to the format expected by a specific provider. +// Each provider may have different expectations: +// - whisper-cpp: uses standard codes like 'en', 'auto' for auto-detect +// - openai: uses standard codes like 'en', empty string for auto-detect +// - groq: same as openai (OpenAI-compatible) +// - mistral: same as openai (OpenAI-compatible) +// - deepgram: uses locale codes like 'en-US', 'es' for Spanish +// - elevenlabs: uses standard codes or full names depending on API version +func ToProviderFormat(code string, providerName string) string { + // handle auto-detect (empty code) + if code == "" { + switch providerName { + case "whisper-cpp": + return "auto" + default: + // most providers use empty string or omit the parameter + return "" + } + } + + switch providerName { + case "deepgram": + // deepgram prefers locale codes for some languages + return toDeepgramFormat(code) + default: + // whisper-cpp, openai, groq, mistral, elevenlabs use standard codes + return code + } +} + +// toDeepgramFormat maps standard codes to Deepgram's preferred format +func toDeepgramFormat(code string) string { + // deepgram uses locale codes for English variants, standard for most others + deepgramMappings := map[string]string{ + "en": "en-US", + "es": "es", // Spanish uses base code + "pt": "pt-BR", // Portuguese defaults to Brazilian + "zh": "zh-CN", // Chinese defaults to Simplified + } + + if mapped, ok := deepgramMappings[code]; ok { + return mapped + } + return code +} diff --git a/internal/language/language_test.go b/internal/language/language_test.go index 7eda70e..2f21a4b 100644 --- a/internal/language/language_test.go +++ b/internal/language/language_test.go @@ -117,3 +117,49 @@ func TestAuto(t *testing.T) { t.Errorf("Auto.Name = %q, want 'Auto-detect'", Auto.Name) } } + +func TestToProviderFormat(t *testing.T) { + tests := []struct { + code string + provider string + want string + }{ + // whisper-cpp + {"en", "whisper-cpp", "en"}, + {"es", "whisper-cpp", "es"}, + {"", "whisper-cpp", "auto"}, + + // openai + {"en", "openai", "en"}, + {"", "openai", ""}, + + // groq (openai-compatible) + {"en", "groq", "en"}, + {"", "groq", ""}, + + // mistral (openai-compatible) + {"en", "mistral", "en"}, + {"", "mistral", ""}, + + // deepgram (uses locale codes) + {"en", "deepgram", "en-US"}, + {"es", "deepgram", "es"}, + {"pt", "deepgram", "pt-BR"}, + {"zh", "deepgram", "zh-CN"}, + {"fr", "deepgram", "fr"}, // no special mapping, passthrough + {"", "deepgram", ""}, + + // elevenlabs + {"en", "elevenlabs", "en"}, + {"", "elevenlabs", ""}, + } + + for _, tt := range tests { + t.Run(tt.code+"_"+tt.provider, func(t *testing.T) { + got := ToProviderFormat(tt.code, tt.provider) + if got != tt.want { + t.Errorf("ToProviderFormat(%q, %q) = %q, want %q", tt.code, tt.provider, got, tt.want) + } + }) + } +} diff --git a/progress.txt b/progress.txt index ddd2bd0..f54700e 100644 --- a/progress.txt +++ b/progress.txt @@ -9,3 +9,10 @@ Started: Sun Feb 1 12:22:47 AM CET 2026 - Implemented FromCode, List, Codes, AllLanguageCodes, IsValidCode - Full 57 language list from OpenAI Whisper - All tests passing, typecheck passes + +### Task 2: Add language list and provider-specific mappings +- Added `ToProviderFormat(code string, providerName string) string` function +- Handles auto-detect: whisper-cpp uses "auto", others use "" +- Deepgram locale mappings: en->en-US, pt->pt-BR, zh->zh-CN +- Added comprehensive test coverage for all provider formats +- All tests passing, typecheck passes diff --git a/tasks/prd.jsonc b/tasks/prd.jsonc index 81e600a..79a19f7 100644 --- a/tasks/prd.jsonc +++ b/tasks/prd.jsonc @@ -29,11 +29,11 @@ "passes": true }, { - "title": "Add language list and provider-specific mappings", +"title": "Add language list and provider-specific mappings", "steps": [ "Update internal/language/language.go with full language list", "Master language list derived from OpenAI Whisper's 57 supported languages (source: https://platform.openai.com/docs/guides/speech-to-text#supported-languages)", - "Add all 57 languages: af/Afrikaans, ar/Arabic/العربية, hy/Armenian/Հայdelays, az/Azerbaijani/Azərbaycan, be/Belarusian/Беларуская, bs/Bosnian/Bosanski, bg/Bulgarian/Български, ca/Catalan/Català, zh/Chinese/中文, hr/Croatian/Hrvatski, cs/Czech/Čeština, da/Danish/Dansk, nl/Dutch/Nederlands, en/English, et/Estonian/Eesti, fi/Finnish/Suomi, fr/French/Français, gl/Galician/Galego, de/German/Deutsch, el/Greek/Ελληνικά, he/Hebrew/עברית, hi/Hindi/हिन्दी, hu/Hungarian/Magyar, is/Icelandic/Íslenska, id/Indonesian/Bahasa Indonesia, it/Italian/Italiano, ja/Japanese/日本語, kn/Kannada/ಕನ್ನಡ, kk/Kazakh/Қазақ, ko/Korean/한국어, lv/Latvian/Latviešu, lt/Lithuanian/Lietuvių, mk/Macedonian/Македонски, ms/Malay/Bahasa Melayu, mr/Marathi/मराठी, mi/Maori/Māori, ne/Nepali/नेपाली, no/Norwegian/Norsk, fa/Persian/فارسی, pl/Polish/Polski, pt/Portuguese/Português, ro/Romanian/Română, ru/Russian/Русский, sr/Serbian/Српски, sk/Slovak/Slovenčina, sl/Slovenian/Slovenščina, es/Spanish/Español, sw/Swahili/Kiswahili, sv/Swedish/Svenska, tl/Tagalog, ta/Tamil/தமிழ், th/Thai/ไทย, tr/Turkish/Türkçe, uk/Ukrainian/Українська, ur/Urdu/اردو, vi/Vietnamese/Tiếng Việt, cy/Welsh/Cymraeg", + "Add all 57 languages: af/Afrikaans, ar/Arabic/العربية, hy/Armenian/Հdelays, az/Azerbaijani/Azərbaycan, be/Belarusian/Беларуская, bs/Bosnian/Bosanski, bg/Bulgarian/Български, ca/Catalan/Català, zh/Chinese/中文, hr/Croatian/Hrvatski, cs/Czech/Čeština, da/Danish/Dansk, nl/Dutch/Nederlands, en/English, et/Estonian/Eesti, fi/Finnish/Suomi, fr/French/Français, gl/Galician/Galego, de/German/Deutsch, el/Greek/Ελληνικά, he/Hebrew/עברית, hi/Hindi/हिन्दी, hu/Hungarian/Magyar, is/Icelandic/Íslenska, id/Indonesian/Bahasa Indonesia, it/Italian/Italiano, ja/Japanese/日本語, kn/Kannada/ಕನ್ನಡ, kk/Kazakh/Қазақ, ko/Korean/한국어, lv/Latvian/Latviešu, lt/Lithuanian/Lietuvių, mk/Macedonian/Македонски, ms/Malay/Bahasa Melayu, mr/Marathi/मराठी, mi/Maori/Māori, ne/Nepali/नेपाली, no/Norwegian/Norsk, fa/Persian/فارسی, pl/Polish/Polski, pt/Portuguese/Português, ro/Romanian/Română, ru/Russian/Русский, sr/Serbian/Српски, sk/Slovak/Slovenčina, sl/Slovenian/Slovenščina, es/Spanish/Español, sw/Swahili/Kiswahili, sv/Swedish/Svenska, tl/Tagalog, ta/Tamil/தமிழ், th/Thai/ไทย, tr/Turkish/Türkçe, uk/Ukrainian/Українська, ur/Urdu/اردو, vi/Vietnamese/Tiếng Việt, cy/Welsh/Cymraeg", "Implement ToProviderFormat(code string, providerName string) string - maps our code to provider-specific format", "Provider mappings: whisper-cpp uses 'en'/'auto', some APIs use 'english', Deepgram uses 'en-US'", "Each provider can handle Auto ('') differently via ToProviderFormat" @@ -47,7 +47,7 @@ "ToProviderFormat('', 'openai') returns '' or appropriate auto value", "Typecheck passes" ], - "passes": false + "passes": true }, { "title": "Create Model type with full metadata",