Repository: go
Issue: x/text/message: documentation for i18n HTML template example?
Labels: Documentation,NeedsInvestigation

Hi,

I would like to see an example for translated `html/template` with `x/text/message`.

Here's my current attempt with two different calling styles (free to use):

```go
package main

import (
	"bytes"
	"fmt"
	"golang.org/x/text/language"
	"golang.org/x/text/message"
	"golang.org/x/text/message/catalog"
	"html/template"
)

type TrPage struct {
	contents string
	trcat    catalog.Catalog
}

type TrTemplate struct {
	funcs template.FuncMap
	base  string            // Base template as string
	pages map[string]TrPage // Pages which uses base template
}

func New(base string, funcs template.FuncMap) (TrTemplate, error) {
	return TrTemplate{
		base:  `{{define "base"}}` + base + `{{end}}`,
		pages: make(map[string]TrPage),
		funcs: funcs,
	}, nil
}

func (t *TrTemplate) AddPage(name string, template string, translations catalog.Catalog) error {
	tp := TrPage{
		contents: `{{define "content"}}` + template + `{{end}}`,
		trcat:    translations,
	}

	t.pages[name] = tp
	return nil
}

func (t *TrTemplate) Render(templatename string, language language.Tag, data interface{}) (out string, err error) {
	var tmp bytes.Buffer

	tpl := template.New(``)
	tpl.Funcs(t.funcs)
	tpl.Funcs(template.FuncMap{
		// Translate inside template
		`T`: func(s string, a ...interface{}) template.HTML {
			pr := message.NewPrinter(language, message.Catalog(t.pages[templatename].trcat))
			return template.HTML(pr.Sprintf(s, a))
		},
	})

	_, err = tpl.Parse(t.base)
	if err != nil {
		return ``, err
	}

	_, err = tpl.Parse(t.pages[templatename].contents)
	if err != nil {
		return ``, err
	}

	err = tpl.ExecuteTemplate(&tmp, `base`, data)
	if err != nil {
		return ``, err
	}

	return tmp.String(), nil
}

type myBaseStruct struct {
	Title    string // Base title
	Language string
	C        interface{} // per-page content variables
}

type myAboutPageStruct struct {
	User string
	Msg  string
}

func main() {
	// Common functions for templates (for example CSRF generation)
	funcs := template.FuncMap{
	}

	basetpl, err := New(baseHTML, funcs)
	if err != nil {
		panic(err)
	}

	// Translate template to this language
	useLanguage := language.Finnish
	//useLanguage := language.English

	// Front page
	frontpageCat := catalog.NewBuilder(
		catalog.Fallback(useLanguage),
	)

	basetpl.AddPage(`frontpage`, frontpageHTML, frontpageCat)

	// About page
	aboutCat := catalog.NewBuilder(
		catalog.Fallback(useLanguage),
	)

	aboutCat.SetString(language.Finnish, `about_page_user`, `Tietoa käyttäjästä %s`)
	aboutCat.SetString(language.English, `about_page_user`, `Information about user %s`)

	basetpl.AddPage(`about`, aboutHTML, aboutCat)

	printer := message.NewPrinter(useLanguage, message.Catalog(aboutCat))

	out, err := basetpl.Render(`about`, useLanguage, myBaseStruct{
		Title:    `yay title`,
		Language: useLanguage.String(),
		C: myAboutPageStruct{
			// Style 1
			User: `test user`,
			// Style 2
			Msg: printer.Sprintf(`about_page_user`, `test`),
		},
	})
	if err != nil {
		panic(err)
	}

	fmt.Print(out)

}

var baseHTML = `
<!DOCTYPE html>
<html lang="{{.Language}}">
<head>
    <meta charset="UTF-8">
    <title>{{.Title}}</title>
</head>
<body>
This is base
Content:
{{template "content" .C}}

</body>
</html>
`

var aboutHTML = `
<div>
    <!-- Style 1 -->
    {{T "about_page_user" "{{.User}}" }}

    <!-- Style 2 -->
    {{.Msg}}
</div>
`

var frontpageHTML = `
<div>
    This is frontpage
</div>
`
```

Which calling style is recommended or is there third option? 

Style 1 also doesn't evaluate `{{.User}}` to `test user` (I don't know how).

I would like to see style 1 to be used. 

Also the parser for `html/template` is hidden as `internal` so you can't build nice automated translated token gatherer script for these kind of tasks to find all `T` calling functions and dump those to a translation file. Are there plans to open it up?

I would also like to see example for when you have to add some HTML to a translation such as:

    someCatalog.SetString(language.Finnish, `about_page_user`, `Tietoa käyttäjästä %s`)

and `%s` is for example `<a href="/foo">{{.User}}</a>`.