jet icon indicating copy to clipboard operation
jet copied to clipboard

Add internationalization support

Open jhsx opened this issue 8 years ago • 12 comments

Support for internationalization can be done by adding a new token type in the lexer, and an evaluator that would call the translator.Translate passed to the template.ExecuteI18n.

Also add a builtin function trans, a type Translator interface{ Translate(v string,i ...interface{}) error }

jhsx avatar May 09 '16 13:05 jhsx

I do internationalization in this way: //in handler or add i18n to global functions m := jet.VarMap{} m.Set("i18n", GetText) //func GetText(locale,str string)string{...} Render(ctx, "public/home", m, data) //ctx=*fasthttp.RequestCtx, I use fasthttp and jet template, so fast ;-) //in template {{i18n(user.Locale,"String to translate")}}

hao1118 avatar Oct 01 '16 04:10 hao1118

Yep, doing it the same way. But it has issues when you're trying to add pluralization because all the libraries out there are using Golang templates under the hood which results in multiple evaluations of template parts. Let's just wait on @jhsx on what he has in mind. :)

annismckenzie avatar Oct 01 '16 05:10 annismckenzie

@hao1118 How do you use jet templating engine to render to fasthttp? fasthttp does not have response.Writer... I tried jetView.Execute(fasthttp.Response.BodyWriter(), nil, c) but that renders only body section as string.

nkev avatar Oct 12 '16 11:10 nkev

@nkev: you can't pass fasthttp.Response.BodyWriter(). For one, it doesn't belong to an instantiated object/context. It also doesn't belong to a request. Looking at the example at https://github.com/valyala/fasthttp#switching-from-nethttp-to-fasthttp (slightly edited for brevity):

  type MyHandler struct {
    foobar string
  }

  // request handler in net/http style, i.e. method bound to MyHandler struct.
  func (h *MyHandler) HandleFastHTTP(ctx *fasthttp.RequestCtx) {
    t, _ := jetView.GetTemplate("some_template.jet")
    t.Execute(ctx, map[string]interface{}, nil)
  }

  // pass bound struct method to fasthttp
  myHandler := &MyHandler{foobar: "foobar"}
  fasthttp.ListenAndServe(":8080", myHandler.HandleFastHTTP)

Let's unpack this: fasthttp's request context already implements the io.Writer interface (see https://github.com/valyala/fasthttp/blob/b43280dfe8ade44056e0179593f8ab30f82a7f47/server.go#L1002) so you can just pass the context to the template's Execute function.

Here's a pointer to the relevant documentation in the wiki: https://github.com/CloudyKit/jet/wiki/Rendering-templates.

If you need help, we're on Gitter: https://gitter.im/CloudyKit/jet. :)

annismckenzie avatar Oct 12 '16 12:10 annismckenzie

@annismckenzie Thank you for taking the time to write the detailed response. Much appreciated!

nkev avatar Oct 12 '16 12:10 nkev

Happy to help!

annismckenzie avatar Oct 12 '16 13:10 annismckenzie

hi @nkev, here is my render function:

https://github.com/hao1118/fasthttp-rendering-jet-template

hao1118 avatar Oct 13 '16 04:10 hao1118

Wow! Including gzip, minification and caching... that's almost a framework, thank you!

nkev avatar Oct 13 '16 04:10 nkev

ya, almost a framework if having session and database modules. I use "github.com/fasthttp-contrib/sessions" and mongodb "gopkg.in/mgo.v2".

func RenderCache should add support for no-gzip clients(unzip gzipped cache data).

hao1118 avatar Oct 13 '16 05:10 hao1118

Guys, while I appreciate you exchanging code and ideas I'd suggest moving this to the Gitter chat room because it has nothing to do with this issue. Agreed? :)

annismckenzie avatar Oct 13 '16 06:10 annismckenzie

@annismckenzie : I just moved the code to my own github page ;-)

hao1118 avatar Oct 13 '16 09:10 hao1118

A bit of an old topic, but I figured that since it has a relevant solution and since it's still open, it still makes sense to add it here.

I'm wondering if the Translator interface can be changed, currently it's:

type Translator interface {
	Msg(key, defaultValue string) string
	Trans(format, defaultFormat string, v ...interface{}) string
}

I'm not sure what Msg() should do, but Trans() is a pretty common API that is shared by go-i18n:

type TranslateFunc func(translationID string, args ...interface{}) string

Currently the translator is accepted, but never used, which sounds like that it's safe to change.

func (t *Template) ExecuteI18N(translator Translator, w io.Writer, variables VarMap, data interface{}) (err error) {

	// ..    
	st.translator = translator
	// ..   		
}

The reason for my request is that I want to influence the function responsible for translation while passing it through to Execute(), e.g.:

// ..

T, err := svc.tr.Tfunc(locale, formal, user.RegionSettings)
if err != nil {
	return false, err
}

err = tpl.ExecuteI18N(T, &writer, nil, nil)
// ..

This way we can keep the templates nice and clean:

{{ T: "my.awesome.key" }}

My current work-around is:

tpl.Execute(html, jet.VarMap{"T": reflect.ValueOf(T)}, nil)

With the template:

{{ T("my.awesome.key") }}

Dynom avatar Oct 21 '20 14:10 Dynom