Files
build-web-application-with-…/zh-tw/10.3.md
2019-02-26 01:40:54 +08:00

5.6 KiB
Raw Blame History

10.3 國際化站點

前面小節介紹瞭如何處理本地化資源即Locale一個相應的配置檔案那麼如果處理多個的本地化資源呢而對於一些我們經常用到的例如簡單的文字翻譯、時間日期、數字等如果處理呢本小節將一一解決這些問題。

管理多個本地包

在開發一個應用的時候首先我們要決定是隻支援一種語言還是多種語言如果要支援多種語言我們則需要制定一個組織結構以方便將來更多語言的新增。在此我們設計如下Locale有關的檔案放置在config/locales下假設你要支援中文和英文那麼你需要在這個資料夾下放置en.json和zh.json。大概的內容如下所示


# zh.json

{
"zh": {
	"submit": "提交",
	"create": "建立"
	}
}

# 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("zh")
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
}

透過上面的方法載入配置資訊到預設的檔案,這樣我們就可以在我們沒有自訂時間資訊的時候執行如下的程式碼取得對應的資訊:


//locale=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. 文字資訊

文字資訊呼叫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}}
  1. 時間日期

時間日期呼叫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}}
  1. 貨幣資訊

貨幣呼叫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}}

總結

透過這小節我們知道了如何實現一個多語言套件的Web應用透過自訂語言套件我們可以方便的實現多語言而且透過配置檔案能夠非常方便的擴充多語言預設情況下go-i18n會自定載入一些公共的配置資訊例如時間、貨幣等我們就可以非常方便的使用同時為了支援在範本中使用這些函式也實現了相應的範本函式這樣就允許我們在開發Web應用的時候直接在範本中透過pipeline的方式來操作多語言套件。