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

GOLANG ROADMAP

阅读模式

  • 沉浸
  • 自动
  • 日常
首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

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

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

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

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

GOLANG ROADMAP


首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

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

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

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

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

    • 课程介绍
  • Web基础

  • 表单

  • 访问数据库

  • session和数据存储

  • 文本处理

  • Web服务

  • 安全与加密

  • 国际化和本地化

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

  • 部署与维护

  • 如何设计一个Web框架

  • 扩展Web框架

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

第3节:本地化资源


ASTA谢

前面小节我们介绍了如何设置 Locale,设置好 Locale 之后我们需要解决的问题就是如何存储相应的 Locale 对应的信息呢?这里面的信息包括:文本信息、时间和日期、货币值、图片、包含文件以及视图等资源。那么接下来我们将对这些信息一一进行介绍,Go 语言中我们把这些格式信息存储在 JSON 中,然后通过合适的方式展现出来。(接下来以中文和英文两种语言对比举例, 存储格式文件 en.json 和 zh-CN.json)

# 本地化文本消息

文本信息是编写 Web 应用中最常用到的,也是本地化资源中最多的信息,想要以适合本地语言的方式来显示文本信息,可行的一种方案是: 建立需要的语言相应的 map 来维护一个 key-value 的关系,在输出之前按需从适合的 map 中去获取相应的文本,如下是一个简单的示例:

package main

import "fmt"

var locales map[string]map[string]string

func main() {
	locales = make(map[string]map[string]string, 2)
	en := make(map[string]string, 10)
	en["pea"] = "pea"
	en["bean"] = "bean"
	locales["en"] = en
	cn := make(map[string]string, 10)
	cn["pea"] = "豌豆"
	cn["bean"] = "毛豆"
	locales["zh-CN"] = cn
	lang := "zh-CN"
	fmt.Println(msg(lang, "pea"))
	fmt.Println(msg(lang, "bean"))
}

func msg(locale, key string) string {
	if v, ok := locales[locale]; ok {
		if v2, ok := v[key]; ok {
			return v2
		}
	}
	return ""
}
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

上面示例演示了不同 locale 的文本翻译,实现了中文和英文对于同一个 key 显示不同语言的实现,上面实现了中文的文本消息,如果想切换到英文版本,只需要把 lang 设置为 en 即可。

有些时候仅是 key-value 替换是不能满足需要的,例如 "I am 30 years old", 中文表达是 "我今年30岁了",而此处的 30 是一个变量,该怎么办呢?这个时候,我们可以结合 fmt.Printf 函数来实现,请看下面的代码:

en["how old"] ="I am %d years old"
cn["how old"] ="我今年%d岁了"

fmt.Printf(msg(lang, "how old"), 30)
1
2
3
4

上面的示例代码仅用以演示内部的实现方案,而实际数据是存储在 JSON 里面的,所以我们可以通过 json.Unmarshal 来为相应的 map 填充数据。

# 本地化日期和时间

因为时区的关系,同一时刻,在不同的地区,表示是不一样的,而且因为 Locale 的关系,时间格式也不尽相同,例如中文环境下可能显示:2012年10月24日 星期三 23时11分13秒 CST,而在英文环境下可能显示: Wed Oct 24 23:11:13 CST 2012。这里面我们需要解决两点:

  1. 时区问题
  2. 格式问题

$GOROOT/lib/time 包中的 timeinfo.zip 含有 locale 对应的时区的定义,为了获得对应于当前 locale 的时间,我们应首先使用 time.LoadLocation(name string) 获取相应于地区的 locale,比如 Asia/Shanghai 或 America/Chicago 对应的时区信息,然后再利用此信息与调用 time.Now 获得的 Time 对象协作来获得最终的时间。详细的请看下面的例子 (该例子采用上面例子的一些变量):

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))
1
2
3
4
5
6
7

我们可以通过类似处理文本格式的方式来解决时间格式的问题,举例如下:

en["date_format"]="%Y-%m-%d %H:%M:%S"
cn["date_format"]="%Y年%m月%d日 %H时%M分%S秒"

fmt.Println(date(msg(lang,"date_format"),t))

func date(fomate string,t time.Time) string{
	year, month, day = t.Date()
	hour, min, sec = t.Clock()
	// 解析相应的 %Y %m %d %H %M %S 然后返回信息
	// %Y 替换成 2012
	// %m 替换成 10
	// %d 替换成 24
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 本地化货币值

各个地区的货币表示也不一样,处理方式也与日期差不多,细节请看下面代码:

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

# 本地化视图和资源

我们可能会根据 Locale 的不同来展示视图,这些视图包含不同的图片、css、js 等各种静态资源。那么应如何来处理这些信息呢?首先我们应按 locale 来组织文件信息,请看下面的文件目录安排:

views
|--en  // 英文模板
	|--images     // 存储图片信息
	|--js         // 存储 JS 文件
	|--css        // 存储 css 文件
	index.tpl     // 用户首页
	login.tpl     // 登录首页
|--zh-CN // 中文模板
	|--images
	|--js
	|--css
	index.tpl
	login.tpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14

有了这个目录结构后我们就可以在渲染的地方这样来实现代码:

s1, _ := template.ParseFiles("views/"+lang+"/index.tpl")
VV.Lang=lang
s1.Execute(os.Stdout, VV)
1
2
3

而对于里面的 index.tpl 里面的资源设置如下:

// js 文件
<script type="text/javascript" src="views/{{.Lang}}/js/jquery/jquery-1.8.0.min.js"></script>
// css 文件
<link href="views/{{.Lang}}/css/bootstrap-responsive.min.css" rel="stylesheet">
// 图片文件
<img src="views/{{.Lang}}/images/btn.png">
1
2
3
4
5
6

采用这种方式来本地化视图以及资源时,我们就可以很容易的进行扩展了。

# 总结

本小节介绍了如何使用及存储本地资源,有时需要通过转换函数来实现,有时通过 lang 来设置,但是最终都是通过 key-value 的方式来存储 Locale 对应的数据,在需要时取出相应于 Locale 的信息后,如果是文本信息就直接输出,如果是时间日期或者货币,则需要先通过 fmt.Printf 或其他格式化函数来处理,而对于不同 Locale 的视图和资源则是最简单的,只要在路径里面增加 lang 就可以实现了。

  • 本地化文本消息
  • 本地化日期和时间
  • 本地化货币值
  • 本地化视图和资源
  • 总结