Translecto
Translecto is a minimal translation library for Ecto to allow for translations at the database level.
It takes a fairly simplistic approach to supporting this. The general idea is that your model has fields that it wishes to be translatable, these fields reference translation models (or model) which contain the translatable terms grouped by :translate_id
and :locale_id
.
The :translate_id
is the logical grouping of translatable data. While the :locale_id
is the value (FK, string, integer, etc.) that distinguishes the specific translation for the given locale.
Locale
The locale is used to specify a specific localised translation. A locale may be a model which contains the different locales, or it may be another type that will be stored with the translation itself. Locales can apply globally or they may be different per translation. A globally applied locale can be specified in the config file by doing the following:
config :translecto,
locale: [schema: { :model, Model.Locale }, db: { :table, :locales }]
The :schema
field indicates the locale type that is applied to schemas, while the :db
field indicates the locale type that is applied to the database (migration) files. For more info on the type of input see Translecto.Schema.Translation.translation/1
and Translecto.Migration.translation/1
.
Translations
A translation is the model representing translated data. Multiple models may be used to store translations (possibly per context) or a single model can be used. To create a translation model you create a translation table and schema accordingly.
defmodule Repo.Migrations.CreateItem.Content.Translations do
use Ecto.Migration
import Translecto.Migration
def change do
create table(:item_content_translations, primary_key: false) do
translation
add :name, :string,
null: false
add :description, :string,
null: false
timestamps
end
end
end
defmodule Item.Content.Translation do
use Ecto.Schema
use Translecto.Schema.Translation
schema "food_diet_list" do
translation
field :name, :string
field :description, :string
timestamps
end
def changeset(struct, params \\ %{}) do
struct
|> translation_changeset(params)
|> cast(params, [:name, :description])
|> validate_required([:name, :description])
end
end
Translatables
A translatable is a field that has translatable data. It references a group of rows from a translation model (by :translate_id
), only needing the :locale_id
to indicate the relevant localisation.
defmodule Repo.Migrations.CreateItem do
use Ecto.Migration
import Translecto.Migration
def change do
create table(:items) do
translate :content,
null: false
# ... other fields
timestamps
end
end
end
defmodule Item do
use Ecto.Schema
use Translecto.Schema.Translatable
schema "items" do
translatable :content, Item.Content.Translation
# ... other fields
timestamps
end
def changeset(struct, params \\ %{}) do
struct
|> translatable_changeset(params, [:content])
|> validate_required([:content])
# |> constraints/validations for other fields
end
end
Insertion
To insert stuff you simply insert the translation data into the translation model using the correct grouping (:translate_id
, :locale_id
).
content = Repo.insert! Item.Content.Translation.changeset(%Item.Content.Translation{}, %{ locale_id: 1, name: "1_1_name", description: "1_1_desc" })
Repo.insert! Item.Content.Translation.changeset(%Item.Content.Translation{}, %{ translate_id: content.translate_id, locale_id: 2, name: "1_2_name", description: "1_2_desc" })
Repo.insert! Item.changeset(%Item{}, %{ content: content.translate_id })
Querying
To simplify querying of translatable fields, the from query syntax has been
extended to introduce a :locale
field, and a :translate
field. The :locale
or :locales
field specifies the current :locale_id
or list of :locale_id
's, while the :translate
or :must_translate
field maps a model's translatable field to a new name.
from item in Item,
locale: 1,
translate: content in item.content,
select: { content.name, content.description }
For more info on the type of fields see Translecto.Query.from/2
.
Installation
defp deps do
[{ :translecto, "~> 0.3.2" }]
end