# How to Localize

The `*i18n.Localizer` returned by the `bot.SettingsProvider` we created on the previous page is now available in the `*plugin.Context`.

## Using the `Localizer`

Localized text is generated using `*i18n.Config`s. Usually, these are placed in a `terms.go` file in your package. If you have many configs, it might also be advisable to group terms into `foo_terms.go`, `bar_terms.go` etc.

In your command's `Invoke` method, you can then use those `*i18n.Configs` to generate messages.

{% code title="plugins/sum/terms.go" %}

```go
package sum

import "github.com/mavolin/adam/pkg/i18n"

var (
    shortDescription = i18n.NewFallbackConfig(
        "plugin.sum.short_description", "Add numbers together")
    
    argsNumbersName = i18n.NewFallbackConfig(
        "plugin.sum.args.numbers.name", "Numbers")
    argsNumbersDescription = i18n.NewFallbackConfig(
        "plugin.sum.arg.numbers.description", 
        "The numbers that shall be added.")
)

var (
    errorNotEnoughNumbers = i18n.NewFallbackConfig(
        "plugin.sum.error.not_enough_numbers", // term
        "I need at least 2 numbers to calculate a sum!") // fallback
    
    result = i18n.NewFallbackConfig(
        "plugin.sum.result", "The sum is {{.sum}}.")
)

// The recommended way to fill placeholders is by using data structs.
// All exported fields will by put into snake_case and given to the Localizer
// as placeholders.
// If you want to use custom names, use the `i18n:"my_custom_name"` struct tag.

type resultPlaceholders struct {
    Sum int
}
```

{% endcode %}

{% code title="plugins/sum/sum.go" %}

```go
package sum

import (
    "github.com/mavolin/adam/pkg/i18n"
    "github.com/mavolin/adam/pkg/impl/arg"
)

type Sum struct {
    command.Meta
}

func New() *Sum {
    return &Sum{
        Meta: command.LocalizedMeta{
            Name: "sum",
            ShortDescription: shortDescription,
            Args: &arg.LocalizedConfig{
                RequiredArgs: []arg.LocalizedRequiredArg{
                    {
                        Name: argsNumbersName,
                        Type: arg.Integer,
                        Description: argsNumbersDescription,
                    },
                },
                Variadic: true,
            },
        },
    }
}

func (s *Say) (_ *state.State, ctx *plugin.Context) (interface{}, error) {
    nums := ctx.Args.Ints(0)
    if len(nums) >= 1 {
        return nil, errors.NewUserErrorl(errorNotEnoughNumbers)
    }
    
    var sum int
    
    for _, num := range nums {
        sum += num
    }
    
    return result.WithPlaceholders(resultPlaceholders{
        Sum: sum,
    }, nil
}
```

{% endcode %}

## Working with `Localizer`s

As you might have already noticed, there are a lot of utilities for working with localized text. Structs typically come in two versions `X` and `LocalizedX` to provide localization support. If they are constructor-based, they might also use constructors like `NewX`, `NewXl`, and `NewXlt` where `NewX` creates an unlocalized version, `NexXl` uses a `*i18n.Config`, and `NewXlt` uses a `i18n.Term`.

The same also applies to other functions. For example `plugin.Context` provides `Reply`, `Replyl` and `Replylt`.
