i18n:国际化。 L10N:本地化。
国际化:就是根据特定的locale信息,提取与之相应的字符串或其他一些东西。
1、如何确定locale。2、如何保存与locale相关的字符串或其他信息。3、如何根据Locale提取字符串和其他相应的信息。
什么是Locale
Locale是一组描述世界上某一特定区域文本格式和语言习惯的设置的集合。
Locale通常由三个部分组成:
第一部分是一个强制性的表示语言的缩写。
第二部分是跟在有一个下划线之后,是一个可选的国家说明符,列如en_US表示美国英语,en_UK表示英国英语。
第三部分跟在一个句点之后是可选的字符集说明符,例如”zh_CN.gb2312“表示中国使用gb2312字符集
GO语言默认采用“UTF-8”编码集
$ locale -a
设置Locale
- 通过域名来设置Locale
设置Locale的办法之一是在应用运行的时候采用域名分级的方式。
.com表示英文站,.cn表示中文站。
if r.Hsot == "www.asta.com" {
i18n.SetLocale("en")
} else if r.Host == "www.asta.cn" {
i18n.SetLocale("zh-CN")
}
- 从域名参数设置Locale
目前最常用的方式是URL里面带上参数,例如www.asta.com/hellow?locale=zh
- 从客户端设置地区
Accept-Language
客户端请求的时候在HTTP头信息里面有Accept-Language。
AL := r.Header.Get("Accept-Language")
if AL == "en" {
i18n.SetLocale("en")
} else if AL == "zh-CN" {
i18n.SetLocale("zh-CN")
}
- IP地址
另一种根据客户端来设定地区的就是用户访问的IP,根据相应的IP库,就可以得到对应的IP地区。
- 用户Profile
根据用户输入的信息保存到账号相关的profile中。
本地化资源
- 本地化文本消息
建立需要的语言相应的MAP来维护一个key-value的关系,在输出之前按需从适合的map中去获取相应的文本。
- 本地化日期和时间
1、时区问题。2、格式问题。
en["time_zone"]="America/Chicago"
cn["time_zone"]="Asia/Shanghai"
loc,_:=time.LoadLocation(msg(lang,"time_zone"))
t:=time.Now()
t = t.In(loc)
fmt.Println(t.Format(time.RFC3339))
- 本地化货币值
en["money"] ="USD %d"
cn["money"] ="¥%d元"
fmt.Println(money_format(msg(lang,"date_format"),100))
func money_format(fomate string,money int64) string{
return fmt.Sprintf(fomate,money)
}
国际化站点
使用一个国际化相关的包——go-i18n,首先我们向go-i18n包注册config/locales这个目录,以加载所有的Locale文件。
Tr := i18n.NewLocale()
Tr.LoadPath("config/locales")
fmt.Println(Tr.Translate("submit"))
//输出Submit
Tr.SetLocale("zh")
fmt.Println(Tr.Translate("submit"))
//输出“提交”
- 自动加载本地包
// 加载默认配置文件,这些文件都放在 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
1、文本信息。文本信息调用Tr.Translate来实现相应的信息转换
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、时间日期
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、货币信息
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}}