鍍金池/ 教程/ GO/ 10.3 國際化站點(diǎn)
7 文本處理
3 Web基礎(chǔ)
14 擴(kuò)展Web框架
10.4 小結(jié)
2.2 Go基礎(chǔ)
2.8 總結(jié)
6.1 session和cookie
5.5 使用beedb庫進(jìn)行ORM開發(fā)
8.3 REST
13.6 小結(jié)
5.4 使用PostgreSQL數(shù)據(jù)庫
14.6 pprof支持
14.1 靜態(tài)文件支持
11.2 使用GDB調(diào)試
7.7 小結(jié)
1 GO環(huán)境配置
14.5 多語言支持
7.1 XML處理
1.5 總結(jié)
13 如何設(shè)計(jì)一個(gè)Web框架
14.3 表單及驗(yàn)證支持
12 部署與維護(hù)
10 國際化和本地化
1.1 Go 安裝
6.2 Go如何使用session
5.6 NOSQL數(shù)據(jù)庫操作
6.5 小結(jié)
9.4 避免SQL注入
12.1 應(yīng)用日志
4.2 驗(yàn)證表單的輸入
10.1 設(shè)置默認(rèn)地區(qū)
1.3 Go 命令
9.6 加密和解密數(shù)據(jù)
4.1 處理表單的輸入
4.4 防止多次遞交表單
11.3 Go怎么寫測試用例
8 Web服務(wù)
12.3 應(yīng)用部署
5.7 小結(jié)
12.5 小結(jié)
11 錯誤處理,調(diào)試和測試
9.2 確保輸入過濾
14.2 Session支持
6.4 預(yù)防session劫持
12.4 備份和恢復(fù)
8.1 Socket編程
13.1 項(xiàng)目規(guī)劃
13.4 日志和配置設(shè)計(jì)
7.6 字符串處理
13.2 自定義路由器設(shè)計(jì)
6.3 session存儲
3.4 Go的http包詳解
8.2 WebSocket
10.3 國際化站點(diǎn)
7.5 文件操作
7.4 模板處理
9.1 預(yù)防CSRF攻擊
13.3 controller設(shè)計(jì)
2.6 interface
14.4 用戶認(rèn)證
2.3 流程和函數(shù)
附錄A 參考資料
11.1 錯誤處理
9.5 存儲密碼
9.3 避免XSS攻擊
12.2 網(wǎng)站錯誤處理
6 session和數(shù)據(jù)存儲
2.4 struct類型
3.3 Go如何使得Web工作
2.5 面向?qū)ο?/span>
3.1 Web工作方式
1.2 GOPATH與工作空間
2.1 你好,Go
9.7 小結(jié)
13.5 實(shí)現(xiàn)博客的增刪改
7.2 JSON處理
10.2 本地化資源
7.3 正則處理
2 Go語言基礎(chǔ)
5.1 database/sql接口
4.5 處理文件上傳
8.5 小結(jié)
4.3 預(yù)防跨站腳本
5.3 使用SQLite數(shù)據(jù)庫
14.7 小結(jié)
3.2 Go搭建一個(gè)Web服務(wù)器
2.7 并發(fā)
5 訪問數(shù)據(jù)庫
4 表單
3.5 小結(jié)
1.4 Go開發(fā)工具
11.4 小結(jié)
9 安全與加密
5.2 使用MySQL數(shù)據(jù)庫
4.6 小結(jié)
8.4 RPC

10.3 國際化站點(diǎn)

前面小節(jié)介紹了如何處理本地化資源,即Locale一個(gè)相應(yīng)的配置文件,那么如果處理多個(gè)的本地化資源呢?而對于一些我們經(jīng)常用到的例如:簡單的文本翻譯、時(shí)間日期、數(shù)字等如果處理呢?本小節(jié)將一一解決這些問題。

管理多個(gè)本地包

在開發(fā)一個(gè)應(yīng)用的時(shí)候,首先我們要決定是只支持一種語言,還是多種語言,如果要支持多種語言,我們則需要制定一個(gè)組織結(jié)構(gòu),以方便將來更多語言的添加。在此我們設(shè)計(jì)如下:Locale有關(guān)的文件放置在config/locales下,假設(shè)你要支持中文和英文,那么你需要在這個(gè)文件夾下放置en.json和zh.json。大概的內(nèi)容如下所示:

# zh.json

{
"zh": {
    "submit": "提交",
    "create": "創(chuàng)建"
    }
}

#en.json

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

為了支持國際化,在此我們使用了一個(gè)國際化相關(guān)的包——go-i18n,首先我們向go-i18n包注冊config/locales這個(gè)目錄,以加載所有的locale文件

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

這個(gè)包使用起來很簡單,你可以通過下面的方式進(jìn)行測試:

fmt.Println(Tr.Translate("submit"))
//輸出Submit
Tr.SetLocale("zn")
fmt.Println(Tr.Translate("submit"))
//輸出“遞交”

自動加載本地包

上面我們介紹了如何自動加載自定義語言包,其實(shí)go-i18n庫已經(jīng)預(yù)加載了很多默認(rèn)的格式信息,例如時(shí)間格式、貨幣格式,用戶可以在自定義配置時(shí)改寫這些默認(rèn)配置,請看下面的處理過程:

//加載默認(rèn)配置文件,這些文件都放在go-i18n/locales下面

//文件命名zh.json、en-json、en-US.json等,可以不斷的擴(kuò)展支持更多的語言

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
}

通過上面的方法加載配置信息到默認(rèn)的文件,這樣我們就可以在我們沒有自定義時(shí)間信息的時(shí)候執(zhí)行如下的代碼獲取對應(yīng)的信息:

//locale=zh的情況下,執(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

上面我們實(shí)現(xiàn)了多個(gè)語言包的管理和加載,而一些函數(shù)的實(shí)現(xiàn)是基于邏輯層的,例如:"Tr.Translate"、"Tr.Time"、"Tr.Money"等,雖然我們在邏輯層可以利用這些函數(shù)把需要的參數(shù)進(jìn)行轉(zhuǎn)換后在模板層渲染的時(shí)候直接輸出,但是如果我們想在模版層直接使用這些函數(shù)該怎么實(shí)現(xiàn)呢?不知你是否還記得,在前面介紹模板的時(shí)候說過:Go語言的模板支持自定義模板函數(shù),下面是我們實(shí)現(xiàn)的方便操作的mapfunc:

  1. 文本信息

文本信息調(diào)用Tr.Translate來實(shí)現(xiàn)相應(yīng)的信息轉(zhuǎn)換,mapFunc的實(shí)現(xiàn)如下:

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)
}

注冊函數(shù)如下:

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

模板中使用如下:

{{.V.Submit | T}}
  1. 時(shí)間日期

時(shí)間日期調(diào)用Tr.Time函數(shù)來實(shí)現(xiàn)相應(yīng)的時(shí)間轉(zhuǎn)換,mapFunc的實(shí)現(xiàn)如下:

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)
}

注冊函數(shù)如下:

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

模板中使用如下:

{{.V.Now | TD}}
  1. 貨幣信息

貨幣調(diào)用Tr.Money函數(shù)來實(shí)現(xiàn)相應(yīng)的時(shí)間轉(zhuǎn)換,mapFunc的實(shí)現(xiàn)如下:

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)
}

注冊函數(shù)如下:

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

模板中使用如下:

{{.V.Money | M}}

總結(jié)

通過這小節(jié)我們知道了如何實(shí)現(xiàn)一個(gè)多語言包的Web應(yīng)用,通過自定義語言包我們可以方便的實(shí)現(xiàn)多語言,而且通過配置文件能夠非常方便的擴(kuò)充多語言,默認(rèn)情況下,go-i18n會自定加載一些公共的配置信息,例如時(shí)間、貨幣等,我們就可以非常方便的使用,同時(shí)為了支持在模板中使用這些函數(shù),也實(shí)現(xiàn)了相應(yīng)的模板函數(shù),這樣就允許我們在開發(fā)Web應(yīng)用的時(shí)候直接在模板中通過pipeline的方式來操作多語言包。