belaustegui

belaustegui

Hi all.
A few days ago I published my first package in Hex.pm. It is called Trans and aims to provide a easy way to leverage database support of JSON datatypes to store translations. Trans is heavily inspired by the incredible gem hstore_translate.

The traditional approach of having adjacent tables for storing the translation information quickly increases the number of JOINs required for retrieving data, especially when a single query contains multiple models. The approach provided by Trans stores translations in a single column of each model, so when a model is retrieved so are it’s translations. Modern RDBMSs provide support for this kind of unschemed data and to use conditions in it.

If you find it interesting, take a more detailed look at:

Any suggestions, issues, ideas and contributions are more than welcome.
Love :hearts:

Showing Posts 1 to 10

belaustegui

belaustegui OP

Trans is now on version 1.0.0 :slight_smile:!!!
You can see the release notes on GitHub. The main changes of this version are the improved support for Elixir 1.3.x and the new requirement of Ecto 2.0.

You can update the version of Trans in your project by adding {:trans, "~> 1.0"} to your mix.exs and then running mix hex.update trans.

As usual, any comments, suggestions, issues or pull-requests are more than welcome!
Love :heart:

belaustegui

belaustegui OP

Hi again! We got a new version of Trans!! :slight_smile:

The version 1.0.1 is a minor release that focuses mainly on making Trans more comprehensible by improving the documentation and adding a changelog that conforms to the Keep a Changelog format.

You can see the release notes on GitHub. There are also some nice improvements planned

As usual, any comments, suggestions, issues or pull-requests are more than welcome!
Love :heart:

belaustegui

belaustegui OP

After a long time we have a new version of Trans.

The main changes in version 1.0.2 are:

  • Trans now compiles cleanly and is tested on Elixir 1.4.
  • The dependency earmark has been removed, since it is already required by ex_doc.
  • A CONTRIBUTING.md file has been added, detailing the contribution guidelines.

You can see the release notes and the planned improvements on GitHub.

The next Trans version will focus on making Ecto an optional dependency that is only required when using the QueryBuilder component.

As usual, any comments, suggestions, issues or pull-requests are more than welcome!
Love :heart:

OvermindDL1

OvermindDL1

So this is not so much for translations of the application, but rather for easily allowing users to create their own translated content for a given set of data? Looks useful. :slight_smile:

agustif

agustif

This is awesome for user-generated sites aspiring to manage multi-lang effortlessly in PostgreSQL with leverage of JSONB types.

Thank you very much for posting about it, I had already in my github stars but forgot about the project now that it might come useful for a side project

belaustegui

belaustegui OP

Thank you very much for your words @OvermindDL1 and @schp :slight_smile:

The mission of Trans is to provide an easy way to retrieve translations from structs or maps, and (optionally) provide an interface for generating Ecto queries by adding conditions on translated fields.

Trans has two main components:

  • The Translator mission is to retrieve a translation into the desired language, or fall back to the default one if no translation exists. (I also plan to allow more flexibility into the fallback process).
  • The QueryBuilder mission is to allow creating or modifying queries based on translated values. This component does require Ecto and leverages the power of the JSONB data type of PostgreSQL databases to look into the translations for the queries.

At the moment Trans has a hard dependency on Ecto, but I intend to make this dependency optional in the next version. Then, you will be able to use the Translator component without Ecto in any application.
The QueryBuilder will still require Ecto to work though, but it won’t be even compiled if Ecto does not exist in the application.

Edit: I actually plan to support MySQL also, since newer versions also have a JSON type. But there is an open issue in the Mariaex adapter to add support for this type that must be addressed first. I could look into it myself, but I would need some guidance into where to look first :sweat_smile:

belaustegui

belaustegui OP

I’ve released a new version of Trans :rocket:

Trans 1.1.0 makes Ecto an optional dependency.

This update addresses one of the main concerns of trans since its inception: to leverage, but be usable without, a database. The Trans.QueryBuilder component requires Ecto to work, but the Trans.Translator component can be used with any struct or map and does not require a database.

As usual, any comments, suggestions, issues or pull-requests are more than welcome!
Love :heart:

belaustegui

belaustegui OP

Trans 2.0 is out! :rocket:

This release of Trans is focused on improving the library interface and making it more safe and usable.
The Trans.QueryBuilder module has been completely rewritten. It now exposes the translated/3 macro that generates an SQL fragment that can be used when building Ecto queries.
The new translated/3 macro is compatible with all the functions and macros in Ecto.Query and Ecto.Query.Api and provides safe checks against translations on non existing or non translatable fields.

Compare how you would create a query with Trans 2.0 and before:

# Now: Trans 2.0
iex> Repo.all(from a in Article,
...> where: ilike(translated(Article, a.body, :es), "%elixir%"))

# Before: Trans 1.0
iex> Article
...> |> Trans.QueryBuilder.with_translation(:es, :title, "%République%", type: :like)
...> |> Repo.all

More detailed release notes can be found at GitHub. I also plan to publish soon an article explaining the changes and the reasoning behind them.

EDIT: the promised article about the changes in Trans 2.0 is now published in Medium :raised_hands:

As usual, any comments, suggestions, issues or pull-requests are more than welcome!
Love :heart:

Eiji

Eiji

@belaustegui: Can you explain why you decided to have all translated columns in big jsonb?
After read your description here I through that you do something like:

defmodule Article do
  # use Ecto.Schema
  use Trans.Schema

  schema "articles" do
    trans_field :body, :string
    trans_field :title, :string
  end
end

so any trans_field is a separate map column.
How about performance when you have big jsonb map (with lots of fields) and lots of records?

Do you validating language codes?

For your #12 and #14 issues: in some cases developer prefer to store locales in database for example table named locales could have fields: id, locale, fallback_locale_id, name and description.

btw. You have still opened 2.0.0 milestone and already released 2.0.0 version :smiley:

belaustegui

belaustegui OP

Hi @Eiji , I really appreciate your comment.
I completely forgot about the milestone :sweat_smile:, it is closed now, thanks!

Your idea of trans_field looks really good indeed. Could you open an issue in the project so we can discuss it further?

I went with this approach for Trans because I wanted to port the hstore_translate gem to Elixir.
I share your concerns with the big jsonb field containing all the translations, in particular when fetching lots of data in queries. I’ve not been able to test Trans in any project with high data volume. I’ve used the hstore_translate gem in a Ruby project and this approach was faster than having the translations in their own separated tables (the globalize approach). I think that this performance gain will still apply in Elixir.

I may perform a test comparing Trans performance versus having the translations separated in different tables. It would be a very interesting comparison :thinking:

Thank you very much!
Cheers.

Where Next? Top

Trending in Announcing Top

wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
fuelen
Hi all! I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas. You...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
akoutmos
@hugobarauna, Dr. Dimitrios Koutmos (my brother) and I (Alex Koutmos) have been hard at work on writing a book on how you can use Elixir ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews