README.md (10056B)
1 # i18n (Go) 2 3 [](https://github.com/kataras/i18n/actions) [](https://goreportcard.com/report/github.com/kataras/i18n) [](https://pkg.go.dev/github.com/kataras/i18n) [](https://iris-go.com/donate) 4 5 Efficient and easy to use localization and internationalization support for Go. 6 7 ## Installation 8 9 The only requirement is the [Go Programming Language](https://go.dev/dl). 10 11 ```sh 12 $ go get github.com/kataras/i18n@latest 13 ``` 14 15 **Examples** 16 17 - [Basic](_examples/basic) 18 - [Template](_examples/template) 19 - [Pluralization](_examples/plurals) 20 - [en-US/welcome.yml](_examples/plurals/locales/en-US/welcome.yml) 21 - [en-US/ini_example.ini](_examples/plurals/locales/en-US/ini_example.ini) 22 - [HTTP](_examples/http) 23 - [Embedded Locales](_examples/embedded-files) 24 25 ## Getting started 26 27 Create a folder named `./locales` and put some `YAML`, `TOML`, `JSON` or `INI` files. 28 29 ```sh 30 │ main.go 31 └───locales 32 ├───el-GR 33 │ example.yml 34 ├───en-US 35 │ example.yml 36 └───zh-CN 37 example.yml 38 ``` 39 40 Now, put the key-values content for each locale, e.g. **./locales/en-US/example.yml** 41 42 ```yaml 43 hi: "Hi %s" 44 # 45 # Templates are supported 46 # hi: "Hi {{ .Name }} 47 # 48 # Template functions are supported 49 # hi: "Hi {{sayHi .Name}} 50 ``` 51 52 ```yaml 53 # ./locales/el-GR/example.yaml 54 hi: "Γειά σου %s" 55 ``` 56 57 ```yaml 58 # ./locales/zh-CN/example.yaml 59 hi: 您好 %s 60 ``` 61 62 Some other possible filename formats... 63 64 - _page.en.yaml_ 65 - _home.cart.el-GR.json_ 66 - _/el/file.tml_ 67 68 > The language code MUST be right before the file extension. 69 70 The [Default](https://github.com/kataras/i18n/blob/master/i18n.go#L33) `I18n` instance will try to load locale files from `./locales` directory. 71 Use the `Tr` package-level function to translate a text based on the given language code. Use the `GetMessage` function to translate a text based on the incoming `http.Request`. Use the `Router` function to wrap an `http.Handler` (i.e an `http.ServeMux`) to set the language based on _path prefix_ such as `/zh-CN/some-path` and subdomains such as `zh.domain.com` **without the requirement of different routes per language**. 72 73 Let's take a look at the simplest usage of this package. 74 75 ```go 76 package main 77 78 import ( 79 "fmt" 80 81 "github.com/kataras/i18n" 82 ) 83 84 type user struct { 85 Name string 86 Age int 87 } 88 89 func main() { 90 // i18n.SetDefaultLanguage("en-US") 91 92 // Fmt style. 93 enText := i18n.Tr("en", "hi", "John Doe") // or "en-US" 94 elText := i18n.Tr("el", "hi", "John Doe") 95 zhText := i18n.Tr("zh", "hi", "John Doe") 96 97 fmt.Println(enText) 98 fmt.Println(elText) 99 fmt.Println(zhText) 100 101 // Templates style. 102 templateData := user{ 103 Name: "John Doe", 104 Age: 66, 105 } 106 107 enText = i18n.Tr("en-US", "intro", templateData) // or "en" 108 elText = i18n.Tr("el-GR", "intro", templateData) 109 zhText = i18n.Tr("zh-CN", "intro", templateData) 110 111 fmt.Println(enText) 112 fmt.Println(elText) 113 fmt.Println(zhText) 114 } 115 ``` 116 117 Load specific languages over a **new I18n instance**. The default language is the first registered, in that case is the "en-US". 118 119 ```go 120 I18n, err := i18n.New(i18n.Glob("./locales/*/*"), "en-US", "el-GR", "zh-CN") 121 ``` 122 123 Load embedded files through a go-bindata package: 124 125 ```go 126 I18n, err := i18n.New(i18n.Assets(AssetNames, Asset), "en-US", "el-GR", "zh-CN") 127 ``` 128 129 Load embedded files through Go's embed directive (**recommended**): 130 131 ```go 132 //go:embed static/locales/* 133 var staticFS embed.FS 134 135 loader, err := i18n.FS(staticFS, "./static/locales/*/*.yml") 136 // [handle error...] 137 I18n, err := i18n.New(loader, "en-US", "el-GR", "zh-CN") 138 ``` 139 140 Load through a simple Go map: 141 142 ```go 143 m := i18n.LangMap{ 144 "en-US": i18n.Map{ 145 "buy": `buy %d`, 146 "cart.checkout": `checkout - {{.Param}}`, 147 "cart.after.thanks": `thanks`, 148 // 149 "JSONTemplateExample": `value of {{.Value}}`, 150 "TypeOf": `type of %T`, 151 "KeyOnlyOnDefaultLang": `value`, 152 // 153 "title": `Title`, 154 "hi": `Hi {{.Name}}`, 155 "int": `1`, 156 "hello": `Hello %s`, 157 // 158 "welcome": `welcome`, 159 }, 160 "el-GR": i18n.Map{ 161 "buy": `αγοράστε %d`, 162 "cart.checkout": `ολοκλήρωση παραγγελίας - {{.Param}}`, 163 "cart.after.thanks": `ευχαριστούμε`, 164 // 165 "JSONTemplateExample": `τιμή του {{.Value}}`, 166 "TypeOf": `τύπος %T`, 167 // 168 "title": `Τίτλος`, 169 "hi": `Γειά σου {{.Name}}`, 170 "int": `1`, 171 // 172 "welcome": `καλώς ήρθατε`, 173 }, 174 } 175 176 loader := i18n.KV(m) 177 178 i18N, err := i18n.New(loader, "en-US", "el-GR") 179 ``` 180 181 ## Template variables & functions 182 183 Using **template variables & functions** as values in your locale value entry via `LoaderConfig`. 184 185 We are going to use a 3rd-party package for plural and singular words. Note that this is only for english dictionary, but you can use the `"current"` `Locale` and make a map with dictionaries to pluralize words based on the given language. 186 187 Before we get started, install the necessary packages: 188 189 ```sh 190 $ go get github.com/kataras/i18n@master 191 $ go get github.com/gertd/go-pluralize@master 192 ``` 193 194 Let's create two simple translation files for our example. The `./locales/en-US/welcome.yml` and `./locales/el-GR/welcome.yml` respectfully: 195 196 ```yml 197 Dog: "dog" 198 HiDogs: Hi {{plural (tr "Dog") .count }} 199 ``` 200 201 ```yml 202 Dog: "σκυλί" 203 HiDogs: Γειά {{plural (tr "Dog") .count }} 204 ``` 205 206 > The `tr` template function is a builtin function registered per locale. It returns the key's translated value. E.g. on english file the `tr "Dog"` returns the `Dog:`'s value: `"dog"` and on greek file it returns `"σκυλί"`. This function helps importing a key to another key to complete a sentence. 207 208 Now, create a `main.go` file and store the following contents: 209 210 ```go 211 package main 212 213 import ( 214 "fmt" 215 "text/template" 216 217 "github.com/kataras/i18n" 218 "github.com/gertd/go-pluralize" 219 ) 220 221 var pluralizeClient = pluralize.NewClient() 222 223 func getFuncs(current *i18n.Locale) template.FuncMap { 224 return template.FuncMap{ 225 "plural": func(word string, count int) string { 226 return pluralizeClient.Pluralize(word, count, true) 227 }, 228 } 229 } 230 231 func main() { 232 I18n, err := i18n.New(i18n.Glob("./locales/*/*", i18n.LoaderConfig{ 233 // Set custom functions per locale! 234 Funcs: getFuncs, 235 }), "en-US", "el-GR", "zh-CN") 236 if err != nil { 237 panic(err) 238 } 239 240 textEnglish := I18n.Tr("en", "HiDogs", map[string]interface{}{ 241 "count": 2, 242 }) // prints "Hi 2 dogs". 243 fmt.Println(textEnglish) 244 245 textEnglishSingular := I18n.Tr("en", "HiDogs", map[string]interface{}{ 246 "count": 1, 247 }) // prints "Hi 1 dog". 248 fmt.Println(textEnglishSingular) 249 250 textGreek := I18n.Tr("el", "HiDogs", map[string]interface{}{ 251 "count": 1, 252 }) // prints "Γειά 1 σκυλί". 253 fmt.Println(textGreek) 254 } 255 ``` 256 257 Use `go run main.go` to run our small Go program. The output should look like this: 258 259 ```sh 260 Hi 2 dogs 261 Hi 1 dog 262 Γειά 1 σκυλί 263 ``` 264 265 ## HTTP 266 267 HTTP, automatically searches for url parameter, cookie, custom function and headers for the current user language. 268 269 ```go 270 mux := http.NewServeMux() 271 272 I18n.URLParameter = "lang" // i.e https://domain.com?lang=el 273 I18n.Cookie = "lang" 274 I18n.ExtractFunc = func(r *http.Request) string { /* custom logic */ } 275 276 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 277 translated := I18n.GetMessage(r, "hi", "John Doe") 278 fmt.Fprintf(w, "Text: %s", translated) 279 }) 280 ``` 281 282 Prefer `GetLocale` if more than one `GetMessage` call. 283 284 ```go 285 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 286 locale := I18n.GetLocale(r) 287 translated := locale.GetMessage("hi", "John Doe") 288 // [...some locale.GetMessage calls] 289 }) 290 ``` 291 292 Optionally, identify the current language by subdomain or path prefix, e.g. 293 en.domain.com and domain.com/en or domain.com/en-US and e.t.c. 294 295 ```go 296 I18n.Subdomain = true 297 298 http.ListenAndServe(":8080", I18n.Router(mux)) 299 ``` 300 301 If the `ContextKey` field is not empty then the `Router` will set the current language. 302 303 ```go 304 I18n.ContextKey = "lang" 305 306 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 307 currentLang := r.Context().Value("lang").(string) 308 fmt.Fprintf(w, "Language: %s", currentLang) 309 }) 310 ``` 311 312 Set the translate function as a key on a `HTML Template`. 313 314 ```go 315 templates, _ := template.ParseGlob("./templates/*.html") 316 317 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 318 // per-request. 319 translateFunc := I18n.GetLocale(r).GetMessage 320 321 templates.ExecuteTemplate(w, "index.html", map[string]interface{}{ 322 "tr": translateFunc, 323 }) 324 325 // {{ call .tr "hi" "John Doe" }} 326 }) 327 ``` 328 329 Global function with the language as its first input argument. 330 331 ```go 332 translateLangFunc := I18n.Tr 333 templates.Funcs(template.FuncMap{ 334 "tr": translateLangFunc, 335 }) 336 337 // {{ tr "en" "hi" "John Doe" }} 338 ``` 339 340 For a more detailed technical documentation you can head over to our [godocs](https://pkg.go.dev/github.com/kataras/i18n). And for executable code you can always visit the [_examples](_examples) repository's subdirectory. 341 342 ## License 343 344 kataras/i18n is free and open-source software licensed under the [MIT License](https://tldrlegal.com/license/mit-license).