69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
// 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, "@._ ")
|
|
}
|