Add locale parsing
This commit is contained in:
parent
bd7dbb9228
commit
25edf46db3
68
locale/locale.go
Normal file
68
locale/locale.go
Normal file
@ -0,0 +1,68 @@
|
||||
// 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, "@._ ")
|
||||
}
|
106
locale/locale_test.go
Normal file
106
locale/locale_test.go
Normal file
@ -0,0 +1,106 @@
|
||||
package locale
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestString (test *testing.T) {
|
||||
testCase := func (correct string, locale Locale) {
|
||||
got := locale.String()
|
||||
if got != correct {
|
||||
test.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", correct, got)
|
||||
}
|
||||
}
|
||||
|
||||
testCase("lang_COUNTRY.ENCODING@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
Encoding: "ENCODING",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
testCase("lang.ENCODING@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Encoding: "ENCODING",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
testCase("lang_COUNTRY@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
testCase("lang_COUNTRY.ENCODING", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
Encoding: "ENCODING",
|
||||
})
|
||||
testCase("lang_COUNTRY", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
})
|
||||
testCase("lang.ENCODING", Locale {
|
||||
Lang: "lang",
|
||||
Encoding: "ENCODING",
|
||||
})
|
||||
testCase("lang@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
}
|
||||
|
||||
func TestParse (test *testing.T) {
|
||||
testCase := func (input string, correct Locale) {
|
||||
got, err := Parse(input)
|
||||
if err != nil {
|
||||
test.Fatal(err)
|
||||
}
|
||||
if got != correct {
|
||||
test.Fatalf("expected:\n\t%v\ngot:\n\t%v\n", correct, got)
|
||||
}
|
||||
}
|
||||
|
||||
testCase("lang_COUNTRY.ENCODING@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
Encoding: "ENCODING",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
testCase("lang.ENCODING@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Encoding: "ENCODING",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
testCase("lang_COUNTRY@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
testCase("lang_COUNTRY.ENCODING", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
Encoding: "ENCODING",
|
||||
})
|
||||
testCase("lang_COUNTRY", Locale {
|
||||
Lang: "lang",
|
||||
Country: "COUNTRY",
|
||||
})
|
||||
testCase("lang.ENCODING", Locale {
|
||||
Lang: "lang",
|
||||
Encoding: "ENCODING",
|
||||
})
|
||||
testCase("lang@MODIFIER", Locale {
|
||||
Lang: "lang",
|
||||
Modifier: "MODIFIER",
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseErr (test *testing.T) {
|
||||
testCase := func (input string, correct error) {
|
||||
_, err := Parse(input)
|
||||
if err != correct {
|
||||
test.Fatalf("expected:\n\t%v\ngot:\n\t%v\n", correct, err)
|
||||
}
|
||||
}
|
||||
|
||||
testCase("lang.ENCODING.MODIFIER", ErrUnexpectedRune)
|
||||
testCase("lang@COUNTRY.ENCODING", ErrUnexpectedRune)
|
||||
testCase("lang.@COUNTRY.ENCODING", ErrUnexpectedRune)
|
||||
testCase("_COUNTRY.ENCODING@MODIFIER", ErrLangEmpty)
|
||||
}
|
Loading…
Reference in New Issue
Block a user