# Documentation

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:

```bash
│   main.go
└───locales
    ├───el-GR
    │       home.yml
    ├───en-US
    │       home.yml
    └───zh-CN
            home.yml
```

The default language for your application is the first registered language.

```go
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:

```go
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](https://gobyexample.com/embed-directive) within your application executable.

1. Import the embed package; if you don’t use any exported identifiers from this package, you can do a blank import with \_ "embed".

```go
import (
    "embed"
)
```

2. 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.

```go
//go:embed embedded/locales/*
var embeddedFS embed.FS
```

3. Instead of the `Load` method, we should use the `LoadFS` one.

```go
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

```yaml
hi: "Hi %s!"
```

```go
ctx.Tr("Hi", "John")
// Outputs: Hi John!
```

### Template

```yaml
hi: "Hi {{.Name}}!"
```

```go
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.

The acceptable keys for variables are:

* `one`
* `"=x"` where x is a number
* `"<x"`
* `other`
* `format`

Example:

```yaml
Vars:
  - Minutes:
      one: "minute"
      other: "minutes"
  - Houses:
      one: "house"
      other: "houses"
```

Then, each message can use this variable, here's how:

```yaml
# Using variables in raw string
YouLate: "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}."
```

```go
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.

```yaml
FreeDay:
  "=3": "You have three days and %[2]d ${Minutes} off." # "FreeDay" 3, 15
  one:  "You have a day off." # "FreeDay", 1
  other: "You have %[1]d free days." # "FreeDay", 5
```

```go
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.

```yaml
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."
```

```go
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 awesome

ctx.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 (`.`).

```yaml
Welcome:
  Message: "Welcome {{.Name}}"
```

```go
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:

```go
func(ctx iris.Context) {
    locale := ctx.GetLocale()
    // [...]
}
```

The **Locale** interface looks like this.

```go
// Locale is the interface which returns from a `Localizer.GetLocale` metod.
// It serves the transltions based on "key" or format. See `GetMessage`.
type Locale interface {
    // 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.

```go
func(ctx iris.Context) {
    text := ctx.Tr("hi", "name")
    // [...]
}
```

## Inside Views

```go
func(ctx iris.Context) {
    ctx.View("index.html", iris.Map{
        "tr": ctx.Tr,
    })
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://iris-go.gitbook.io/iris/localization/i18n.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
