Go 國際化站點

2022-05-13 17:08 更新

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

管理多個本地包

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

# zh.json

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

#en.json

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

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

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

這個包使用起來很簡單,你可以通過下面的方式進行測試:

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

自動加載本地包

上面我們介紹了如何自動加載自定義語言包,其實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
}

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

//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

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

  1. 文本信息
  2. 文本信息調用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}}
  3. 時間日期
  4. 時間日期調用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)
    }

    注冊函數如下:

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

    模板中使用如下:

    {{.V.Now | TD}}
  5. 貨幣信息
  6. 貨幣調用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)
    }

    注冊函數如下:

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

    模板中使用如下:

    {{.V.Money | M}}

總結

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

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號