# `AshGettext`
[🔗](https://github.com/Undeadlol1/ash_gettext/blob/v0.1.0/lib/ash_gettext.ex#L1)

Translate the text an Ash app shows: strings, plurals, enum labels and attribute labels.

Enum values translate themselves: see `AshGettext.Enum`.

    AshGettext.translate(MyApp.Gettext, "default", "Order shipped", [], "ru")
    #=> "Заказ отправлен"

Every input is an argument, including the language, and nothing is read
from global state. So a translation works the same from any process, and a
test of one is a single assertion with no setup.

The text you write is the msgid. In the source language (the backend's
configured `:default_locale`, else the global `:gettext` one, else `"en"`)
it is also the translation, so that language needs no catalog.

## Missing translations are observable

`translate_or_missing/5` reports `{:missing, fallback}` rather than silently
handing back the msgid, so a test can assert that a string really *is*
covered in a locale:

    assert {:ok, _} = AshGettext.translate_or_missing(MyApp.Gettext, "default", "Order shipped", [], "ru")

The detection is gettext's own signal: a lookup that misses returns the msgid
unchanged. In the source locale `translate_or_missing/5` always reports
`:ok`. In a translated locale, an *identity* translation (a catalog mapping a
msgid to itself) is indistinguishable from a miss and is reported as
`:missing`. Use `translate/5` when you only want the string.

To translate Ash's error messages as well, see `AshGettext.Domain`.

# `backend`

```elixir
@type backend() :: module()
```

# `bindings`

```elixir
@type bindings() :: Keyword.t() | map()
```

# `locale`

```elixir
@type locale() :: String.t()
```

# `msgid`

```elixir
@type msgid() :: String.t() | atom()
```

# `text_domain`

```elixir
@type text_domain() :: String.t()
```

# `attribute_label`

```elixir
@spec attribute_label(module(), atom()) :: String.t()
```

The translated label of a resource attribute, in Gettext's current language.

The text is the one you wrote in the resource's `gettext` block
(`label :delivery_date, "Delivery date"`). It is never made from the
attribute's code name. The backend and text domain come from the resource's
domain (`AshGettext.Domain`). Misses fall back to the written text and are
reported through telemetry. Raises `ArgumentError` for an unknown attribute,
an attribute with no written label, or a resource whose domain has no
`gettext` block.

# `attribute_label_or_missing`

```elixir
@spec attribute_label_or_missing(module(), atom()) ::
  {:ok, String.t()} | {:missing, String.t()}
```

The label of a resource attribute, reporting whether the catalog covered it.

# `known_locales`

```elixir
@spec known_locales(backend()) :: [locale()]
```

The locales `backend` ships catalogs for.

Derived from the backend rather than re-declared in config, so the supported
list can never drift from the catalogs on disk.

# `source_locale`

```elixir
@spec source_locale(backend()) :: locale()
```

The backend's source locale: the language its msgids are written in, which
needs no catalog.

# `translate`

```elixir
@spec translate(backend(), text_domain(), msgid(), bindings(), locale()) :: String.t()
```

Translate `msgid` and return the string, falling back to the msgid on a miss.

# `translate_or_missing`

```elixir
@spec translate_or_missing(backend(), text_domain(), msgid(), bindings(), locale()) ::
  {:ok, String.t()} | {:missing, String.t()}
```

Translate `msgid`, reporting whether the catalog actually covered it.

# `translate_plural`

```elixir
@spec translate_plural(
  backend(),
  text_domain(),
  msgid(),
  msgid(),
  non_neg_integer(),
  bindings(),
  locale()
) :: String.t()
```

Translate a pluralised `msgid`, returning the string.

`count` is always available to the catalog as the `%{count}` binding, and it
wins over a `:count` the caller happens to pass in bindings — the number that
selected the plural form is the number the sentence shows.

# `translate_plural_or_missing`

```elixir
@spec translate_plural_or_missing(
  backend(),
  text_domain(),
  msgid(),
  msgid(),
  non_neg_integer(),
  bindings(),
  locale()
) :: {:ok, String.t()} | {:missing, String.t()}
```

Translate a pluralised `msgid`, reporting whether the catalog covered it.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
