Skip to content

Commit 69cb863

Browse files
committed
libpod/container_internal: Split locale at the first dot, etc.
We're going to feed this into Go's BCP 47 language parser. Language tags have the form [1]: language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse] and locales have the form [2]: [language[_territory][.codeset][@modifier]] The modifier is useful for collation, but Go's language-based API [3] does not provide a way for us to supply it. This code converts our locale to a BCP 47 language by stripping the dot and later and replacing the first underscore, if any, with a hyphen. This will avoid errors like [4]: WARN[0000] failed to parse language "en_US.UTF-8": language: tag is not well-formed when feeding language.Parse(...). [1]: https://tools.ietf.org/html/bcp47#section-2.1 [2]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02 [3]: golang/go#25340 [4]: #2494 Signed-off-by: W. Trevor King <[email protected]>
1 parent 40f7843 commit 69cb863

File tree

2 files changed

+61
-7
lines changed

2 files changed

+61
-7
lines changed

libpod/container_internal.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ const (
3434
)
3535

3636
var (
37-
// localeToLanguage maps from locale values to language tags.
38-
localeToLanguage = map[string]string{
37+
// localeToLanguageMap maps from locale values to language tags.
38+
localeToLanguageMap = map[string]string{
3939
"": "und-u-va-posix",
4040
"c": "und-u-va-posix",
4141
"posix": "und-u-va-posix",
@@ -1281,6 +1281,16 @@ func (c *Container) saveSpec(spec *spec.Spec) error {
12811281
return nil
12821282
}
12831283

1284+
// localeToLanguage translates POSIX locale strings to BCP 47 language tags.
1285+
func localeToLanguage(locale string) string {
1286+
locale = strings.Replace(strings.SplitN(locale, ".", 2)[0], "_", "-", 1)
1287+
langString, ok := localeToLanguageMap[strings.ToLower(locale)]
1288+
if !ok {
1289+
langString = locale
1290+
}
1291+
return langString
1292+
}
1293+
12841294
// Warning: precreate hooks may alter 'config' in place.
12851295
func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (extensionStageHooks map[string][]spec.Hook, err error) {
12861296
var locale string
@@ -1296,11 +1306,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten
12961306
}
12971307
}
12981308

1299-
langString, ok := localeToLanguage[strings.ToLower(locale)]
1300-
if !ok {
1301-
langString = locale
1302-
}
1303-
1309+
langString := localeToLanguage(locale)
13041310
lang, err := language.Parse(langString)
13051311
if err != nil {
13061312
logrus.Warnf("failed to parse language %q: %s", langString, err)

libpod/container_internal_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,54 @@ import (
1717
// hookPath is the path to an example hook executable.
1818
var hookPath string
1919

20+
func TestLocaleToLanguage(t *testing.T) {
21+
for _, testCase := range []struct {
22+
locale string
23+
language string
24+
}{
25+
{
26+
locale: "",
27+
language: "und-u-va-posix",
28+
},
29+
{
30+
locale: "C",
31+
language: "und-u-va-posix",
32+
},
33+
{
34+
locale: "POSIX",
35+
language: "und-u-va-posix",
36+
},
37+
{
38+
locale: "c",
39+
language: "und-u-va-posix",
40+
},
41+
{
42+
locale: "en",
43+
language: "en",
44+
},
45+
{
46+
locale: "en_US",
47+
language: "en-US",
48+
},
49+
{
50+
locale: "en.UTF-8",
51+
language: "en",
52+
},
53+
{
54+
locale: "en_US.UTF-8",
55+
language: "en-US",
56+
},
57+
{
58+
locale: "does-not-exist",
59+
language: "does-not-exist",
60+
},
61+
} {
62+
t.Run(testCase.locale, func(t *testing.T) {
63+
assert.Equal(t, testCase.language, localeToLanguage(testCase.locale))
64+
})
65+
}
66+
}
67+
2068
func TestPostDeleteHooks(t *testing.T) {
2169
ctx := context.Background()
2270
dir, err := ioutil.TempDir("", "libpod_test_")

0 commit comments

Comments
 (0)