50 lines
1.4 KiB
Go
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
|
|
}
|