Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #771 from gobuffalo/localized-views
Browse files Browse the repository at this point in the history
Implement #723 - Localized views
  • Loading branch information
markbates authored Nov 27, 2017
2 parents 6bb737f + 0f0171b commit ba44ab7
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 4 deletions.
23 changes: 20 additions & 3 deletions middleware/i18n/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package i18n

import (
"log"
"strings"

"github.com/gobuffalo/buffalo"
"github.com/gobuffalo/packr"
Expand All @@ -21,7 +22,7 @@ type LanguageFinder func(*Translator, buffalo.Context) []string
type Translator struct {
// Box - where are the files?
Box packr.Box
// DefaultLanguage - default is "en-US"
// DefaultLanguage - default is passed as a parameter on New.
DefaultLanguage string
// CookieName - name of the cookie to find the desired language.
// default is "lang"
Expand Down Expand Up @@ -157,10 +158,26 @@ func defaultLanguageFinder(t *Translator, c buffalo.Context) []string {
// try to get the language from a header:
acceptLang := r.Header.Get("Accept-Language")
if acceptLang != "" {
langs = append(langs, acceptLang)
langs = append(langs, parseAcceptLanguage(acceptLang)...)
}

// try to get the language from the session:
// finally set the default app language as fallback
langs = append(langs, t.DefaultLanguage)
return langs
}

// Inspired from https://siongui.github.io/2015/02/22/go-parse-accept-language/
// Parse an Accept-Language string to get usable lang values for i18n system
func parseAcceptLanguage(acptLang string) []string {
var lqs []string

langQStrs := strings.Split(acptLang, ",")
for _, langQStr := range langQStrs {
trimedLangQStr := strings.Trim(langQStr, " ")

langQ := strings.Split(trimedLangQStr, ";")
lq := langQ[0]
lqs = append(lqs, lq)
}
return lqs
}
36 changes: 36 additions & 0 deletions middleware/i18n/i18n_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ func app() *buffalo.App {
c.Set("Users", usersList)
return c.Render(200, r.HTML("format.html"))
})
app.GET("/localized", func(c buffalo.Context) error {
return c.Render(200, r.HTML("localized_view.html"))
})
// Disable i18n middleware
noI18n := func(c buffalo.Context) error {
return c.Render(200, r.HTML("localized_view.html"))
}
app.Middleware.Skip(t.Middleware(), noI18n)
app.GET("/localized-disabled", noI18n)
return app
}

Expand Down Expand Up @@ -101,3 +110,30 @@ func Test_i18n_format_fr(t *testing.T) {
res := req.Get()
r.Equal("Bonjour Mark !\n\n\t* M. Mark Bates\n\n\t* M. Chuck Berry\n", res.Body.String())
}

func Test_i18n_Localized_View(t *testing.T) {
r := require.New(t)

w := willie.New(app())
// Test with complex Accept-Language
req := w.Request("/localized")
req.Headers["Accept-Language"] = "en-UK,en-US;q=0.5"
res := req.Get()
r.Equal("Hello!\n", res.Body.String())

// Test priority
req.Headers["Accept-Language"] = "fr,en-US"
res = req.Get()
r.Equal("Bonjour !\n", res.Body.String())

// Test fallback
req.Headers["Accept-Language"] = "ru"
res = req.Get()
r.Equal("Default\n", res.Body.String())

// Test i18n disabled
req = w.Request("/localized-disabled")
req.Headers["Accept-Language"] = "en-UK,en-US;q=0.5"
res = req.Get()
r.Equal("Default\n", res.Body.String())
}
1 change: 1 addition & 0 deletions middleware/i18n/templates/localized_view.en-uk.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello!
1 change: 1 addition & 0 deletions middleware/i18n/templates/localized_view.fr.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bonjour !
1 change: 1 addition & 0 deletions middleware/i18n/templates/localized_view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Default
27 changes: 26 additions & 1 deletion render/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,32 @@ func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
}
}

source, err := s.TemplatesBox.MustBytes(name)
// Try to use localized version
templateName := name
if languages, ok := data["languages"].([]string); ok {
ll := len(languages)
if ll > 0 {
// Default language is the last in the list
defaultLanguage := languages[ll-1]
ext := filepath.Ext(name)
rawName := strings.TrimSuffix(name, ext)

for _, l := range languages {
var candidateName string
if l == defaultLanguage {
break
}
candidateName = rawName + "." + strings.ToLower(l) + ext
if s.TemplatesBox.Has(candidateName) {
// Replace name with the existing suffixed version
templateName = candidateName
break
}
}
}
}

source, err := s.TemplatesBox.MustBytes(templateName)
if err != nil {
return "", err
}
Expand Down

0 comments on commit ba44ab7

Please sign in to comment.