xdg/locale/locale.go

69 lines
1.7 KiB
Go
Raw Normal View History

2024-04-26 16:51:01 -06:00
// Package locale defines a Locale type that represents a POSIX locale value, as
// required by desktop-entry-spec.
package locale
import "fmt"
import "strings"
type localeError string
func (err localeError) Error () string { return string(err) }
const (
// ErrUnexpectedRune indicates an unexpected rune was encountered while
// parsing a locale string.
ErrUnexpectedRune = localeError("unexpected rune")
// ErrLangEmpty indicates that a lang value was not specified.
ErrLangEmpty = localeError("lang empty")
)
// Locale represents a POSIX locale value.
type Locale struct {
Lang string
Country string
Encoding string
Modifier string
}
// String returns the string representation of the Locale. Unspecified values
// are left out.
func (locale Locale) String () string {
str := locale.Lang
if locale.Country != "" {
str = fmt.Sprint(str, "_", locale.Country)
}
if locale.Encoding != "" {
str = fmt.Sprint(str, ".", locale.Encoding)
}
if locale.Modifier != "" {
str = fmt.Sprint(str, "@", locale.Modifier)
}
return str
}
// Parse parses a formatted locale string and returns the corresponding Locale.
func Parse (value string) (Locale, error) {
locale := Locale { }
value, locale.Modifier, _ = strings.Cut(value, "@")
value, locale.Encoding, _ = strings.Cut(value, ".")
value, locale.Country, _ = strings.Cut(value, "_")
locale.Lang = value
if hasIllegalRunes(locale.Lang) ||
hasIllegalRunes(locale.Country) ||
hasIllegalRunes(locale.Encoding) ||
hasIllegalRunes(locale.Modifier) {
return Locale { }, ErrUnexpectedRune
}
if locale.Lang == "" {
return Locale { }, ErrLangEmpty
}
return locale, nil
}
func hasIllegalRunes (value string) bool {
return strings.ContainsAny(value, "@._ ")
}