Skip to content

Commit

Permalink
Improve JSON format #2
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaysoro committed Sep 9, 2022
1 parent a7b9d46 commit 891ff94
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 14 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,21 @@ Load bundles for locales to support.
err := i18n.LoadBundle(discordgo.French, "path/to/your/file.json")
```

The bundle format must respect the schema below; note [text/template](http://golang.org/pkg/text/template/) syntax is used to inject variables. Since the library lets you define multiple translations per key, an array is required.
The bundle format must respect the schema below; note [text/template](http://golang.org/pkg/text/template/) syntax is used to inject variables.
For a given key, value can be string, string array to randomize translations or even deep structures to group translations as wanted. In case any other type is provided, it is mapped to string automatically.

```json
{
"hello_world": ["Hello world!"],
"hello_anyone": ["Hello {{ .anyone }}!"],
"hello_world": "Hello world!",
"hello_anyone": "Hello {{ .anyone }}!",
"image": "https://media2.giphy.com/media/Ju7l5y9osyymQ/giphy.gif",
"bye": ["See you", "Bye!"],
"image": ["https://media2.giphy.com/media/Ju7l5y9osyymQ/giphy.gif"]
"command": {
"scream": {
"dog": "Waf waf! 🐶",
"cat": "Miaw! 🐱"
}
}
}
```

Expand Down Expand Up @@ -81,6 +88,10 @@ fmt.Println(bye)
keyDoesNotExist := i18n.Get(discordgo.EnglishUS, "key_does_not_exist")
fmt.Println(keyDoesNotExist)
// Prints "key_does_not_exist"

dog := i18n.Get(discordgo.EnglishUS, "command.scream.dog")
fmt.Println(dog)
// Prints "Waf waf! 🐶"
```

Here an example of how it can work with interactions.
Expand All @@ -94,7 +105,7 @@ func HelloWorld(s *discordgo.Session, i *discordgo.InteractionCreate) {
Embeds: []*discordgo.MessageEmbed{
{
Title: i18n.Get(i.Locale, "hello_world"),
Description: i18n.Get(i.Locale, "hello_anyone", i18n.Vars{"anyone": i.Member.Nick}),
Description: i18n.Get(i.Locale, "hello_anyone", i18n.Vars{"anyone": i.Member.Nick}),
Image: &discordgo.MessageEmbedImage{URL: i18n.Get(i.Locale, "image")},
},
},
Expand Down
33 changes: 31 additions & 2 deletions translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package discordgoi18n
import (
"bytes"
"encoding/json"
"fmt"
"math/rand"
"os"
"strings"
Expand All @@ -17,6 +18,7 @@ const (
defaultLocale = discordgo.EnglishUS
leftDelim = "{{"
rightDelim = "}}"
keyDelim = "."
executionPolicy = "missingkey=error"
)

Expand Down Expand Up @@ -45,12 +47,14 @@ func (translator *translatorImpl) LoadBundle(locale discordgo.Locale, path strin
return err
}

var newBundle bundle
err = json.Unmarshal(buf, &newBundle)
var jsonContent map[string]interface{}
err = json.Unmarshal(buf, &jsonContent)
if err != nil {
return err
}

newBundle := translator.mapBundleStructure(jsonContent)

log.Debug().Msgf("Bundle '%s' loaded with '%s' content", locale, path)
translator.loadedBundles[path] = newBundle
translator.translations[locale] = newBundle
Expand Down Expand Up @@ -106,3 +110,28 @@ func (translator *translatorImpl) Get(locale discordgo.Locale, key string, varia

return raw
}

func (translator *translatorImpl) mapBundleStructure(jsonContent map[string]interface{}) bundle {
bundle := make(map[string][]string)
for key, content := range jsonContent {
switch v := content.(type) {
case string:
bundle[key] = []string{v}
case []interface{}:
values := make([]string, 0)
for _, value := range v {
values = append(values, fmt.Sprintf("%v", value))
}
bundle[key] = values
case map[string]interface{}:
subValues := translator.mapBundleStructure(v)
for subKey, subValue := range subValues {
bundle[fmt.Sprintf("%s%s%s", key, keyDelim, subKey)] = subValue
}
default:
bundle[key] = []string{fmt.Sprintf("%v", v)}
}
}

return bundle
}
88 changes: 81 additions & 7 deletions translator_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package discordgoi18n

import (
"fmt"
"os"
"reflect"
"testing"

"github.com/bwmarrin/discordgo"
Expand Down Expand Up @@ -36,13 +38,12 @@ const (
`

badContent = `
{
"content": {
"not": {
"ok": "test"
}
}
}
[
"content",
"not",
"ok",
"test"
]
`
)

Expand Down Expand Up @@ -159,3 +160,76 @@ func TestGet(t *testing.T) {
// Bad case, value is well structured but cannot inject value
assert.Equal(t, "this is a {{ .Test }}", translatorTest.Get(discordgo.Dutch, "hi", Vars{}))
}

func TestMapBundleStructure(t *testing.T) {
setUp()
defer tearDown()

tests := []struct {
Description string
Input map[string]interface{}
ExpectedBundle bundle
}{
{
Description: "Nil Input",
Input: nil,
ExpectedBundle: make(bundle),
},
{
Description: "Empty Input",
Input: make(map[string]interface{}),
ExpectedBundle: make(bundle),
},
{
Description: "Simple string Input",
Input: map[string]interface{}{
"simple": "translation",
"variabilized": "translation {{ .translation }}",
},
ExpectedBundle: bundle{
"simple": []string{"translation"},
"variabilized": []string{"translation {{ .translation }}"},
},
},
{
Description: "Different types handled",
Input: map[string]interface{}{
"pi": 3.14,
"answer_to_ultimate_question_of_life": 42,
"some_prime_numbers": []interface{}{2, "3", 5.0, 7},
},
ExpectedBundle: bundle{
"pi": []string{"3.14"},
"answer_to_ultimate_question_of_life": []string{"42"},
"some_prime_numbers": []string{"2", "3", "5", "7"},
},
},
{
Description: "Deep structure",
Input: map[string]interface{}{
"command": map[string]interface{}{
"salutation": map[string]interface{}{
"hi": "Hello there!",
"bye": []interface{}{"Bye {{ .anyone }}!", "See u {{ .anyone }}"},
},
"speak": map[string]interface{}{
"random": []interface{}{"love to talk", "how are u?", "u're so interesting"},
},
},
"panic": "I've panicked!",
},
ExpectedBundle: bundle{
"command.salutation.hi": []string{"Hello there!"},
"command.salutation.bye": []string{"Bye {{ .anyone }}!", "See u {{ .anyone }}"},
"command.speak.random": []string{"love to talk", "how are u?", "u're so interesting"},
"panic": []string{"I've panicked!"},
},
},
}

for _, test := range tests {
bundle := translatorTest.mapBundleStructure(test.Input)
assert.True(t, reflect.DeepEqual(test.ExpectedBundle, bundle),
fmt.Sprintf("%s:\n\nExpecting: %v\n\nGot : %v", test.Description, test.ExpectedBundle, bundle))
}
}

0 comments on commit 891ff94

Please sign in to comment.