# 10.1 設置默認地區
## 什么是Locale
Locale是一組描述世界上某一特定區域文本格式和語言習慣的設置的集合。locale名通常由三個部分組成:第一部分,是一個強制性的,表示語言的縮寫,例如"en"表示英文或"zh"表示中文。第二部分,跟在一個下劃線之后,是一個可選的國家說明符,用于區分講同一種語言的不同國家,例如"en_US"表示美國英語,而"en_UK"表示英國英語。最后一部分,跟在一個句點之后,是可選的字符集說明符,例如"zh_CN.gb2312"表示中國使用gb2312字符集。
GO語言默認采用"UTF-8"編碼集,所以我們實現i18n時不考慮第三部分,接下來我們都采用locale描述的前面兩部分來作為i18n標準的locale名。
>在Linux和Solaris系統中可以通過`locale -a`命令列舉所有支持的地區名,讀者可以看到這些地區名的命名規范。對于BSD等系統,沒有locale命令,但是地區信息存儲在/usr/share/locale中。
## 設置Locale
有了上面對locale的定義,那么我們就需要根據用戶的信息(訪問信息、個人信息、訪問域名等)來設置與之相關的locale,我們可以通過如下幾種方式來設置用戶的locale。
### 通過域名設置Locale
設置Locale的辦法這一就是在應用運行的時候采用域名分級的方式,例如,我們采用www.asta.com當做我們的英文站(默認站),而把域名www.asta.cn當做中文站。這樣通過在應用里面設置域名和相應的locale的對應關系,就可以設置好地區。這樣處理有幾點好處:
- 通過URL就可以很明顯的識別
- 用戶可以通過域名很直觀的知道將訪問那種語言的站點
- 在Go程序中實現非常的簡單方便,通過一個map就可以實現
- 有利于搜索引擎抓取,能夠提高站點的SEO
我們可以通過下面的代碼來實現域名的對應locale:
if r.Host == "www.asta.com" {
i18n.SetLocale("en")
} else if r.Host == "www.asta.cn" {
i18n.SetLocale("zh-CN")
} else if r.Host == "www.asta.tw" {
i18n.SetLocale("zh-TW")
}
當然除了整域名設置地區之外,我們還可以通過子域名來設置地區,例如"en.asta.com"表示英文站點,"cn.asta.com"表示中文站點。實現代碼如下所示:
prefix := strings.Split(r.Host,".")
if prefix[0] == "en" {
i18n.SetLocale("en")
} else if prefix[0] == "cn" {
i18n.SetLocale("zh-CN")
} else if prefix[0] == "tw" {
i18n.SetLocale("zh-TW")
}
通過域名設置Locale有如上所示的優點,但是我們一般開發Web應用的時候不會采用這種方式,因為首先域名成本比較高,開發一個Locale就需要一個域名,而且往往統一名稱的域名不一定能申請的到,其次我們不愿意為每個站點去本地化一個配置,而更多的是采用url后面帶參數的方式,請看下面的介紹。
### 從域名參數設置Locale
目前最常用的設置Locale的方式是在URL里面帶上參數,例如www.asta.com/hello?locale=zh或者www.asta.com/zh/hello。這樣我們就可以設置地區:`i18n.SetLocale(params["locale"])`。
這種設置方式幾乎擁有前面講的通過域名設置Locale的所有優點,它采用RESTful的方式,以使得我們不需要增加額外的方法來處理。但是這種方式需要在每一個的link里面增加相應的參數locale,這也許有點復雜而且有時候甚至相當的繁瑣。不過我們可以寫一個通用的函數url,讓所有的link地址都通過這個函數來生成,然后在這個函數里面增加`locale=params["locale"]`參數來緩解一下。
也許我們希望URL地址看上去更加的RESTful一點,例如:www.asta.com/en/books(英文站點)和www.asta.com/zh/books(中文站點),這種方式的URL更加有利于SEO,而且對于用戶也比較友好,能夠通過URL直觀的知道訪問的站點。那么這樣的URL地址可以通過router來獲取locale(參考REST小節里面介紹的router插件實現):
mux.Get("/:locale/books", listbook)
### 從客戶端設置地區
在一些特殊的情況下,我們需要根據客戶端的信息而不是通過URL來設置Locale,這些信息可能來自于客戶端設置的喜好語言(瀏覽器中設置),用戶的IP地址,用戶在注冊的時候填寫的所在地信息等。這種方式比較適合Web為基礎的應用。
- Accept-Language
客戶端請求的時候在HTTP頭信息里面有`Accept-Language`,一般的客戶端都會設置該信息,下面是Go語言實現的一個簡單的根據`Accept-Language`實現設置地區的代碼:
AL := r.Header.Get("Accept-Language")
if AL == "en" {
i18n.SetLocale("en")
} else if AL == "zh-CN" {
i18n.SetLocale("zh-CN")
} else if AL == "zh-TW" {
i18n.SetLocale("zh-TW")
}
當然在實際應用中,可能需要更加嚴格的判斷來進行設置地區
- IP地址
另一種根據客戶端來設定地區就是用戶訪問的IP,我們根據相應的IP庫,對應訪問的IP到地區,目前全球比較常用的就是GeoIP Lite Country這個庫。這種設置地區的機制非常簡單,我們只需要根據IP數據庫查詢用戶的IP然后返回國家地區,根據返回的結果設置對應的地區。
- 用戶profile
當然你也可以讓用戶根據你提供的下拉菜單或者別的什么方式的設置相應的locale,然后我們將用戶輸入的信息,保存到與它帳號相關的profile中,當用戶再次登陸的時候把這個設置復寫到locale設置中,這樣就可以保證該用戶每次訪問都是基于自己先前設置的locale來獲得頁面。
## 總結
通過上面的介紹可知,設置Locale可以有很多種方式,我們應該根據需求的不同來選擇不同的設置Locale的方法,以讓用戶能以它最熟悉的方式,獲得我們提供的服務,提高應用的用戶友好性。
## links
* [目錄](<preface.md>)
* 上一節: [國際化和本地化](<10.0.md>)
* 下一節: [本地化資源](<10.2.md>)
- 目錄
- Go環境配置
- Go安裝
- GOPATH 與工作空間
- Go 命令
- Go開發工具
- 小結
- Go語言基礎
- 你好,Go
- Go基礎
- 流程和函數
- struct
- 面向對象
- interface
- 并發
- 小結
- Web基礎
- web工作方式
- Go搭建一個簡單的web服務
- Go如何使得web工作
- Go的http包詳解
- 小結
- 表單
- 處理表單的輸入
- 驗證表單的輸入
- 預防跨站腳本
- 防止多次遞交表單
- 處理文件上傳
- 小結
- 訪問數據庫
- database/sql接口
- 使用MySQL數據庫
- 使用SQLite數據庫
- 使用PostgreSQL數據庫
- 使用beedb庫進行ORM開發
- NOSQL數據庫操作
- 小結
- session和數據存儲
- session和cookie
- Go如何使用session
- session存儲
- 預防session劫持
- 小結
- 文本文件處理
- XML處理
- JSON處理
- 正則處理
- 模板處理
- 文件操作
- 字符串處理
- 小結
- Web服務
- Socket編程
- WebSocket
- REST
- RPC
- 小結
- 安全與加密
- 預防CSRF攻擊
- 確保輸入過濾
- 避免XSS攻擊
- 避免SQL注入
- 存儲密碼
- 加密和解密數據
- 小結
- 國際化和本地化
- 設置默認地區
- 本地化資源
- 國際化站點
- 小結
- 錯誤處理,調試和測試
- 錯誤處理
- 使用GDB調試
- Go怎么寫測試用例
- 小結
- 部署與維護
- 應用日志
- 網站錯誤處理
- 應用部署
- 備份和恢復
- 小結
- 如何設計一個Web框架
- 項目規劃
- 自定義路由器設計
- controller設計
- 日志和配置設計
- 實現博客的增刪改
- 小結
- 擴展Web框架
- 靜態文件支持
- Session支持
- 表單支持
- 用戶認證
- 多語言支持
- pprof支持
- 小結
- 參考資料