Files
build-web-application-with-…/en/eBook/10.3.md
2014-11-16 20:34:47 -08:00

6.2 KiB

10.3 International sites

The previous section explained how to deal with localized resources, namely by using locale configuration files. So what can we do if we need to deal with multiple localized resources like text translations, times and dates, numbers, etc? This section will address these issues one by one.

Managing multiple locale packages

In the development of an application, often the first thing you need to do is to decide whether or not you want to support more than one language. If you do decide to support multiple languages, you'll need to develop an organizational structure to facilitate the process of adding more languages in the future. One way we can do this is to put all our related locale files together in a config/locales directory, or something of the like. Let's suppose you want to support both Chinese and English. In this case, you'd be placing both the en.json and zh.json locale files into the aforementioned folder. Their contents would probably look something like the following:

# zh.json

{
"zh": {
	"submit": "提交",
	"create": "创建"
	}
}

#en.json

{
"en": {
	"submit": "Submit",
	"create": "Create"
	}
}

We decided to use some 3rd party Go packages to help us internationalize our web applications. In the case of go-i18n ( A more advanced i18n package can be found here ), we first have to register our config/locales directory to load all of our locale files:

Tr := i18n.NewLocale()
Tr.LoadPath("config/locales")

This package is simple to use. We can test that it works like so:

fmt.Println(Tr.Translate("submit"))
//Output "submit"
Tr.SetLocale("zn")
fmt.Println(Tr.Translate("submit"))
//Outputs "递交"

Automatically load local package

We've just described how to automatically load custom language packs. In fact, the go-i18n library comes pre-loaded with a bunch of default formatting information such as time and currency formats. These default configurations can be overridden and customized by users to suit their needs. Consider the following process:

//Load the default configuration files, which are placed below in `go-i18n/locales`

//File should be named zh.json, en-json, en-US.json etc., so we can be continuously support more languages

func (il *IL) loadDefaultTranslations(dirPath string) error {
	dir, err := os.Open(dirPath)
	if err != nil {
		return err
	}
	defer dir.Close()

	names, err := dir.Readdirnames(-1)
	if err != nil {
		return err
	}

	for _, name := range names {
		fullPath := path.Join(dirPath, name)

		fi, err := os.Stat(fullPath)
		if err != nil {
			return err
		}

		if fi.IsDir() {
			if err := il.loadTranslations(fullPath); err != nil {
				return err
			}
		} else if locale := il.matchingLocaleFromFileName(name); locale != "" {
			file, err := os.Open(fullPath)
			if err != nil {
				return err
			}
			defer file.Close()

			if err := il.loadTranslation(file, locale); err != nil {
				return err
			}
		}
	}

	return nil
}

Using the above code to load all of our default translations, we can then use the following code to select and use a locale:

fmt.Println(Tr.Time(time.Now()))
//Output: 2009年1月08日 星期四 20:37:58 CST

fmt.Println(Tr.Time(time.Now(),"long"))
//Output: 2009年1月08日

fmt.Println(Tr.Money(11.11))
//Output: ¥11.11

Template mapfunc

Above, we've presented one way of managing and integrating a number of language packs. Some of the functions we've implemented are based on the logical layer, for example: "Tr.Translate", "Tr.Time", "Tr.Money" and so on. In the logical layer, we can use these functions (after supplying the required parameters) for applying your translations, outputting the results directly to the template layer at render time. What can we do if we want to use these functions directly in the template layer? In case you've forgotten, earlier in the book we mentioned that Go templates support custom template functions. The following code shows how easy mapfunc is to implement:

1 text information

Text information call Tr.Translate to achieve the appropriate information conversion, mapFunc is implemented as follows:

func I18nT(args ...interface{}) string {
	ok := false
	var s string
	if len(args) == 1 {
		s, ok = args[0].(string)
	}
	if !ok {
		s = fmt.Sprint(args...)
	}
	return Tr.Translate(s)
}

Registration function is as follows:

t.Funcs(template.FuncMap{"T": I18nT})

Using the following template:

{{.V.Submit | T}}
  1. The date and time

Date and time to call Tr.Time function to achieve the appropriate time for a change, mapFunc is implemented as follows:

func I18nTimeDate(args ...interface{}) string {
	ok := false
	var s string
	if len(args) == 1 {
		s, ok = args[0].(string)
	}
	if !ok {
		s = fmt.Sprint(args...)
	}
	return Tr.Time(s)
}

Registration function is as follows:

t.Funcs(template.FuncMap{"TD": I18nTimeDate})

Using the following template:

{{.V.Now | TD}}

3 Currency Information

Currency called Tr.Money function to achieve the appropriate time for a change, mapFunc is implemented as follows:

func I18nMoney(args ...interface{}) string {
	ok := false
	var s string
	if len(args) == 1 {
		s, ok = args[0].(string)
	}
	if !ok {
		s = fmt.Sprint(args...)
	}
	return Tr.Money(s)
}

Registration function is as follows:

t.Funcs(template.FuncMap{"M": I18nMoney})

Using the following template:

{{.V.Money | M}}

Summary

Through this section we know how to implement a multi-language package for Web applications, through a custom language packs that we can facilitate the realization of multi-language, but also through the configuration file can be very convenient to expand multi-language, by default, go-i18n will be self- fixed load some common configuration information, such as time, money, etc., we can be very convenient to use, and in order to support the use of these functions in the template, but also to achieve the appropriate template functions, thus allowing us to develop Web applications in the time directly in the template the way through the pipeline operate multiple language packs.