// 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 }