扫码订阅《 》或入驻星球,即可阅读文章!

GOLANG ROADMAP

阅读模式

  • 沉浸
  • 自动
  • 日常
首页
Go学习
  • Go学院

    • Go小课
    • Go小考
    • Go实战
    • 精品课
  • Go宝典

    • 在线宝典
    • B站精选
    • 推荐图书
    • 精品博文
  • Go开源

    • Go仓库
    • Go月刊
  • Go下载

    • 视频资源
    • 文档资源
Go求职
  • 求职服务

    • 内推互助
    • 求职助力
  • 求职刷题

    • 企业题库
    • 面试宝典
    • 求职面经
Go友会
  • 城市
  • 校园
推广返利 🤑
实验区
  • Go周边
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
author-avatar

GOLANG ROADMAP


首页
Go学习
  • Go学院

    • Go小课
    • Go小考
    • Go实战
    • 精品课
  • Go宝典

    • 在线宝典
    • B站精选
    • 推荐图书
    • 精品博文
  • Go开源

    • Go仓库
    • Go月刊
  • Go下载

    • 视频资源
    • 文档资源
Go求职
  • 求职服务

    • 内推互助
    • 求职助力
  • 求职刷题

    • 企业题库
    • 面试宝典
    • 求职面经
Go友会
  • 城市
  • 校园
推广返利 🤑
实验区
  • Go周边
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
  • Go语言Web编程

    • 课程介绍
  • Web基础

  • 表单

  • 访问数据库

  • session和数据存储

  • 文本处理

  • Web服务

  • 安全与加密

  • 国际化和本地化

    • 第1节:国际化和本地化
    • 第2节:设置默认地区
    • 第3节:本地化资源
    • 第4节:国际化站点
    • 第5节:小结
  • 错误处理,调试和测试

  • 部署与维护

  • 如何设计一个Web框架

  • 扩展Web框架

扫码订阅《 》或入驻星球,即可阅读文章!

第4节:国际化站点


ASTA谢

前面小节介绍了如何处理本地化资源,即 Locale 一个相应的配置文件,那么如果处理多个的本地化资源呢?而对于一些我们经常用到的例如:简单的文本翻译、时间日期、数字等如果处理呢?本小节将一一解决这些问题。

# 管理多个本地包

在开发一个应用的时候,首先我们要决定是只支持一种语言,还是多种语言,如果要支持多种语言,我们则需要制定一个组织结构,以方便将来更多语言的添加。在此我们设计如下:Locale 有关的文件放置在 config/locales 下,假设你要支持中文和英文,那么你需要在这个文件夹下放置 en.json 和 zh.json。大概的内容如下所示:

# zh.json

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

# en.json

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

为了支持国际化,在此我们使用了一个国际化相关的包 —— go-i18n (opens new window),首先我们向 go-i18n 包注册 config/locales 这个目录, 以加载所有的 locale 文件

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

这个包使用起来很简单,你可以通过下面的方式进行测试:

fmt.Println(Tr.Translate("submit"))
//输出Submit
Tr.SetLocale("zh")
fmt.Println(Tr.Translate("submit"))
//输出“提交”
1
2
3
4
5

# 自动加载本地包

上面我们介绍了如何自动加载自定义语言包,其实 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
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

通过上面的方法加载配置信息到默认的文件,这样我们就可以在我们没有自定义时间信息的时候执行如下的代码获取对应的信息:

// 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
1
2
3
4
5
6
7
8
9
10

# 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)
}
1
2
3
4
5
6
7
8
9
10
11

注册函数如下:

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

模板中使用如下:

{{.V.Submit | T}}
1
  1. 时间日期

时间日期调用 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)
}
1
2
3
4
5
6
7
8
9
10
11

注册函数如下:

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

模板中使用如下:

{{.V.Now | TD}}
1
  1. 货币信息

货币调用 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)
}
1
2
3
4
5
6
7
8
9
10
11

注册函数如下:

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

模板中使用如下:

{{.V.Money | M}}
1

# 总结

通过这小节我们知道了如何实现一个多语言包的 Web 应用,通过自定义语言包我们可以方便的实现多语言,而且通过配置文件能够非常方便的扩充多语言,默认情况下,go-i18n 会自定加载一些公共的配置信息,例如时间、货币等,我们就可以非常方便的使用,同时为了支持在模板中使用这些函数,也实现了相应的模板函数,这样就允许我们在开发 Web 应用的时候直接在模板中通过 pipeline 的方式来操作多语言包。

  • 管理多个本地包
  • 自动加载本地包
  • template mapfunc
  • 总结