goweb- 国际化和本地化

喜夏-厌秋 提交于 2020-01-15 13:29:04

国际化和本地化

为了适应经济的全球一体化,作为开发者,我们需要开发出支持多国语言、国际化的Web应用,即同样的页面在不同的语言环境下需要显示不同的效果,也就是说应用程序在运行时能够根据请求所来自的地域与语言的不同而显示不同的用户界面。这样,当需要在应用程序中添加对新的语言的支持时,无需修改应用程序的代码,只需要增加语言包即可实现。

国际化与本地化(Internationalization and localization,通常用i18n和L10N表示),国际化是将针对某个地区设计的程序进行重构,以使它能够在更多地区使用,本地化是指在一个面向国际化的程序中增加对新地区的支持。

所谓的国际化:就是根据特定的locale信息,提取与之相应的字符串或其它一些东西(比如时间和货币的格式)等等。这涉及到三个问题:

1、如何确定locale。

2、如何保存与locale相关的字符串或其它信息。

3、如何根据locale提取字符串和其它相应的信息。

设置默认地区

什么是Locale

Locale是一组描述世界上某一特定区域文本格式和语言习惯的设置的集合。locale名通常由三个部分组成:第一部分,是一个强制性的,表示语言的缩写,例如"en"表示英文或"zh"表示中文。第二部分,跟在一个下划线之后,是一个可选的国家说明符,用于区分讲同一种语言的不同国家,例如"en_US"表示美国英语,而"en_UK"表示英国英语。最后一部分,跟在一个句点之后,是可选的字符集说明符,例如"zh_CN.gb2312"表示中国使用gb2312字符集。

本地化资源

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

本地化文本消息

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

有些时候仅是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)

本地化日期和时间

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

  • 时区问题
  • 格式问题

本地化视图和资源

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

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

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

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

而对于里面的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">

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

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

国际化站点

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

管理多个本地包

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

自动加载本地包

上面我们介绍了如何自动加载自定义语言包,其实go-i18n库已经预加载了很多默认的格式信息.

emplate mapfunc

上面实现了多个语言包的管理和加载,而一些函数的实现是基于逻辑层的,例如:"Tr.Translate"、"Tr.Time"、"Tr.Money"等,虽然我们在逻辑层可以利用这些函数把需要的参数进行转换后在模板层渲染的时候直接输出,但是如果我们想在模版层直接使用这些函数该怎么实现呢?不知你是否还记得,在前面介绍模板的时候说过:Go语言的模板支持自定义模板函数,下面是我们实现的方便操作的mapfunc:

文本信息
文本信息调用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}}

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!