# Cldr Trans

[](https://hex.pm/packages/ex_cldr_trans)
[](https://hex.pm/packages/ex_cldr_trans)
[](https://hex.pm/packages/ex_cldr_trans)
[](https://hex.pm/packages/ex_cldr_trans)
## Attribution
`ex_cldr_trans` is an `ex_cldr`-integrated fork of the excellent [trans](https://github.com/crbelaus/trans) by [@crbelaus](https://github.com/crbelaus). The enhancements in this library have been been submitted as a [PR](https://github.com/crbelaus/trans/pull/74) to `trans`. If the PR is accepted in the future then this library will revert to depending on it rather than maintaining a fork. Such a change will not affect the functionality or API in this library.
The documentation in `cldr_trans` is edited from the original `trans` documentation.
### Introduction
`ex_cldr_trans` provides a way to manage and query translations embedded into schemas
and removes the necessity of maintaining extra tables only for translation storage. It is an addon library to [ex_cldr](https://hex.pm/packages/ex_cldr).
`ex_cldr_trans` is published on [hex.pm](https://hex.pm/packages/ex_cldr_trans) and the documentation
is also [available online](https://hexdocs.pm/ex_cldr_trans/).
## Optional Requirements
Having Ecto SQL and Postgrex in your application will allow you to use the `Cldr.Trans.QueryBuilder`
component to generate database queries based on translated data. You can still
use the `Cldr.Trans.Translator` component without those dependencies though.
- [Ecto SQL](https://hex.pm/packages/ecto_sql) 3.0 or higher
- [PostgreSQL](https://hex.pm/packages/postgrex) 9.4 or higher (since `Cldr.Trans` leverages the JSONB datatype)
## Why CLDR Trans?
The traditional approach to content internationalization consists on using an
additional table for each translatable schema. This table works only as a storage
for the original schema translations. For example, we may have a `posts` and
a `posts_translations` tables.
This approach has a few disadvantages:
- It complicates the database schema because it creates extra tables that are
coupled to the "main" ones.
- It makes migrations and schemas more complicated, since we always have to keep
the two tables in sync.
- It requires constant JOINs in order to filter or fetch records along with their
translations.
The approach used by `Cldr.Trans` is based on modern RDBMSs support for unstructured
datatypes. Instead of storing the translations in a different table, each
translatable schema has an extra column that contains all of its translations.
This approach drastically reduces the number of required JOINs when filtering or
fetching records.
`Cldr.Trans` is lightweight and modularized. The `Cldr.Trans` module provides metadata
that is used by the `Cldr.Trans.Translator` and `Cldr.Trans.QueryBuilder` modules, which
implement the main functionality of this library.
## Quickstart
Imagine that we have an `Article` schema that we want to translate:
```elixir
defmodule MyApp.Article do
use Ecto.Schema
schema "articles" do
field :title, :string
field :body, :string
end
end
```
### Add a JSON column
The first step would be to add a new JSON column to the table so we can store the translations in it.
```elixir
defmodule MyApp.Repo.Migrations.AddTranslationsToArticles do
use Ecto.Migration
def change do
alter table(:articles) do
add :translations, :map
end
end
end
```
### Generate database function migration
`ex_cldr_trans` defines a Postgres database function to support in-db field translation. A migration task is provided to generate the migration required to define this function.
```elixir
% MIX_ENV=test mix cldr.trans.gen.translate_function
* creating priv/repo/migrations
* creating priv/repo/migrations/20220307212312_trans_gen_translate_function.exs
```
### Run migrations
Migrate the database to add the translations column and define the database function.
```elixir
% mix ecto.migrate
```
### Define a backend module
The next step is to define an [ex_cldr](https://hex.pm/packages/ex_cldr) [backend module](https://hexdocs.pm/ex_cldr/readme.html#backend-module-configuration) that defines the configured locales and other information for supporting localised applications. For example:
```elixir
defmodule MyApp.Cldr do
use Cldr,
locales: ["en", "de", "ja", "en-AU", "th", "ar", "pl", "doi", "fr-CA", "nb", "no"],
providers: [Cldr.Trans]
end
```
Note that for existing backend modules the only required step is to add `Cldr.Trans` to the list of `:providers`.
### Add translations to schema
Once we have the new database column and the backend module, we can update the Article schema to include the translations:
```elixir
defmodule MyApp.Article do
use Ecto.Schema
use MyApp.Cldr.Trans, translates: [:title, :body]
schema "articles" do
field :title, :string
field :body, :string
translations :translations
end
end
```
After doing this we can leverage the [Cldr.Trans.Translator](https://hexdocs.pm/ex_cldr_trans/Cldr.Trans.Translator.html) and [Cldr.Trans.QueryBuilder](https://hexdocs.pm/ex_cldr_trans/Cldr.Trans.QueryBuilder.html) modules to fetch and query translations from the database.
The translation storage can be managed using normal `Ecto.Changeset` functions just like any other field.