Localization feature provide a convenient way to retrieve strings in various languages, allowing you to easily support multiple languages within your application. Language strings are stored in files within the ./locales directory. Within this directory there should be a subdirectory for each language supported by the application:
The default language for your application is the first registered language.
app := iris.New()// First parameter: Glob filpath patern,// Second variadic parameter: Optional language tags,// the first one is the default/fallback one.app.I18n.Load("./locales/*/*", "en-US", "el-GR", "zh-CN")
Or if you load all languages by filename:
app.I18n.Load("./locales/*/*")// Then set the default language using:app.I18n.SetDefault("en-US")
Load embedded locales
You may want to embed locales with the new embed directive within your application executable.
Import the embed package; if you don’t use any exported identifiers from this package, you can do a blank import with _ "embed".
import ("embed")
Embed directives accept paths relative to the directory containing the Go source file. We can embed multiple files or even folders with wildcards. This uses a variable of the embed.FS type, which implements a simple virtual file system.
Instead of the Load method, we should use the LoadFS one.
err := app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini", "en-US", "el-GR")// OR to load all languages by filename:// app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini")// Then set the default language using:// app.I18n.SetDefault("en-US")
Defining Translations
Locale files can be written at YAML(recommended), JSON, TOML or INI form.
Each file should contain keys. Keys can have sub-keys(we call them "sections") too.
Each key's value should be of form string or map containing by its translated text (or template) or/and its pluralized key-values.
Iris i18n module supports pluralization out-of-the-box, see below.
Fmt Style
hi:"Hi %s!"
ctx.Tr("Hi", "John")// Outputs: Hi John!
Template
hi:"Hi {{.Name}}!"
ctx.Tr("Hi", iris.Map{"Name": "John"})// Outputs: Hi John!
Pluralization
Iris i18n supports plural variables. To define a per-locale variable you must define a new section of Vars key.
Then, each message can use this variable, here's how:
# Using variables in raw stringYouLate:"You are %[1]d ${Minutes} late."# [x] is the argument position,# variables always have priority other fmt-style arguments,# that's why we see [1] for houses and [2] for the string argument.HouseCount:"%[2]s has %[1]d ${Houses}."
ctx.Tr("YouLate", 1)// Outputs: You are 1 minute late.ctx.Tr("YouLate", 10)// Outputs: You are 10 minutes late.ctx.Tr("HouseCount", 2, "John")// Outputs: John has 2 houses.
You can select what message will be shown based on a given plural count.
Except variables, each message can also have its plural form too!
Acceptable keys:
zero
one
two
"=x"
"<x"
">x"
other
Let's create a simple plural-featured message, it can use the Minutes variable we created above too.
FreeDay:"=3":"You have three days and %[2]d ${Minutes} off."# "FreeDay" 3, 15one:"You have a day off."# "FreeDay", 1other:"You have %[1]d free days."# "FreeDay", 5
ctx.Tr("FreeDay", 3, 15)// Outputs: You have three days and 15 minutes off.ctx.Tr("FreeDay", 1)// Outputs: You have a day off.ctx.Tr("FreeDay", 5)// Outputs: You have 5 free days.
Let's continue with a bit more advanced example, using template text + functions + plural + variables.
Vars: - Houses:one:"house"other:"houses" - Gender:"=1":"She""=2":"He"VarTemplatePlural:one:"${Gender} is awesome!"other:"other (${Gender}) has %[3]d ${Houses}.""=5":"{{call .InlineJoin .Names}} are awesome."
const ( female =iota+1 male)ctx.Tr("VarTemplatePlural", iris.Map{"PluralCount": 5,"Names": []string{"John", "Peter"},"InlineJoin": func(arr []string) string {return strings.Join(arr, ", ") },})// Outputs: John, Peter are awesomectx.Tr("VarTemplatePlural", 1, female)// Outputs: She is awesome!ctx.Tr("VarTemplatePlural", 2, female, 5)// Outputs: other (She) has 5 houses.
Sections
If the key is not a reserved one (e.g. one, two...) then it acts as a sub section. The sections are separated by dot characters (.).
Welcome:Message:"Welcome {{.Name}}"
ctx.Tr("Welcome.Message", iris.Map{"Name": "John"})// Outputs: Welcome John
Determining The Current Locale
You may use the context.GetLocale method to determine the current locale or check if the locale is a given value:
// Locale is the interface which returns from a `Localizer.GetLocale` metod.// It serves the transltions based on "key" or format. See `GetMessage`.typeLocaleinterface {// Index returns the current locale index from the languages list.Index() int// Tag returns the full language Tag attached tothis Locale,// it should be uniue across different Locales.Tag() *language.Tag// Language should return the exact languagecode of this `Locale`//that the user provided on `New` function.//// Same as `Tag().String()` but it's static.Language() string// GetMessage should return translated text based n the given "key".GetMessage(key string, args ...interface{}) string}
Retrieving Translation
Use of context.Tr method as a shortcut to get a translated text for this request.
func(ctx iris.Context) { text := ctx.Tr("hi", "name")// [...]}