Merging other languages

This commit is contained in:
James Miranda
2016-09-23 18:01:10 -03:00
parent 380a8ee74c
commit de3c5bdaa4
490 changed files with 24539 additions and 24588 deletions

View File

@@ -1,180 +1,184 @@
# 10.3 国际化站点
前面小节介绍了如何处理本地化资源即Locale一个相应的配置文件那么如果处理多个的本地化资源呢而对于一些我们经常用到的例如简单的文本翻译、时间日期、数字等如果处理呢本小节将一一解决这些问题。
## 管理多个本地包
在开发一个应用的时候首先我们要决定是只支持一种语言还是多种语言如果要支持多种语言我们则需要制定一个组织结构以方便将来更多语言的添加。在此我们设计如下Locale有关的文件放置在config/locales下假设你要支持中文和英文那么你需要在这个文件夹下放置en.json和zh.json。大概的内容如下所示
# zh.json
{
"zh": {
"submit": "提交",
"create": "创建"
}
}
#en.json
{
"en": {
"submit": "Submit",
"create": "Create"
}
}
为了支持国际化,在此我们使用了一个国际化相关的包——[go-i18n](https://github.com/astaxie/go-i18n)首先我们向go-i18n包注册config/locales这个目录,以加载所有的locale文件
Tr:=i18n.NewLocale()
Tr.LoadPath("config/locales")
这个包使用起来很简单,你可以通过下面的方式进行测试:
fmt.Println(Tr.Translate("submit"))
//输出Submit
Tr.SetLocale("zn")
fmt.Println(Tr.Translate("submit"))
//输出“递交”
## 自动加载本地包
上面我们介绍了如何自动加载自定义语言包其实go-i18n库已经预加载了很多默认的格式信息例如时间格式、货币格式用户可以在自定义配置时改写这些默认配置请看下面的处理过程
//加载默认配置文件这些文件都放在go-i18n/locales下面
//文件命名zh.json、en-json、en-US.json等可以不断的扩展支持更多的语言
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
}
通过上面的方法加载配置信息到默认的文件,这样我们就可以在我们没有自定义时间信息的时候执行如下的代码获取对应的信息:
//locale=zh的情况下执行如下代码
fmt.Println(Tr.Time(time.Now()))
//输出2009年1月08日 星期四 20:37:58 CST
fmt.Println(Tr.Time(time.Now(),"long"))
//输出2009年1月08日
fmt.Println(Tr.Money(11.11))
//输出:¥11.11
## template mapfunc
上面我们实现了多个语言包的管理和加载,而一些函数的实现是基于逻辑层的,例如:"Tr.Translate"、"Tr.Time"、"Tr.Money"等虽然我们在逻辑层可以利用这些函数把需要的参数进行转换后在模板层渲染的时候直接输出但是如果我们想在模版层直接使用这些函数该怎么实现呢不知你是否还记得在前面介绍模板的时候说过Go语言的模板支持自定义模板函数下面是我们实现的方便操作的mapfunc
1. 文本信息
文本信息调用`Tr.Translate`来实现相应的信息转换mapFunc的实现如下
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)
}
注册函数如下:
t.Funcs(template.FuncMap{"T": I18nT})
模板中使用如下:
{{.V.Submit | T}}
2. 时间日期
时间日期调用`Tr.Time`函数来实现相应的时间转换mapFunc的实现如下
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)
}
注册函数如下:
t.Funcs(template.FuncMap{"TD": I18nTimeDate})
模板中使用如下:
{{.V.Now | TD}}
3. 货币信息
货币调用`Tr.Money`函数来实现相应的时间转换mapFunc的实现如下
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)
}
注册函数如下:
t.Funcs(template.FuncMap{"M": I18nMoney})
模板中使用如下:
{{.V.Money | M}}
## 总结
通过这小节我们知道了如何实现一个多语言包的Web应用通过自定义语言包我们可以方便的实现多语言而且通过配置文件能够非常方便的扩充多语言默认情况下go-i18n会自定加载一些公共的配置信息例如时间、货币等我们就可以非常方便的使用同时为了支持在模板中使用这些函数也实现了相应的模板函数这样就允许我们在开发Web应用的时候直接在模板中通过pipeline的方式来操作多语言包。
## links
* [目录](<preface.md>)
* 上一节: [本地化资源](<10.2.md>)
* 下一节: [小结](<10.4.md>)
# 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](https://github.com/astaxie/go-i18n) ( ***A more advanced i18n package can be found [here](https://github.com/beego/i18n)*** ), 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
A simple text conversion function implementing a mapfunc can be seen below. It uses `Tr.Translate` to perform the appropriate translations:
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)
}
We register the function like so:
t.Funcs(template.FuncMap{"T": I18nT})
Then use it from your template:
{{.V.Submit | T}}
2. The date and time
Dates and times call the `Tr.Time` function to perform their translations. The 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)
}
Register the function like so:
t.Funcs(template.FuncMap{"TD": I18nTimeDate})
Then use it from your template:
{{.V.Now | TD}}
3 Currency Information
Currencies use the `Tr.Money` function to convert money. The 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)
}
Register the function like so:
t.Funcs(template.FuncMap{"M": I18nMoney})
Then use it from your template:
{{.V.Money | M}}
## Summary
In this section we learned how to implement multiple language packs in our web applications. We saw that through custom language packs, we can not only easily internationalize our applications, but facilitate the addition of other languages also (through the use of a configuration file). By default, the go-i18n package will provide some common configurations for time, currency, etc., which can be very convenient to use. We learned that these functions can also be used directly from our templates using mapping functions; each translated string can be piped directly to our templates. This enables our web applications to accommodate multiple languages with minimal effort.
## Links
- [Directory](preface.md)
- Previous section: [Localized resources](10.2.md)
- Next section: [Summary](10.4.md)