# `MishkaCmsCore.Runtime.States.TranslationsState`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/states/translations_state.ex#L5)

ETS copy of `MishkaCmsCore.Runtime.Translation`, so `t/1` is answered without a query.

The same shape as `MishkaCmsCore.Runtime.States.SettingsState`, for the same reasons: loaded once
at boot, then kept current off the resource's own PubSub broadcasts, which reach every node — a
translation saved on one server is on all of them without a restart.

Each entry is `{{site_id, language, key}, value}`, `site_id` nil for a global row. Only rows that
HAVE a value are kept: a registered key nobody has translated is the same to `t/1` as no row at
all, and it would only cost memory.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `languages`

```elixir
@spec languages() :: [String.t()]
```

Every language a cached translation is written in.

# `lookup`

```elixir
@spec lookup(String.t() | nil, String.t(), String.t()) :: String.t() | nil
```

The value for `key` in `language` on `site_id`, falling back to the global row, else `nil`.

Two lookups at most, no GenServer hop. Never raises: a table that is not there yet is the same as
one with nothing in it, so a template rendered before this process starts shows its keys.

# `put`

```elixir
@spec put(String.t() | nil, String.t(), String.t(), String.t() | nil) :: :ok
```

Put one translation in the cache directly (test and seed helper).

# `refresh`

```elixir
@spec refresh() :: :ok
```

Reload every translation from the database.

# `start_link`

---

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