Files

50 lines
1.4 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package speech
import (
"os"
"sort"
"strings"
)
// LocaleVoices prefers the current locale's exact dialect, then its base
// language. An unknown locale retains the catalog, matching quick settings.
func LocaleVoices(voices []Voice) []Voice {
locale := ""
for _, key := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} {
if value := os.Getenv(key); value != "" {
locale = value
break
}
}
normalize := func(value string) string {
value = strings.Split(strings.Split(value, ".")[0], "@")[0]
return strings.ToLower(strings.ReplaceAll(value, "_", "-"))
}
locale = normalize(locale)
if locale == "" || locale == "c" || locale == "posix" {
locale = "en-us"
}
for _, language := range []string{locale, strings.SplitN(locale, "-", 2)[0]} {
var selected []Voice
for _, voice := range voices {
if normalize(voice.Language) == language {
selected = append(selected, voice)
}
}
if len(selected) == 0 {
continue
}
// A '+' in the synthesis name denotes an eSpeak variant; Variant
// is gender metadata and cannot identify the unmodified voice.
sort.SliceStable(selected, func(i, j int) bool {
return !strings.Contains(selected[i].Name, "+") && strings.Contains(selected[j].Name, "+")
})
return selected
}
return voices
}