Current section

Files

Jump to
translecto lib translecto.ex
Raw

lib/translecto.ex

defmodule Translecto do
@moduledoc """
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`.
"""
end