mathieuprog

mathieuprog

I18n Helpers - ease the use of embedded translations in Ecto Schemas

Hello everyone :wave:

I’ve been learning Elixir for a few months now and just published my first Hex package :tada:
Any feedback is welcome.

This library might be relevant to you if you need to store translations in the database (e.g. user-generated content), and want to store these translations in a JSON data type (as opposed to storing them in separate tables).

You can manage that by just using the Ecto’s :map field type, but the idea of this library is to provide a set of helpers to ease working with such embedded translations.

The library expects you to store a map of translations for each field. For example:

%Post{
  title: %{"en" => "The title", "fr" => "Le titre"},   
  body: %{"en" => "The content", "fr" => "Le contenu"}
}

In brief, the library helps you translating your Ecto struct and its associations for a given locale (in one call), with a fallback locale and a handler for missing translations.

post =
 Repo.all(Post)
 |> Repo.preload(:category)
 |> Repo.preload(:comments)
 |> Translator.translate("fr", fallback_locale: "en")

assert post.translated_title == "Le titre"
assert post.category.translated_name == "La catégorie"
assert List.first(post.comments).translated_text == "Un commentaire"

As you might already understand from the example above, by “translating an Ecto struct”, it is meant extracting the texts (from the different translations’ maps) for a given locale and fallback locale, and set them in a virtual field (which is named by the field it retrieved the text from prefixed by “translated_”).

It is done recursively for the struct and all their loaded associations.

It is particularly useful if you need to use different fallback locales throughout your application as is my case, or if you need to be notified for missing translations.

This library differs from other similar libraries where:

  • translations are stored in a JSON data type (in Postgres that will be jsonb type);
  • each field has its translations map (as opposed to one big translation map for all fields);
  • there is no notion of “main” locale, all the texts are stored in the map (but you can specify a fallback locale);
  • translations for a given locale are retrieved in one call for an Ecto struct and all its associations;
  • a fallback locale and a handler for missing translations may be provided.

https://github.com/mathieuprog/i18n_helpers

:v:

Most Liked

mathieuprog

mathieuprog

It would look something like:

from(
  p in Post,
  where: ilike(fragment("(?->>'en')", p.title), "%elixir%"),
  select: p
)

Thank you for the suggestion; I think indeed a helper to build Ecto queries should be part of the library :+1: It’s not my priority right now as I don’t need a search feature in my project.

However, I’m now working on view helpers to make working with form and such embedded fields easier.
These view helpers would render something like:

These fields can be generated in one line.

This will be push’ed in a few days.

Phillipp

Phillipp

It’s indeed very useful for setups where you want to keep the DB schema rather simple. How would one query the DB for e.g. a search feature? I guess it’s possible to search inside JSON using Postgres, I haven’t done that yet, though.

Maybe you could provide a helper function that assembles the correct Ecto query part?

Where Next?

Popular in Announcing Top

deadtrickster
I’ve just released stable versions of my Prometheus Elixir libs: Elixir client [docs]; Ecto collector [docs]; Plugs instrumenter/Export...
New
jakub-zawislak
Hi everyone, I’m coming from the Symfony (PHP) framework. I like Phoenix, but it has a one thing that was build much better in the Symfo...
New
riverrun
I’ve just released version 3 of Comeonin, a password hashing library. The following small changes have been made: changes to the NIF c...
New
kip
ex_cldr provides localisation and internationalisation support based upon the data from the Unicode CLDR project. Unicode released CLDR ...
407 13014 120
New
mbuhot
Leverage Open Api 3.0 (Swagger) to document, test, validate and explore your Plug and Phoenix APIs. Generate and serve a JSON Open API ...
New
Azolo
Hey everyone, I just released WebSockex which is a Elixir WebSocket client. WebSockex strives to work as a OTP special process, be RFC6...
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
anshuman23
Hello all, I have been working on my proposed project called Tensorflex as part of Google Summer of Code 2018.. Tensorflex can be used f...
New
devonestes
Introducing assertions, the library that helps you write really great test assertions! GitHub: GitHub - devonestes/assertions: Helpful a...
New

Other popular topics Top

AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement