{"id":16828112,"url":"https://github.com/kataras/i18n","last_synced_at":"2025-03-17T04:31:44.525Z","repository":{"id":39588433,"uuid":"225164581","full_name":"kataras/i18n","owner":"kataras","description":":new: High-performant and powerful localization and internationalization support for Go","archived":false,"fork":false,"pushed_at":"2023-11-13T11:56:07.000Z","size":130,"stargazers_count":112,"open_issues_count":10,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-27T17:45:46.354Z","etag":null,"topics":["go","golang","i18n","iris","json","localization","middleware","toml","translate","yaml"],"latest_commit_sha":null,"homepage":"https://en.wikipedia.org/wiki/Website_localization","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kataras.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":"https://iris-go.com/donate"}},"created_at":"2019-12-01T13:17:46.000Z","updated_at":"2025-02-16T09:30:53.000Z","dependencies_parsed_at":"2024-06-18T16:56:22.564Z","dependency_job_id":null,"html_url":"https://github.com/kataras/i18n","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kataras%2Fi18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kataras%2Fi18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kataras%2Fi18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kataras%2Fi18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kataras","download_url":"https://codeload.github.com/kataras/i18n/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243841223,"owners_count":20356446,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","i18n","iris","json","localization","middleware","toml","translate","yaml"],"created_at":"2024-10-13T11:24:45.692Z","updated_at":"2025-03-17T04:31:44.236Z","avatar_url":"https://github.com/kataras.png","language":"Go","funding_links":["https://iris-go.com/donate"],"categories":[],"sub_categories":[],"readme":"# i18n (Go)\r\n\r\n[![build status](https://img.shields.io/github/actions/workflow/status/kataras/i18n/ci.yml?branch=master\u0026style=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)\r\n\r\nEfficient and easy to use localization and internationalization support for Go.\r\n\r\n## Installation\r\n\r\nThe only requirement is the [Go Programming Language](https://go.dev/dl).\r\n\r\n```sh\r\n$ go get github.com/kataras/i18n@latest\r\n```\r\n\r\n**Examples**\r\n\r\n- [Basic](_examples/basic)\r\n- [Template](_examples/template)\r\n- [Pluralization](_examples/plurals)\r\n    - [en-US/welcome.yml](_examples/plurals/locales/en-US/welcome.yml)\r\n    - [en-US/ini_example.ini](_examples/plurals/locales/en-US/ini_example.ini)\r\n- [HTTP](_examples/http)\r\n- [Embedded Locales](_examples/embedded-files)\r\n\r\n## Getting started\r\n\r\nCreate a folder named `./locales` and put some `YAML`, `TOML`, `JSON` or `INI` files.\r\n\r\n```sh\r\n│   main.go\r\n└───locales\r\n    ├───el-GR\r\n    │       example.yml\r\n    ├───en-US\r\n    │       example.yml\r\n    └───zh-CN\r\n            example.yml\r\n```\r\n\r\nNow, put the key-values content for each locale, e.g. **./locales/en-US/example.yml** \r\n\r\n```yaml\r\nhi: \"Hi %s\"\r\n#\r\n# Templates are supported\r\n# hi: \"Hi {{ .Name }}\r\n#\r\n# Template functions are supported\r\n# hi: \"Hi {{sayHi .Name}}\r\n```\r\n\r\n```yaml\r\n# ./locales/el-GR/example.yaml\r\nhi: \"Γειά σου %s\"\r\n```\r\n\r\n```yaml\r\n# ./locales/zh-CN/example.yaml\r\nhi: 您好 %s\r\n```\r\n\r\nSome other possible filename formats...\r\n\r\n- _page.en.yaml_\r\n- _home.cart.el-GR.json_\r\n- _/el/file.tml_\r\n\r\n\u003e The language code MUST be right before the file extension.\r\n\r\nThe [Default](https://github.com/kataras/i18n/blob/master/i18n.go#L33) `I18n` instance will try to load locale files from `./locales` directory.\r\nUse 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**.\r\n\r\nLet's take a look at the simplest usage of this package.\r\n\r\n```go\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\r\n\t\"github.com/kataras/i18n\"\r\n)\r\n\r\ntype user struct {\r\n\tName string\r\n\tAge  int\r\n}\r\n\r\nfunc main() {\r\n\t// i18n.SetDefaultLanguage(\"en-US\")\r\n\r\n\t// Fmt style.\r\n\tenText := i18n.Tr(\"en\", \"hi\", \"John Doe\") // or \"en-US\"\r\n\telText := i18n.Tr(\"el\", \"hi\", \"John Doe\")\r\n\tzhText := i18n.Tr(\"zh\", \"hi\", \"John Doe\")\r\n\r\n\tfmt.Println(enText)\r\n\tfmt.Println(elText)\r\n\tfmt.Println(zhText)\r\n\r\n\t// Templates style.\r\n\ttemplateData := user{\r\n\t\tName: \"John Doe\",\r\n\t\tAge:  66,\r\n\t}\r\n\r\n\tenText = i18n.Tr(\"en-US\", \"intro\", templateData) // or \"en\"\r\n\telText = i18n.Tr(\"el-GR\", \"intro\", templateData)\r\n\tzhText = i18n.Tr(\"zh-CN\", \"intro\", templateData)\r\n\r\n\tfmt.Println(enText)\r\n\tfmt.Println(elText)\r\n\tfmt.Println(zhText)\r\n}\r\n```\r\n\r\nLoad specific languages over a **new I18n instance**. The default language is the first registered, in that case is the \"en-US\".\r\n\r\n```go\r\nI18n, err := i18n.New(i18n.Glob(\"./locales/*/*\"), \"en-US\", \"el-GR\", \"zh-CN\")\r\n```\r\n\r\nLoad embedded files through a go-bindata package:\r\n\r\n```go\r\nI18n, err := i18n.New(i18n.Assets(AssetNames, Asset), \"en-US\", \"el-GR\", \"zh-CN\")\r\n```\r\n\r\nLoad embedded files through Go's embed directive (**recommended**):\r\n\r\n```go\r\n//go:embed static/locales/*\r\nvar staticFS embed.FS\r\n\r\nloader, err := i18n.FS(staticFS, \"./static/locales/*/*.yml\")\r\n// [handle error...]\r\nI18n, err := i18n.New(loader, \"en-US\", \"el-GR\", \"zh-CN\")\r\n```\r\n\r\nLoad through a simple Go map:\r\n\r\n```go\r\nm := i18n.LangMap{\r\n    \"en-US\": i18n.Map{\r\n        \"buy\":               `buy %d`,\r\n        \"cart.checkout\":     `checkout - {{.Param}}`,\r\n        \"cart.after.thanks\": `thanks`,\r\n        //\r\n        \"JSONTemplateExample\":  `value of {{.Value}}`,\r\n        \"TypeOf\":               `type of %T`,\r\n        \"KeyOnlyOnDefaultLang\": `value`,\r\n        //\r\n        \"title\": `Title`,\r\n        \"hi\":    `Hi {{.Name}}`,\r\n        \"int\":   `1`,\r\n        \"hello\": `Hello %s`,\r\n        //\r\n        \"welcome\": `welcome`,\r\n    },\r\n    \"el-GR\": i18n.Map{\r\n        \"buy\":               `αγοράστε %d`,\r\n        \"cart.checkout\":     `ολοκλήρωση παραγγελίας - {{.Param}}`,\r\n        \"cart.after.thanks\": `ευχαριστούμε`,\r\n        //\r\n        \"JSONTemplateExample\": `τιμή του {{.Value}}`,\r\n        \"TypeOf\":              `τύπος %T`,\r\n        //\r\n        \"title\": `Τίτλος`,\r\n        \"hi\":    `Γειά σου {{.Name}}`,\r\n        \"int\":   `1`,\r\n        //\r\n        \"welcome\": `καλώς ήρθατε`,\r\n    },\r\n}\r\n\r\nloader := i18n.KV(m)\r\n\r\ni18N, err := i18n.New(loader, \"en-US\", \"el-GR\")\r\n```\r\n\r\n## Template variables \u0026 functions\r\n\r\nUsing **template variables \u0026 functions** as values in your locale value entry via `LoaderConfig`.\r\n\r\nWe 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.\r\n\r\nBefore we get started, install the necessary packages:\r\n\r\n```sh\r\n$ go get github.com/kataras/i18n@master\r\n$ go get github.com/gertd/go-pluralize@master\r\n```\r\n\r\nLet's create two simple translation files for our example. The `./locales/en-US/welcome.yml` and `./locales/el-GR/welcome.yml` respectfully:\r\n\r\n```yml\r\nDog: \"dog\"\r\nHiDogs: Hi {{plural (tr \"Dog\") .count }}\r\n```\r\n\r\n```yml\r\nDog: \"σκυλί\"\r\nHiDogs: Γειά {{plural (tr \"Dog\") .count }}\r\n```\r\n\r\n\u003e 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.\r\n\r\nNow, create a `main.go` file and store the following contents:\r\n\r\n```go\r\npackage main\r\n\r\nimport (\r\n    \"fmt\"\r\n    \"text/template\"\r\n\r\n    \"github.com/kataras/i18n\"\r\n    \"github.com/gertd/go-pluralize\"\r\n)\r\n\r\nvar pluralizeClient = pluralize.NewClient()\r\n\r\nfunc getFuncs(current *i18n.Locale) template.FuncMap {\r\n    return template.FuncMap{\r\n        \"plural\": func(word string, count int) string {\r\n            return pluralizeClient.Pluralize(word, count, true)\r\n        },\r\n    }\r\n}\r\n\r\nfunc main() {\r\n    I18n, err := i18n.New(i18n.Glob(\"./locales/*/*\", i18n.LoaderConfig{\r\n        // Set custom functions per locale!\r\n        Funcs: getFuncs,\r\n    }), \"en-US\", \"el-GR\", \"zh-CN\")\r\n    if err != nil {\r\n        panic(err)\r\n    }\r\n\r\n    textEnglish := I18n.Tr(\"en\", \"HiDogs\", map[string]interface{}{\r\n        \"count\": 2,\r\n    }) // prints \"Hi 2 dogs\".\r\n    fmt.Println(textEnglish)\r\n\r\n    textEnglishSingular := I18n.Tr(\"en\", \"HiDogs\", map[string]interface{}{\r\n        \"count\": 1,\r\n    }) // prints \"Hi 1 dog\".\r\n    fmt.Println(textEnglishSingular)\r\n\r\n    textGreek := I18n.Tr(\"el\", \"HiDogs\", map[string]interface{}{\r\n        \"count\": 1,\r\n    }) // prints \"Γειά 1 σκυλί\".\r\n    fmt.Println(textGreek)\r\n}\r\n```\r\n\r\nUse `go run main.go` to run our small Go program. The output should look like this:\r\n\r\n```sh\r\nHi 2 dogs\r\nHi 1 dog\r\nΓειά 1 σκυλί\r\n```\r\n\r\n## HTTP\r\n\r\nHTTP, automatically searches for url parameter, cookie, custom function and headers for the current user language.\r\n\r\n```go\r\nmux := http.NewServeMux()\r\n\r\nI18n.URLParameter = \"lang\" // i.e https://domain.com?lang=el\r\nI18n.Cookie = \"lang\"\r\nI18n.ExtractFunc = func(r *http.Request) string { /* custom logic */ }\r\n\r\nmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\r\n    translated := I18n.GetMessage(r, \"hi\", \"John Doe\")\r\n    fmt.Fprintf(w, \"Text: %s\", translated)\r\n})\r\n```\r\n\r\nPrefer `GetLocale` if more than one `GetMessage` call.\r\n\r\n```go\r\nmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\r\n    locale := I18n.GetLocale(r)\r\n    translated := locale.GetMessage(\"hi\", \"John Doe\")\r\n    // [...some locale.GetMessage calls]\r\n})\r\n```\r\n\r\nOptionally, identify the current language by subdomain or path prefix, e.g.\r\nen.domain.com and domain.com/en or domain.com/en-US and e.t.c.\r\n\r\n```go\r\nI18n.Subdomain = true\r\n\r\nhttp.ListenAndServe(\":8080\", I18n.Router(mux))\r\n```\r\n\r\nIf the `ContextKey` field is not empty then the `Router` will set the current language.\r\n\r\n```go\r\nI18n.ContextKey = \"lang\" \r\n\r\nmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\r\n    currentLang := r.Context().Value(\"lang\").(string)\r\n    fmt.Fprintf(w, \"Language: %s\", currentLang)\r\n})\r\n```\r\n\r\nSet the translate function as a key on a `HTML Template`.\r\n\r\n```go\r\ntemplates, _ := template.ParseGlob(\"./templates/*.html\")\r\n\r\nmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\r\n    // per-request.\r\n    translateFunc := I18n.GetLocale(r).GetMessage\r\n\r\n    templates.ExecuteTemplate(w, \"index.html\", map[string]interface{}{\r\n        \"tr\": translateFunc,\r\n    })\r\n\r\n    // {{ call .tr \"hi\" \"John Doe\" }}\r\n})\r\n```\r\n\r\nGlobal function with the language as its first input argument.\r\n\r\n```go\r\ntranslateLangFunc := I18n.Tr\r\ntemplates.Funcs(template.FuncMap{\r\n    \"tr\": translateLangFunc,\r\n})\r\n\r\n// {{ tr \"en\" \"hi\" \"John Doe\" }}\r\n```\r\n\r\nFor 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.\r\n\r\n## License\r\n\r\nkataras/i18n is free and open-source software licensed under the [MIT License](https://tldrlegal.com/license/mit-license).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkataras%2Fi18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkataras%2Fi18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkataras%2Fi18n/lists"}