Hi everyone,
I only found this on this topic How to approach multi language content management system?
and wondering if in 2020 there is a better way to structure the database schema except for embedding the translations in the article table?
How would you solve this problem?
Any suggestion or ideas is welcomed.
I am also interested in using absinthe and phoenix templates apps how to handle this?
Thanks in adavance
Without having read that link I’d do it by having a column that encodes the language key as well, makes it for easy and efficient lookup, making it trivial to even fall back to another with minimal network use compared to embedding and so forth.
2 Likes
Thanks @OvermindDL1 for the suggestion and explanations.
1 Like
Also i would like to be sure that understood your point of view so I am writing the following schema
Languages migration
create table(:languages) do
add :name, :string
timestamps()
end
Article migration
create table(:posts) do
add :title, :string
add :content, :string
add :published, :boolean, default: false, null: false
add :language_id, references(:languages, on_delete: :nothing)
timestamps()
end
Category migration
create table(:categories) do
add :name, :string
add :language_id, references(:languages, on_delete: :nothing)
timestamps()
end
Something like this?
But the language_id
to be optional only if the category or article
written in another language?
I wouldn’t even have the languages
table at all, I’d just use the ISO-standard language codes for the language mappings.
For posts
the language_id
would just be a string type for that ISO mapping. Use the elixir cldr library (I think that was it?) for handling the language codes and making sure they are correct and all. Nicely by following this style you can easily lookup codes like en-us
for a US specific entry, and if it doesn’t exist you can fall back to an en
generic lookup, and if that fails you can fall back to an en-%
prefix lookup, and if that fails fallback to whatever you want, all in a single query is easy to do. 
And for the categories
table the language_id
would again just be a string for the ISO language code.
I haven’t done anything super advanced with internationalization though so I could easily be missing something, but this is both what I’ve done in the past and what I’ve seen in a large variety of significantly used databases.
2 Likes
So something like this
create table(:categories) do
add :name, :string
add :language_code, :string
timestamps()
end
and i would use a where
for every language i support i guess.
Thanks @OvermindDL1 i think i finally got it.
That’s what I’d do. Plus add an index for the language code (along with probably the name after it, so an index on [:language_code, :name]
perhaps would be the easiest and fastest index to make for the most usual queries I’d wager, but it all depends on what kind of queries you do).
2 Likes
Ah yep, that looks like it, in addition to ex_cldr
itself too!
EDIT: Or perhaps just ex_cldr
itself?
1 Like
What are the difference because i couldn’t tell from the docs of https://hexdocs.pm/ex_cldr_languages/
1 Like
Looks like ex_cldr_languages
just uses ex_cldr
under the hood for an easier language name conversion, but it seems you can do it all with normal ex_cldr
I think?
1 Like
Thanks i will have to try and see how it goes.
For the table, I would add a translation table, if You don’t want to embed translation…
create table(:posts) do
add :title, :string
add :content, :string
add :published, :boolean, default: false, null: false
timestamps()
end
create table(:posts_translations) do
add :post_id, references(:posts, on_delete: :delete_all)
add :language_id, references(:languages, on_delete: :nothing)
# Add fields You want to translate
add :title, :string
add :content, :string
timestamps()
end
This is more or less what globalize does.
3 Likes
Hmm interesting @kokolegorille but wouldn’t i have more joins to do this way?
Also i have more things that need to have a relations to an article(post):
category
tags
type
Yes, one join to do, but only one, not many…
That is why embedding translation in a json field is a good alternative.
1 Like
Got it the translations are required to be there just once when i select the language the content is displayed.
Thanks @kokolegorille for sharing this database diagram
I’ve generally seen both a side translation table and an embedded translation thing as crutches for fixing up originally broken designs. Designing the tables with the translation keys from the start is far superior as there is less joining, more efficient indexes, etc…
3 Likes
Yes it is quicker, but You also duplicate values that doesn’t need to be translated.
So the diagram vision is speed vs data duplication?
Wouldn’t you just duplicate the languages_code in @OvermindDL1 database diagram suggestion?
If it doesn’t need to be translated then just have a default of a blank locale key. ^.^
But really, I’m curious what wouldn’t ever need to be translated?
I don’t see that there’s any duplication at all with my setup? Can you elaborate with an example I’m quite curious?