Last active
March 10, 2017 11:20
-
-
Save u007/fda1dd4f92f424242732b5f7a82d5fc3 to your computer and use it in GitHub Desktop.
buffalo i18n locale
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in actions/app.go | |
/* | |
directory structure | |
app/ | |
locales/en-us.yaml | |
assets/js/locales/ | |
middleware/ | |
actions/tools | |
*/ | |
import( | |
///... | |
ownmiddleware "project/middleware" | |
"project/actions/tools" | |
) | |
func App() *buffalo.App { | |
///... | |
translation.SetupLocale("en-US") | |
app.Use(ownmiddleware.LanguageMiddleware) | |
//... | |
return app; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# in locales/en-us.yaml | |
# https://github.com/nicksnyder/go-i18n/blob/64786dc4f56b1cceffc2ce90a7f512d9ab70bba2/goi18n/testdata/en-us.yaml | |
- id: Hi | |
translation: Hello | |
- id: Another name | |
translation: Something else |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- in views/index.html --> | |
{{T "Hi"}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// middleware/language.go | |
package middleware | |
import ( | |
"project/actions/tools" | |
"fmt" | |
"github.com/gobuffalo/buffalo" | |
) | |
func LanguageMiddleware(next buffalo.Handler) buffalo.Handler { | |
return func(c buffalo.Context) error { | |
locale := c.Request().Header.Get("Accept-Language") | |
c.Logger().Info(fmt.Sprintf("locale: %s", locale)) | |
translation.LoadTranslation(locale) | |
return next(c) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in actions/tools/translation.go | |
package translation | |
import ( | |
"encoding/json" | |
"fmt" | |
"github.com/gobuffalo/velvet" | |
"github.com/nicksnyder/go-i18n/i18n" | |
"github.com/nicksnyder/go-i18n/i18n/bundle" | |
"gopkg.in/yaml.v2" | |
"io/ioutil" | |
"log" | |
"os" | |
"reflect" | |
"strings" | |
"time" | |
) | |
var DefaultLocale = "en-US" | |
func SetupLocale(defaultLocale string) { | |
DefaultLocale = defaultLocale | |
LoadLocaleFile("en-us") | |
} | |
// this load translation and convert it to i18n-react js file | |
func LoadLocaleFile(locale string) { | |
path := "./locales/" + locale + ".yaml" | |
dest_json := "./assets/js/locales/" + locale + ".jsx" | |
bundle := bundle.New() | |
bundle.MustLoadTranslationFile(path) | |
if 1 == 2 && !FileChanged(path, dest_json) { | |
return | |
} | |
data, err := ioutil.ReadFile(path) | |
if err != nil { | |
log.Fatalf("Unable to load yaml") | |
} | |
log.Printf("yaml: %#v\n", string(data)) | |
// m := make(map[string][]interface{}) | |
var m []map[string]string | |
// m := make(map[interface{}]interface{}) | |
err = yaml.Unmarshal((data), &m) | |
if err != nil { | |
log.Fatalf("error: %v", err) | |
} | |
// log.Printf(fmt.Sprintf("yaml: %#v\n", m)) | |
jsonMap := make(map[string]interface{}) | |
// translations := bundle.Translations() | |
// // log.Printf("translations: %#v", translations["en-us"]) | |
// r, _ := regexp.Compile("p([a-z]+)ch") | |
for c := range m { | |
name := m[c]["id"] | |
names := strings.Split(name, ".") | |
value := strings.Replace(m[c]["translation"], "{{.", "{", -1) | |
value = strings.Replace(value, "}}", "}", -1) | |
if len(names) > 1 { | |
name = names[0] | |
} | |
if _, ok := jsonMap[name]; ok { | |
// has existing key | |
if _, ok := jsonMap[name].(string); ok { | |
//replace by nested array, or value after it | |
jsonMap[name] = NestedValue(names[1:], value) | |
log.Printf("was string, result: %#v\n", jsonMap[name]) | |
} else { | |
// source := make(map[string]interface{}) | |
rv := reflect.ValueOf(jsonMap[name]) | |
if rv.Kind() == reflect.Map { | |
source, ok := jsonMap[name].(map[string]interface{}) | |
if !ok { | |
log.Fatalf("unable to convert to map[string]interface{} of %#v", jsonMap) | |
} | |
log.Printf("b4---%#v\n", jsonMap) | |
jsonMap[name] = JoinNested(source, NestedValue(names[1:], value)) | |
} else { | |
log.Fatalf("Unsupported type: %#v", rv.Kind()) | |
} | |
} | |
} else { | |
if len(names) > 1 { | |
jsonMap[name] = NestedValue(names[1:], value) | |
log.Printf("first nested: %#v\n", jsonMap) | |
} else { | |
jsonMap[name] = value | |
} | |
} | |
} | |
jsonResult, err := json.Marshal(jsonMap) | |
if err != nil { | |
log.Panicf("Unable to create json from yaml") | |
} | |
jsContent := `import T from 'i18n-react'; | |
T.setTexts(` + string(jsonResult) + `) | |
export default T` | |
// jsonResult, err = json.MarshalIndent(jsonResult, "", " ") | |
// if err != nil { | |
// log.Panicf("Unable to indent json") | |
// } | |
err = ioutil.WriteFile(dest_json, []byte(jsContent), 0644) | |
if err != nil { | |
log.Panicf("Unable to write %s", dest_json) | |
} | |
log.Printf("Written to %s\n", dest_json) | |
} | |
func NestedValue(names []string, value string) map[string]interface{} { | |
res := make(map[string]interface{}) | |
if len(names) > 1 { | |
res[names[0]] = NestedValue(names[1:], value) | |
} else { | |
res[names[0]] = value | |
} | |
log.Printf("nestedvalue: %#v = %#v\n", names, res) | |
return res | |
} | |
func JoinNested(existing map[string]interface{}, values map[string]interface{}) map[string]interface{} { | |
fmt.Printf("joining nested %#v\n", existing) | |
fmt.Printf("joining nested2 %#v\n", values) | |
res := make(map[string]interface{}) | |
for i := range existing { | |
res[i] = existing[i] | |
} | |
for i := range values { | |
if _, ok := res[i].(string); ok { | |
//replace by nested array, or value after it | |
res[i] = values[i] | |
} else { | |
name := i | |
value := values[i] | |
if _, ok := res[name]; ok { | |
// has existing key | |
if _, ok := res[name].(string); ok { | |
//replace by nested array, or value after it | |
res[name] = value | |
} else { | |
rv := reflect.ValueOf(res[name]) | |
rv2 := reflect.ValueOf(value) | |
if rv.Kind() == reflect.Map && rv2.Kind() == reflect.Map { | |
source, ok := res[name].(map[string]interface{}) | |
if !ok { | |
log.Fatalf("unable to convert to map[string]interface{} of %#v", res) | |
} | |
destination, ok := value.(map[string]interface{}) | |
res[name] = JoinNested(source, destination) | |
} else { | |
log.Fatalf("Unsupported type: %#v and %#v", rv.Kind(), rv2.Kind()) | |
} | |
// source := make(map[string]interface{}) | |
// rv := reflect.ValueOf(res[name]) | |
// if rv.Kind() == reflect.Map { | |
// for _, key := range rv.MapKeys() { | |
// log.Printf("rv-nested-key: %#v", key) | |
// source[key.String()] = rv.MapIndex(key) | |
// } | |
// } | |
// destination := make(map[string]interface{}) | |
// rv = reflect.ValueOf(value) | |
// if rv.Kind() == reflect.Map { | |
// for _, key := range rv.MapKeys() { | |
// log.Printf("rv-destination-nested-key: %#v", key) | |
// destination[key.String()] = rv.MapIndex(key) | |
// } | |
// } | |
} | |
} else { | |
res[name] = value | |
} | |
} | |
} | |
fmt.Printf("result nested: %#v\n", res) | |
return res | |
} | |
func FileChanged(source string, destination string) bool { | |
file1Info, err := os.Stat(source) | |
if err != nil { | |
log.Panicf("%s is not a file. \n", source) | |
} | |
file2Info, err := os.Stat(destination) | |
if err != nil && os.IsNotExist(err) { | |
return true | |
} else if err != nil { | |
log.Panicf("%s is not a file %s", destination, err.Error()) | |
} | |
modTime1 := file1Info.ModTime() | |
modTime2 := file2Info.ModTime() | |
log.Printf("source: %#v, destination: %#v", modTime1, modTime2) | |
diff := modTime1.Sub(modTime2) | |
if diff > (time.Duration(0) * time.Second) { | |
log.Printf("Locale changed %s\n", source) | |
return true | |
} | |
return false | |
} | |
func LoadTranslation(locale string) { | |
err := velvet.Helpers.Add("T", func(name string, a ...interface{}) string { | |
T, _ := i18n.Tfunc(locale, DefaultLocale) | |
return T(name, a...) | |
}) | |
if err != nil { | |
msg := fmt.Sprintf("unable to add velvet helper: %#v\n", err.Error()) | |
log.Fatalf(msg) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment