Skip to content

Commit

Permalink
Fix case sensitivity with message keys (#358)
Browse files Browse the repository at this point in the history
Fixes #357
  • Loading branch information
nicksnyder authored Feb 2, 2025
1 parent 711fb20 commit 4333871
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 50 deletions.
30 changes: 22 additions & 8 deletions i18n/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ var everythingMessage = MustNewMessage(map[string]string{
"few": "few translation",
"many": "many translation",
"other": "other translation",
"leftDelim": "<<",
"rightDelim": ">>",
})

func TestConcurrentAccess(t *testing.T) {
Expand Down Expand Up @@ -113,7 +115,9 @@ func TestJSON(t *testing.T) {
"two": "two translation",
"few": "few translation",
"many": "many translation",
"other": "other translation"
"other": "other translation",
"leftDelim": "<<",
"rightDelim": ">>"
}
}`), "en-US.json")

Expand Down Expand Up @@ -143,6 +147,8 @@ everything:
few: few translation
many: many translation
other: other translation
leftDelim: "<<"
rightDelim: ">>"
`), "en-US.yaml")

expectMessage(t, bundle, language.AmericanEnglish, "simple", simpleMessage)
Expand Down Expand Up @@ -171,6 +177,8 @@ everything:
few: few translation
many: many translation
other: other translation
leftDelim: "<<"
rightDelmin: ">>"
garbage: something
description: translation
Expand Down Expand Up @@ -212,6 +220,8 @@ two = "two translation"
few = "few translation"
many = "many translation"
other = "other translation"
leftDelim = "<<"
rightDelim = ">>"
`), "en-US.toml")

expectMessage(t, bundle, language.AmericanEnglish, "simple", simpleMessage)
Expand Down Expand Up @@ -241,9 +251,7 @@ func TestV1Format(t *testing.T) {
`), "en-US.json")

expectMessage(t, bundle, language.AmericanEnglish, "simple", simpleMessage)
e := *everythingMessage
e.Description = ""
expectMessage(t, bundle, language.AmericanEnglish, "everything", &e)
expectMessage(t, bundle, language.AmericanEnglish, "everything", newV1EverythingMessage())
}

func TestV1FlatFormat(t *testing.T) {
Expand All @@ -264,15 +272,21 @@ func TestV1FlatFormat(t *testing.T) {
`), "en-US.json")

expectMessage(t, bundle, language.AmericanEnglish, "simple", simpleMessage)
e := *everythingMessage
e.Description = ""
expectMessage(t, bundle, language.AmericanEnglish, "everything", &e)
expectMessage(t, bundle, language.AmericanEnglish, "everything", newV1EverythingMessage())
}

func expectMessage(t *testing.T, bundle *Bundle, tag language.Tag, messageID string, message *Message) {
expected := NewMessageTemplate(message)
actual := bundle.messageTemplates[tag][messageID]
if !reflect.DeepEqual(actual, expected) {
t.Errorf("bundle.MessageTemplates[%q][%q] = %#v; want %#v", tag, messageID, actual, expected)
t.Errorf("bundle.MessageTemplates[%q][%q]\ngot %#v\nwant %#v", tag, messageID, actual, expected)
}
}

func newV1EverythingMessage() *Message {
e := *everythingMessage
e.Description = ""
e.LeftDelim = ""
e.RightDelim = ""
return &e
}
67 changes: 25 additions & 42 deletions i18n/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ var reservedKeys = map[string]struct{}{
}

func isReserved(key string, val any) bool {
if _, ok := reservedKeys[key]; ok {
lk := strings.ToLower(key)
if _, ok := reservedKeys[lk]; ok {
if key == "translation" {
return true
}
Expand All @@ -214,62 +215,44 @@ func isMessage(v interface{}) (bool, error) {
case nil, string:
return true, nil
case map[string]interface{}:
reservedKeyCount := 0
for key := range reservedKeys {
val, ok := data[key]
if ok && isReserved(key, val) {
reservedKeyCount++
reservedKeys := make([]string, 0, len(reservedKeys))
unreservedKeys := make([]string, 0, len(data))
for k, v := range data {
if isReserved(k, v) {
reservedKeys = append(reservedKeys, k)
} else {
unreservedKeys = append(unreservedKeys, k)
}
}
if reservedKeyCount == 0 {
return false, nil
}
if len(data) > reservedKeyCount {
reservedKeys := make([]string, 0, reservedKeyCount)
unreservedKeys := make([]string, 0, len(data)-reservedKeyCount)
for k, v := range data {
if isReserved(k, v) {
reservedKeys = append(reservedKeys, k)
} else {
unreservedKeys = append(unreservedKeys, k)
}
}
hasReservedKeys := len(reservedKeys) > 0
if hasReservedKeys && len(unreservedKeys) > 0 {
return false, &mixedKeysError{
reservedKeys: reservedKeys,
unreservedKeys: unreservedKeys,
}
}
return true, nil
return hasReservedKeys, nil
case map[interface{}]interface{}:
reservedKeyCount := 0
for key := range reservedKeys {
val, ok := data[key]
if ok && isReserved(key, val) {
reservedKeyCount++
reservedKeys := make([]string, 0, len(reservedKeys))
unreservedKeys := make([]string, 0, len(data))
for key, v := range data {
k, ok := key.(string)
if !ok {
unreservedKeys = append(unreservedKeys, fmt.Sprintf("%+v", key))
} else if isReserved(k, v) {
reservedKeys = append(reservedKeys, k)
} else {
unreservedKeys = append(unreservedKeys, k)
}
}
if reservedKeyCount == 0 {
return false, nil
}
if len(data) > reservedKeyCount {
reservedKeys := make([]string, 0, reservedKeyCount)
unreservedKeys := make([]string, 0, len(data)-reservedKeyCount)
for key, v := range data {
k, ok := key.(string)
if !ok {
unreservedKeys = append(unreservedKeys, fmt.Sprintf("%+v", key))
} else if isReserved(k, v) {
reservedKeys = append(reservedKeys, k)
} else {
unreservedKeys = append(unreservedKeys, k)
}
}
hasReservedKeys := len(reservedKeys) > 0
if hasReservedKeys && len(unreservedKeys) > 0 {
return false, &mixedKeysError{
reservedKeys: reservedKeys,
unreservedKeys: unreservedKeys,
}
}
return true, nil
return hasReservedKeys, nil
}
return false, nil
}
Expand Down

0 comments on commit 4333871

Please sign in to comment.