Trans v1.0.1 Trans.QueryBuilder

Provides functions for building Ecto queries with conditions on translated fields.

Summary

Functions

Adds a condition to the given query to filter only those records for which the field translation in the given locale matches the specified value using one of the available comparison operators

Adds a condition to the given query to filter only those schemas translated into the given locale

Functions

with_translation(query, locale, field, expected, opts \\ [])

Adds a condition to the given query to filter only those records for which the field translation in the given locale matches the specified value using one of the available comparison operators.

Usage example (basic)

Imagine that we have an Article schema wich has a title and a body that must be translated:

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

  schema "articles" do
    field :title, :string
    field :body, :string
    field :translations, :map
  end
end

We could then get only the articles for which the title in French matches “La République” like this:

iex> Article
...> |> Trans.QueryBuilder.with_translation(:es, :title, "La République")
...> |> Repo.all
[debug] SELECT a0."id", a0."title", a0."body", a0."translations"
        FROM "articles" AS a0
        WHERE (a0."translations"->$1->>$2 = $3) ["fr", "title", "La République"]
[debug] OK query=2.6ms queue=0.1ms

If we want to use a comparison with wilcards, we may specify a LIKE comparison:

iex> Article
...> |> Trans.QueryBuilder.with_translation(:es, :title, "%République%", type: :like)
...> |> Repo.all
[debug] SELECT a0."id", a0."title", a0."body", a0."translations"
        FROM "articles" AS a0
        WHERE (a0."translations"->$1->>$2 LIKE $3) ["fr", "title", "%République%"]
[debug] OK query=2.1ms queue=0.1ms

We can also perform a case insensitive comparison by using a ILIKE comparison:

iex> Article
...> |> Trans.QueryBuilder.with_translation(:es, :title, "%république%", type: :ilike)
...> |> Repo.all
[debug] SELECT a0."id", a0."title", a0."body", a0."translations"
        FROM "articles" AS a0
        WHERE (a0."translations"->$1->>$2 ILIKE $3) ["fr", "title", "%république%"]
[debug] OK query=2.1ms queue=0.1ms

Usage example (different translation container)

As stated in the documentation of Trans, the translation container is the field that contains the list of translations for the struct.

By default this function looks for the translations in a field called translations. If your struct stores the translations in a different field, it should be specified when calling this function.

Imagine that we have an Article schema like the previous example, but this time the translations will be stored in the field article_translations:

defmodule Article do
  use Ecto.Schema
  use Trans, defaults: [container: :article_translations],
    translates: [:title, :body]

  schema "articles" do
    field :title, :string
    field :body, :string
    field :article_translations, :map
  end
end

As in the previous example, we may want to fetch all articles whose title contains the word “république” by performing a case insensitive operation. This time we must also specify the translation container name:

iex> Article
...> |> Trans.QueryBuilder.with_translation(:fr, :title, "%république%", type: :ilike, container: :article_translations)
...> |> Repo.all
[debug] SELECT a0."id", a0."title", a0."body", a0."article_translations"
        FROM "articles" AS a0
        WHERE (a0."article_translations"->$1->>$2 ILIKE $3) ["fr", "title", "%république%"]
[debug] OK query=2.1ms queue=0.1ms

Having to repat constantly the name of the translation container can get tiresome quickly. You can avoid that by using the Trans module in your schema. Take a look at its documentation in order to see some examples.

with_translation_ilike(query, locale, field, expected, container)
with_translations(query, locale, opts \\ [])

Adds a condition to the given query to filter only those schemas translated into the given locale.

Usage example (basic)

Imagine that we have an Article schema wich has a title and a body that must be translated:

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

  schema "articles" do
    field :title, :string
    field :body, :string
    field :translations, :map
  end
end

We could then get only the articles that are translated into ES like this:

iex> Article
...> |> Trans.QueryBuilder.with_translations(:es)
...> |> Repo.all
[debug] SELECT a0."id", a0."title", a0."body", a0."translations"
        FROM "articles" AS a0
        WHERE ((a0."translations"->>$1) is not null) ["es"]
[debug] OK query=4.7ms queue=0.1ms

Usage example (different translation container)

As stated in the documentation of Trans, the translation container is the field that contains the list of translations for the struct.

By default this function looks for the translations in a field called translations. If your struct stores the translations in a different field, it should be specified when calling this function.

Imagine that we have an Article schema like the previous example, but this time the translations will be stored in the field article_translations:

defmodule Article do
  use Ecto.Schema
  use Trans, defaults: [container: :article_translations],
    translates: [:title, :body]

  schema "articles" do
    field :title, :string
    field :body, :string
    field :article_translations, :map
  end
end

Then, to get only the articles that are translated into ES we could use the same technique as in the first example, but specifying the container:

iex> Article
...> |> Trans.QueryBuilder.with_translations(:es, container: :article_translations)
...> |> Repo.all
[debug] SELECT a0."id", a0."title", a0."body", a0."article_translations"
        FROM "articles" AS a0
        WHERE ((a0."article_translations"->>$1) is not null) ["es"]
[debug] OK query=4.7ms queue=0.1ms

Having to repat constantly the name of the translation container can get tiresome quickly. You can avoid that by using the Trans module in your schema. Take a look at its documentation in order to see some examples.