validate general.language in config and use effective language for model compatibility
This commit is contained in:
@@ -2039,3 +2039,100 @@ func TestConfig_EffectiveLanguage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfig_Validate_GeneralLanguage(t *testing.T) {
|
||||||
|
baseConfig := func() *Config {
|
||||||
|
return &Config{
|
||||||
|
Recording: RecordingConfig{
|
||||||
|
SampleRate: 16000,
|
||||||
|
Channels: 1,
|
||||||
|
Format: "s16",
|
||||||
|
BufferSize: 8192,
|
||||||
|
ChannelBufferSize: 30,
|
||||||
|
Timeout: time.Minute,
|
||||||
|
},
|
||||||
|
Transcription: TranscriptionConfig{
|
||||||
|
Provider: "openai",
|
||||||
|
APIKey: "test-key",
|
||||||
|
Model: "whisper-1",
|
||||||
|
},
|
||||||
|
Injection: InjectionConfig{
|
||||||
|
Backends: []string{"clipboard"},
|
||||||
|
YdotoolTimeout: 5 * time.Second,
|
||||||
|
WtypeTimeout: 5 * time.Second,
|
||||||
|
ClipboardTimeout: 3 * time.Second,
|
||||||
|
},
|
||||||
|
Notifications: NotificationsConfig{Type: "log"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("valid general.language passes validation", func(t *testing.T) {
|
||||||
|
config := baseConfig()
|
||||||
|
config.General.Language = "es"
|
||||||
|
|
||||||
|
err := config.Validate()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Validate() should pass with valid general.language: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("general.language validated against model", func(t *testing.T) {
|
||||||
|
config := baseConfig()
|
||||||
|
config.General.Language = "es"
|
||||||
|
config.Transcription.Provider = "groq-transcription"
|
||||||
|
config.Transcription.Model = "distil-whisper-large-v3-en" // english-only model
|
||||||
|
config.Transcription.APIKey = "gsk-test-key"
|
||||||
|
|
||||||
|
err := config.Validate()
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Validate() should fail when general.language incompatible with model")
|
||||||
|
}
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "does not support Spanish") {
|
||||||
|
t.Errorf("error should mention Spanish, got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("transcription.language override validated against model", func(t *testing.T) {
|
||||||
|
config := baseConfig()
|
||||||
|
config.General.Language = "en" // compatible
|
||||||
|
config.Transcription.Language = "es" // override with incompatible
|
||||||
|
config.Transcription.Provider = "groq-transcription"
|
||||||
|
config.Transcription.Model = "distil-whisper-large-v3-en" // english-only model
|
||||||
|
config.Transcription.APIKey = "gsk-test-key"
|
||||||
|
|
||||||
|
err := config.Validate()
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Validate() should fail when transcription.language override is incompatible")
|
||||||
|
}
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "does not support Spanish") {
|
||||||
|
t.Errorf("error should mention Spanish, got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("valid override with compatible language", func(t *testing.T) {
|
||||||
|
config := baseConfig()
|
||||||
|
config.General.Language = "es" // would be incompatible
|
||||||
|
config.Transcription.Language = "en" // override with compatible
|
||||||
|
config.Transcription.Provider = "groq-transcription"
|
||||||
|
config.Transcription.Model = "distil-whisper-large-v3-en" // english-only model
|
||||||
|
config.Transcription.APIKey = "gsk-test-key"
|
||||||
|
|
||||||
|
err := config.Validate()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Validate() should pass when transcription.language override is compatible: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("auto language always passes", func(t *testing.T) {
|
||||||
|
config := baseConfig()
|
||||||
|
config.General.Language = "" // auto
|
||||||
|
config.Transcription.Provider = "groq-transcription"
|
||||||
|
config.Transcription.Model = "distil-whisper-large-v3-en" // english-only model
|
||||||
|
config.Transcription.APIKey = "gsk-test-key"
|
||||||
|
|
||||||
|
err := config.Validate()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Validate() should pass with auto language: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,9 +85,12 @@ func (c *Config) Validate() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate language code - warn if not recognized but don't error
|
// validate language codes - warn if not recognized but don't error
|
||||||
|
if c.General.Language != "" && !language.IsValidCode(c.General.Language) {
|
||||||
|
log.Printf("warning: unrecognized language code '%s' in general.language, will be passed as-is to provider", c.General.Language)
|
||||||
|
}
|
||||||
if c.Transcription.Language != "" && !language.IsValidCode(c.Transcription.Language) {
|
if c.Transcription.Language != "" && !language.IsValidCode(c.Transcription.Language) {
|
||||||
log.Printf("warning: unrecognized language code '%s', will be passed as-is to provider", c.Transcription.Language)
|
log.Printf("warning: unrecognized language code '%s' in transcription.language, will be passed as-is to provider", c.Transcription.Language)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate model exists
|
// validate model exists
|
||||||
@@ -111,8 +114,9 @@ func (c *Config) Validate() error {
|
|||||||
return fmt.Errorf("invalid model for %s: %s (available: %s)", c.Transcription.Provider, c.Transcription.Model, strings.Join(modelIDs, ", "))
|
return fmt.Errorf("invalid model for %s: %s (available: %s)", c.Transcription.Provider, c.Transcription.Model, strings.Join(modelIDs, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate language-model compatibility
|
// validate language-model compatibility using effective language (transcription overrides general)
|
||||||
if err := ValidateModelLanguageCompatibility(registryName, c.Transcription.Model, c.Transcription.Language); err != nil {
|
effectiveLanguage := c.resolveEffectiveLanguage()
|
||||||
|
if err := ValidateModelLanguageCompatibility(registryName, c.Transcription.Model, effectiveLanguage); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -596,3 +596,16 @@ Started: Sun Feb 1 12:22:47 AM CET 2026
|
|||||||
- Added TestValidateModelLanguage_ErrorFormat test verifying error includes model name, docs URL, and language
|
- Added TestValidateModelLanguage_ErrorFormat test verifying error includes model name, docs URL, and language
|
||||||
- Updated test expectations in config_test.go for new error format
|
- Updated test expectations in config_test.go for new error format
|
||||||
- All tests passing, typecheck passes
|
- All tests passing, typecheck passes
|
||||||
|
|
||||||
|
### Task 11: Update config validation for general language
|
||||||
|
- Updated `internal/config/validate.go` to validate `general.language` if set
|
||||||
|
- Added warning for unrecognized `general.language` code (warns but doesn't error)
|
||||||
|
- Changed language-model compatibility check to use effective language (`resolveEffectiveLanguage()`)
|
||||||
|
- Effective language = transcription.language override, or general.language if no override
|
||||||
|
- Added comprehensive tests in config_test.go:
|
||||||
|
- `TestConfig_Validate_GeneralLanguage/valid_general.language_passes_validation`
|
||||||
|
- `TestConfig_Validate_GeneralLanguage/general.language_validated_against_model`
|
||||||
|
- `TestConfig_Validate_GeneralLanguage/transcription.language_override_validated_against_model`
|
||||||
|
- `TestConfig_Validate_GeneralLanguage/valid_override_with_compatible_language`
|
||||||
|
- `TestConfig_Validate_GeneralLanguage/auto_language_always_passes`
|
||||||
|
- All tests passing, typecheck passes
|
||||||
+1
-1
@@ -184,7 +184,7 @@
|
|||||||
"Config with general.language='invalid' warns but doesn't hard fail",
|
"Config with general.language='invalid' warns but doesn't hard fail",
|
||||||
"Typecheck passes"
|
"Typecheck passes"
|
||||||
],
|
],
|
||||||
"passes": false
|
"passes": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Update README and docs for general language setting",
|
"title": "Update README and docs for general language setting",
|
||||||
|
|||||||
Reference in New Issue
Block a user