Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kataras/i18n
:new: High-performant and powerful localization and internationalization support for Go
https://github.com/kataras/i18n
go golang i18n iris json localization middleware toml translate yaml
Last synced: 3 months ago
JSON representation
:new: High-performant and powerful localization and internationalization support for Go
- Host: GitHub
- URL: https://github.com/kataras/i18n
- Owner: kataras
- License: mit
- Created: 2019-12-01T13:17:46.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-11-13T11:56:07.000Z (about 1 year ago)
- Last Synced: 2024-10-14T11:24:35.509Z (4 months ago)
- Topics: go, golang, i18n, iris, json, localization, middleware, toml, translate, yaml
- Language: Go
- Homepage: https://en.wikipedia.org/wiki/Website_localization
- Size: 127 KB
- Stars: 110
- Watchers: 4
- Forks: 13
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# i18n (Go)
[![build status](https://img.shields.io/github/actions/workflow/status/kataras/i18n/ci.yml?branch=master&style=for-the-badge)](https://github.com/kataras/i18n/actions) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/i18n) [![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/i18n) [![donate on Stripe](https://img.shields.io/badge/support-Stripe-blue.svg?style=for-the-badge)](https://iris-go.com/donate)
Efficient and easy to use localization and internationalization support for Go.
## Installation
The only requirement is the [Go Programming Language](https://go.dev/dl).
```sh
$ go get github.com/kataras/i18n@latest
```**Examples**
- [Basic](_examples/basic)
- [Template](_examples/template)
- [Pluralization](_examples/plurals)
- [en-US/welcome.yml](_examples/plurals/locales/en-US/welcome.yml)
- [en-US/ini_example.ini](_examples/plurals/locales/en-US/ini_example.ini)
- [HTTP](_examples/http)
- [Embedded Locales](_examples/embedded-files)## Getting started
Create a folder named `./locales` and put some `YAML`, `TOML`, `JSON` or `INI` files.
```sh
│ main.go
└───locales
├───el-GR
│ example.yml
├───en-US
│ example.yml
└───zh-CN
example.yml
```Now, put the key-values content for each locale, e.g. **./locales/en-US/example.yml**
```yaml
hi: "Hi %s"
#
# Templates are supported
# hi: "Hi {{ .Name }}
#
# Template functions are supported
# hi: "Hi {{sayHi .Name}}
``````yaml
# ./locales/el-GR/example.yaml
hi: "Γειά σου %s"
``````yaml
# ./locales/zh-CN/example.yaml
hi: 您好 %s
```Some other possible filename formats...
- _page.en.yaml_
- _home.cart.el-GR.json_
- _/el/file.tml_> The language code MUST be right before the file extension.
The [Default](https://github.com/kataras/i18n/blob/master/i18n.go#L33) `I18n` instance will try to load locale files from `./locales` directory.
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**.Let's take a look at the simplest usage of this package.
```go
package mainimport (
"fmt""github.com/kataras/i18n"
)type user struct {
Name string
Age int
}func main() {
// i18n.SetDefaultLanguage("en-US")// Fmt style.
enText := i18n.Tr("en", "hi", "John Doe") // or "en-US"
elText := i18n.Tr("el", "hi", "John Doe")
zhText := i18n.Tr("zh", "hi", "John Doe")fmt.Println(enText)
fmt.Println(elText)
fmt.Println(zhText)// Templates style.
templateData := user{
Name: "John Doe",
Age: 66,
}enText = i18n.Tr("en-US", "intro", templateData) // or "en"
elText = i18n.Tr("el-GR", "intro", templateData)
zhText = i18n.Tr("zh-CN", "intro", templateData)fmt.Println(enText)
fmt.Println(elText)
fmt.Println(zhText)
}
```Load specific languages over a **new I18n instance**. The default language is the first registered, in that case is the "en-US".
```go
I18n, err := i18n.New(i18n.Glob("./locales/*/*"), "en-US", "el-GR", "zh-CN")
```Load embedded files through a go-bindata package:
```go
I18n, err := i18n.New(i18n.Assets(AssetNames, Asset), "en-US", "el-GR", "zh-CN")
```Load embedded files through Go's embed directive (**recommended**):
```go
//go:embed static/locales/*
var staticFS embed.FSloader, err := i18n.FS(staticFS, "./static/locales/*/*.yml")
// [handle error...]
I18n, err := i18n.New(loader, "en-US", "el-GR", "zh-CN")
```Load through a simple Go map:
```go
m := i18n.LangMap{
"en-US": i18n.Map{
"buy": `buy %d`,
"cart.checkout": `checkout - {{.Param}}`,
"cart.after.thanks": `thanks`,
//
"JSONTemplateExample": `value of {{.Value}}`,
"TypeOf": `type of %T`,
"KeyOnlyOnDefaultLang": `value`,
//
"title": `Title`,
"hi": `Hi {{.Name}}`,
"int": `1`,
"hello": `Hello %s`,
//
"welcome": `welcome`,
},
"el-GR": i18n.Map{
"buy": `αγοράστε %d`,
"cart.checkout": `ολοκλήρωση παραγγελίας - {{.Param}}`,
"cart.after.thanks": `ευχαριστούμε`,
//
"JSONTemplateExample": `τιμή του {{.Value}}`,
"TypeOf": `τύπος %T`,
//
"title": `Τίτλος`,
"hi": `Γειά σου {{.Name}}`,
"int": `1`,
//
"welcome": `καλώς ήρθατε`,
},
}loader := i18n.KV(m)
i18N, err := i18n.New(loader, "en-US", "el-GR")
```## Template variables & functions
Using **template variables & functions** as values in your locale value entry via `LoaderConfig`.
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.
Before we get started, install the necessary packages:
```sh
$ go get github.com/kataras/i18n@master
$ go get github.com/gertd/go-pluralize@master
```Let's create two simple translation files for our example. The `./locales/en-US/welcome.yml` and `./locales/el-GR/welcome.yml` respectfully:
```yml
Dog: "dog"
HiDogs: Hi {{plural (tr "Dog") .count }}
``````yml
Dog: "σκυλί"
HiDogs: Γειά {{plural (tr "Dog") .count }}
```> 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.
Now, create a `main.go` file and store the following contents:
```go
package mainimport (
"fmt"
"text/template""github.com/kataras/i18n"
"github.com/gertd/go-pluralize"
)var pluralizeClient = pluralize.NewClient()
func getFuncs(current *i18n.Locale) template.FuncMap {
return template.FuncMap{
"plural": func(word string, count int) string {
return pluralizeClient.Pluralize(word, count, true)
},
}
}func main() {
I18n, err := i18n.New(i18n.Glob("./locales/*/*", i18n.LoaderConfig{
// Set custom functions per locale!
Funcs: getFuncs,
}), "en-US", "el-GR", "zh-CN")
if err != nil {
panic(err)
}textEnglish := I18n.Tr("en", "HiDogs", map[string]interface{}{
"count": 2,
}) // prints "Hi 2 dogs".
fmt.Println(textEnglish)textEnglishSingular := I18n.Tr("en", "HiDogs", map[string]interface{}{
"count": 1,
}) // prints "Hi 1 dog".
fmt.Println(textEnglishSingular)textGreek := I18n.Tr("el", "HiDogs", map[string]interface{}{
"count": 1,
}) // prints "Γειά 1 σκυλί".
fmt.Println(textGreek)
}
```Use `go run main.go` to run our small Go program. The output should look like this:
```sh
Hi 2 dogs
Hi 1 dog
Γειά 1 σκυλί
```## HTTP
HTTP, automatically searches for url parameter, cookie, custom function and headers for the current user language.
```go
mux := http.NewServeMux()I18n.URLParameter = "lang" // i.e https://domain.com?lang=el
I18n.Cookie = "lang"
I18n.ExtractFunc = func(r *http.Request) string { /* custom logic */ }mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
translated := I18n.GetMessage(r, "hi", "John Doe")
fmt.Fprintf(w, "Text: %s", translated)
})
```Prefer `GetLocale` if more than one `GetMessage` call.
```go
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
locale := I18n.GetLocale(r)
translated := locale.GetMessage("hi", "John Doe")
// [...some locale.GetMessage calls]
})
```Optionally, identify the current language by subdomain or path prefix, e.g.
en.domain.com and domain.com/en or domain.com/en-US and e.t.c.```go
I18n.Subdomain = truehttp.ListenAndServe(":8080", I18n.Router(mux))
```If the `ContextKey` field is not empty then the `Router` will set the current language.
```go
I18n.ContextKey = "lang"mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
currentLang := r.Context().Value("lang").(string)
fmt.Fprintf(w, "Language: %s", currentLang)
})
```Set the translate function as a key on a `HTML Template`.
```go
templates, _ := template.ParseGlob("./templates/*.html")mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// per-request.
translateFunc := I18n.GetLocale(r).GetMessagetemplates.ExecuteTemplate(w, "index.html", map[string]interface{}{
"tr": translateFunc,
})// {{ call .tr "hi" "John Doe" }}
})
```Global function with the language as its first input argument.
```go
translateLangFunc := I18n.Tr
templates.Funcs(template.FuncMap{
"tr": translateLangFunc,
})// {{ tr "en" "hi" "John Doe" }}
```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.
## License
kataras/i18n is free and open-source software licensed under the [MIT License](https://tldrlegal.com/license/mit-license).