i18n 模塊主要用于實(shí)現(xiàn)站點(diǎn)或應(yīng)用的國際化功能,實(shí)現(xiàn)多語言界面與反饋,增強(qiáng)用戶體驗(yàn)。像 Go Walker 和 beego 官網(wǎng) 即是采用了該模塊實(shí)現(xiàn)了中文與英文的雙語界面。
您可以通過以下方式安裝該模塊:
go get github.com/beego/i18n
首先,您需要導(dǎo)入該包:
import (
"github.com/beego/i18n"
)
該模塊主要采用的是鍵值對(duì)的形式,非常類似 INI 格式的配置文件,但又在此基礎(chǔ)上增強(qiáng)了一些功能。每個(gè)語種均對(duì)應(yīng)一個(gè)本地化文件,例如 beego 官網(wǎng)的 conf 目錄下就有 locale_en-US.ini 和 locale_zh-CN.ini 兩個(gè)本地化文件。
本地化文件的文件名和后綴是隨意的,不過我們建議您采用與 beego 官網(wǎng)相同的風(fēng)格來對(duì)它們命名。
下面是兩個(gè)最簡(jiǎn)單的本地化文件示例:
文件 locale_en-US.ini:
hi = hello
bye = goodbye
文件 locale_zh-CN.ini:
hi = 您好
bye = 再見
對(duì)于每個(gè)請(qǐng)求,beego 都會(huì)采用單獨(dú)的 goroutine 來處理,因此可以對(duì)每個(gè)控制器匿名嵌入一個(gè) i18n.Locale 結(jié)構(gòu)用于處理當(dāng)前請(qǐng)求的本地化響應(yīng)。這個(gè)要求您能夠理解 beego 的 baseController 理念和使用 Prepare 方法,具體可參考 beego 官網(wǎng)的控制器源碼部分 routers/router.go。
接受請(qǐng)求之后,在 baseController 的 Prepare 方法內(nèi)進(jìn)行語言處理,這樣便可應(yīng)用后所有其它控制器內(nèi)而無需重復(fù)編寫代碼。
以下代碼摘取自 beego 官網(wǎng)源碼 routers/init.go:
// Initialized language type list.
langs := strings.Split(beego.AppConfig.String("lang::types"), "|")
names := strings.Split(beego.AppConfig.String("lang::names"), "|")
langTypes = make([]*langType, 0, len(langs))
for i, v := range langs {
langTypes = append(langTypes, &langType{
Lang: v,
Name: names[i],
})
}
for _, lang := range langs {
beego.Trace("Loading language: " + lang)
if err := i18n.SetMessage(lang, "conf/"+"locale_"+lang+".ini"); err != nil {
beego.Error("Fail to set message file: " + err.Error())
return
}
}
在這段代碼中,我們首先從配置文件中獲取我們需要支持的語言種類,例如官網(wǎng)支持的語言有 en-US 和 zh-CN。接著初始化了一個(gè)用于實(shí)現(xiàn)用戶自由切換語言的 slice(此處不做討論),最后,根據(jù)我們需要支持的語言種類,采用一個(gè)循環(huán)內(nèi)調(diào)用 i18n.SetMessage 加載所有本地化文件。此時(shí),您應(yīng)該明白為什么我們推薦您采用標(biāo)準(zhǔn)化的形式命名您的本地化文件。
下面的代碼摘取自 beego 官網(wǎng)的控制器語言處理部分 routers/router.go,依次根據(jù) URL 指定、Cookies 和瀏覽器 Accept-Language 來獲取用戶語言選項(xiàng),然后設(shè)置控制器級(jí)別的語言。
// setLangVer sets site language version.
func (this *baseRouter) setLangVer() bool {
isNeedRedir := false
hasCookie := false
// 1. Check URL arguments.
lang := this.Input().Get("lang")
// 2. Get language information from cookies.
if len(lang) == 0 {
lang = this.Ctx.GetCookie("lang")
hasCookie = true
} else {
isNeedRedir = true
}
// Check again in case someone modify by purpose.
if !i18n.IsExist(lang) {
lang = ""
isNeedRedir = false
hasCookie = false
}
// 3. Get language information from 'Accept-Language'.
if len(lang) == 0 {
al := this.Ctx.Request.Header.Get("Accept-Language")
if len(al) > 4 {
al = al[:5] // Only compare first 5 letters.
if i18n.IsExist(al) {
lang = al
}
}
}
// 4. Default language is English.
if len(lang) == 0 {
lang = "en-US"
isNeedRedir = false
}
curLang := langType{
Lang: lang,
}
// Save language information in cookies.
if !hasCookie {
this.Ctx.SetCookie("lang", curLang.Lang, 1<<31-1, "/")
}
restLangs := make([]*langType, 0, len(langTypes)-1)
for _, v := range langTypes {
if lang != v.Lang {
restLangs = append(restLangs, v)
} else {
curLang.Name = v.Name
}
}
// Set language properties.
this.Lang = lang
this.Data["Lang"] = curLang.Lang
this.Data["CurLang"] = curLang.Name
this.Data["RestLangs"] = restLangs
return isNeedRedir
}
其中,isNeedRedir 變量用于表示用戶是否是通過 URL 指定來決定語言選項(xiàng)的,為了保持 URL 整潔,官網(wǎng)在遇到這種情況時(shí)自動(dòng)將語言選項(xiàng)設(shè)置到 Cookies 中然后重定向。
代碼 this.Data["Lang"] = curLang.Lang 是將用戶語言選項(xiàng)設(shè)置到名為 Lang 的模板變量中,使得能夠在模板中處理語言問題。
以下兩行:
this.Data["CurLang"] = curLang.Name
this.Data["RestLangs"] = restLangs
主要用于實(shí)現(xiàn)用戶自由切換語言,具體實(shí)現(xiàn)原理請(qǐng)參考 beego 官網(wǎng)源碼。
當(dāng)作為匿名字段嵌入到 baseController 之后,直接通過 this.Tr(format string, args ...interface{}) 即可進(jìn)行語言處理。
通過在控制器中傳入一個(gè) Lang 變量來指示語言選項(xiàng)后,就可以在模板中進(jìn)行本地化處理,不過在這之前,需要先注冊(cè)一個(gè)模板函數(shù)。
以下代碼摘取自 beego 官網(wǎng)源碼 beeweb.go:
beego.AddFuncMap("i18n", i18n.Tr)
注冊(cè)完成之后,便可配合 Lang 變量在模板中進(jìn)行語言處理:
{{i18n .Lang "hi%d" 12}}
以上代碼會(huì)輸出:
針對(duì)不同頁面,同一個(gè)鍵的名稱很可能會(huì)對(duì)應(yīng)不同的含義。因此,i18n 模塊還利用 INI 格式配置文件的節(jié)特性來實(shí)現(xiàn)分區(qū)功能。
例如,同樣是鍵名 about,在首頁需要顯示為 關(guān)于,而在關(guān)于頁面需要顯示為 關(guān)于我們,則可以通過分區(qū)功能來實(shí)現(xiàn)。
本地化文件中的內(nèi)容:
about = About
[about]
about = About Us
獲取首頁的 about:
{{i18n .Lang "about"}}
獲取關(guān)于頁面的 about:
{{i18n .Lang "about.about"}}
由于 . 是作為分區(qū)的標(biāo)志,所以當(dāng)您的鍵名出現(xiàn)該符號(hào)的時(shí)候,會(huì)出現(xiàn)歧義導(dǎo)致語言處理失敗。這時(shí),您只需要在整個(gè)鍵名前加上一個(gè)額外的 . 即可避免歧義。
例如,我們的鍵名為 about.,為了避免歧義,我們需要使用:
{{i18n .Lang ".about."}}
來獲取正確的本地化結(jié)果。
i18n 模塊提供命令行工具 beei18n 來幫助簡(jiǎn)化開發(fā)中的一些步驟。您可以通過以下方式安裝:
go get github.com/beego/i18n/beei18n
命令 sync 允許您使用已經(jīng)創(chuàng)建好的一個(gè)本地化文件為模板,創(chuàng)建或同步其它的本地化文件:
beei18n sync srouce_file.ini other1.ini other2.ini
該命令可以同時(shí)操作 1 個(gè)或多個(gè)文件。
如果未找到相應(yīng)鍵的對(duì)應(yīng)值,則會(huì)輸出鍵的原字符串。例如:當(dāng)鍵為 hi 但未在本地化文件中找到以該字符串命名的鍵,則會(huì)將 hi 作為字符串返回給調(diào)用者。
更多建議: