// 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, "@._ ") }