go-i18n is a Go package and a command that can be used to translate Go programs into multiple languages.
Requires Go 1.2.
- Implements CLDR plural rules.
- Uses text/template for strings with variables.
- Translation files are simple JSON.
- Documented and tested!
The i18n package provides runtime APIs for looking up translated strings.
import "github.com/nicksnyder/go-i18n/i18n"
Load translation files during your program's initialization. The name of a translation file must contain a supported language tag.
i18n.MustLoadTranslationFile("path/to/fr-FR.all.json")
Tfunc returns a function that can lookup the translation of a string for that locale. It accepts one or more locale parameters so you can gracefully fallback to other locales.
userLocale = "ar-AR" // user preference, accept header, language cookie
defaultLocale = "en-US" // known valid locale
T, err := i18n.Tfunc(userLocale, defaultLocale)
Use the translation function to fetch the translation of a string.
fmt.Println(T("Hello world"))
Usually it is a good idea to identify strings by a generic id rather than the English translation, but the rest of this document will continue to use the English translation for readability.
T("program_greeting")
You can have variables in your string using text/template syntax.
T("Hello {{.Person}}", map[string]interface{}{
"Person": "Bob",
})
Each language handles pluralization differently. A few examples:
- English treats one as singular and all other numbers as plural (e.g. 0 cats, 1 cat, 2 cats).
- French treats zero as singular.
- Japan has a single plural form for all numbers.
- Arabic has six different plural forms!
The translation function handles all of this logic for you.
T("You have {{.Count}} unread emails", 2)
T("I am {{.Count}} meters tall.", "1.7")
With variables:
T("{{.Person}} has {{.Count}} unread emails", 2, map[string]interface{}{
"Person": "Bob",
})
Sentences with multiple plural components can be supported with nesting.
T("{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.", 3, map[string]interface{}{
"Person": "Bob",
"Timeframe": T("{{.Count}} days", 2),
})
A complete example is here.
You can call the .Funcs()
method on a text/template or html/template to register the translation function for usage inside of that template.
A complete example is here.
The goi18n command provides functionality for managing the translation process.
Make sure you have setup GOPATH.
go get -u github.com/nicksnyder/go-i18n/goi18n
goi18n -help
A typical workflow looks like this:
-
Add a new string to your source code.
T("settings_title")
-
Add the string to en-US.all.json
[ { "id": "settings_title", "translation": "Settings" } ]
-
Run goi18n
goi18n path/to/*.all.json
-
Send
path/to/*.untranslated.json
to get translated. -
Run goi18n again to merge the translations
goi18n path/to/*.all.json path/to/*.untranslated.json
A translation file stores translated and untranslated strings.
Example:
[
{
"id": "d_days",
"translation": {
"one": "{{.Count}} day",
"other": "{{.Count}} days"
}
},
{
"id": "my_height_in_meters",
"translation": {
"one": "I am {{.Count}} meter tall.",
"other": "I am {{.Count}} meters tall."
}
},
{
"id": "person_greeting",
"translation": "Hello {{.Person}}"
},
{
"id": "person_unread_email_count",
"translation": {
"one": "{{.Person}} has {{.Count}} unread email.",
"other": "{{.Person}} has {{.Count}} unread emails."
}
},
{
"id": "person_unread_email_count_timeframe",
"translation": {
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
}
},
{
"id": "program_greeting",
"translation": "Hello world"
},
{
"id": "your_unread_email_count",
"translation": {
"one": "You have {{.Count}} unread email.",
"other": "You have {{.Count}} unread emails."
}
}
]
- Arabic (
ar
) - Catalan (
ca
) - Chinese (simplified and traditional) (
zh
) - Czech (
cs
) - Danish (
da
) - Dutch (
nl
) - English (
en
) - French (
fr
) - German (
de
) - Italian (
it
) - Japanese (
ja
) - Lithuanian (
lt
) - Portuguese (
pt
) - Portuguese (Brazilian) (
pt-BR
) - Spanish (
es
)
More languages are straightforward to add:
-
Lookup the language's CLDR plural rules.
-
Add the language to language.go:
var languages = map[string]*Language{ // ... "en": &Language{ ID: "en", Name: "English", PluralCategories: newSet(plural.One, plural.Other), PluralFunc: func(ops *plural.Operands) plural.Category { if ops.I == 1 && ops.V == 0 { return plural.One } return plural.Other }, }, // ... }
-
Add a test to language_test.go
-
Submit a pull request!
go-i18n is available under the MIT license. See the LICENSE file for more info.