View Source Trans (Trans v3.0.0)

Manage translations embedded into structs.

Although it can be used with any struct Trans shines when paired with an Ecto.Schema. It allows you to keep the translations into a field of the schema and avoids requiring extra tables for translation storage and complex joins when retrieving translations from the database.

Trans is split into two main components:

When used, Trans accepts the following options:

  • :translates (required) - list of the fields that will be translated.
  • :container (optional) - name of the field that contains the embedded translations. Defaults to:translations.
  • :default_locale (optional) - declares the locale of the base untranslated column.

storing-translations

Storing translations

To store translations in a schema you must use the translations macro:

defmodule MyApp.Article do
  use Ecto.Schema
  use Trans, translates: [:title, :body], default_locale: :en

  schema "articles" do
    field :title, :string
    field :body, :string

    translations [:es, :fr]
  end
end

This is equivalent to:

defmodule MyApp.Article do
  use Ecto.Schema
  use Trans, translates: [:title, :body], default_locale: :en

  schema "articles" do
    field :title, :string
    field :body, :string

    embeds_many :translations, Translations, primary_key: :false do
      embeds_one :es, Fields
      embeds_one :fr, Fields
    end
  end
end

defmodule MyApp.Article.Translations.Fields do
  use Ecto.Schema

  embedded_schema do
    field :title, :string
    field :body, :string
  end
end

If you want to customize the translation fields (for example how they are casted) you may define them yourself manually. In such cases you may tell Trans not to generate the fields automatically for you:

defmodule MyApp.Article do
  use Ecto.Schema
  use Trans, translates: [:title, :body], default_locale: :en

  schema "articles" do
    field :title, :string
    field :body, :string

    # Define MyApp.Article.Translations.Fields yourself
    translations [:es, :fr], build_field_schema: false
  end
end

the-translation-container

The translation container

As we have seen in the previous examples, Trans automatically stores and looks for translations in a field called :translations. This is known as the translations container.

In certain cases you may want to use a different field for storing the translations, this can be specified when using Trans in your module.

# Use the field `:locales` as translation container instead of the default `:translations`
use Trans, translates: [...], container: :locales

reflection

Reflection

Any module that uses Trans will have an autogenerated __trans__ function that can be used for runtime introspection of the translation metadata.

  • __trans__(:fields) - Returns the list of translatable fields.
  • __trans__(:container) - Returns the name of the translation container.
  • __trans__(:default_locale) - Returns the name of default locale.

Link to this section Summary

Types

A locale that may be a string or an atom

When translating or querying either a single locale or a list of locales can be provided

A translatable struct that uses Trans

Functions

Checks whether the given field is translatable or not.

Create the translation container and fields.

Link to this section Types

@type locale() :: String.t() | atom()

A locale that may be a string or an atom

@type locale_list() :: locale() | [locale(), ...]

When translating or querying either a single locale or a list of locales can be provided

@type translatable() :: struct()

A translatable struct that uses Trans

Link to this section Functions

Link to this function

translatable?(module_or_translatable, field)

View Source
@spec translatable?(module() | translatable(), locale()) :: boolean()

Checks whether the given field is translatable or not.

Returns true if the given field is translatable. Raises if the given module or struct does not use Trans.

examples

Examples

Assuming the Article schema defined before.

If we want to know whether a certain field is translatable or not we can use this function as follows:

iex> Trans.translatable?(Article, :title)
true
iex> Trans.translatable?(%Article{}, :not_existing)
false

Raises if the given module or struct does not use Trans:

iex> Trans.translatable?(Date, :day)
** (RuntimeError) Elixir.Date must use `Trans` in order to be translated
Link to this macro

translations(locales, options \\ [])

View Source (macro)

Create the translation container and fields.

This macro creates a field named like the module's translation container to store the translations. By default YourModule.Translations and YourModule.Translations.Fields schemas will be created.

This macro creates an embedded field named after your "translation container" of type YourModule.Translations. This field in turn has an embedded field for each locale of type YourModule.Translations.Fields.

Calling:

translations [:en, :es]

Is equivalent to:

embeds_one :translations, Translations do
  embeds_one :en, Fields
  embeds_one :es, Fields
end

options

Options

  • build_field_schema (boolean / default: false) wether to automatically generate the module for locales or not. Set this to false if you want to customize how the field translations are stored and keep in mind that you must create a YourModule.Translations.Fields schema.