How to approach multi language content management system?

we also went the embed way, but did it directly with ecto. Depending on your app if the contents don’t have to be queried (they can, but the syntax is not that nice yet) it’s relatively straightforward with nested embeds. Still not really simple but these things are rarely so :slight_smile:

Here’s a simplified schema

defmodule App.Thing do
  use App.Web, :model

  alias App.Thing.Content
  alias App.OtherThing

  schema "thing" do
    field :name, :string
    field :order, :integer

    embeds_one :en, Content, [on_replace: :delete]
    embeds_one :de, Content, [on_replace: :delete]

    has_many :other_things, OtherThing

    timestamps()
  end

each content can have own embeds one / embeds many. Example query

@spec only_lang(struct(), atom()) :: map()
def only_lang(queryable, lang) do
  queryable
  |> where([t], not(is_nil(field(t, ^lang))))
  |> select([t], %{content: field(t, ^lang), id: t.id, uuid: t.uuid, name: t.name})
end

these fields are nullable so the user can have something for only one supported language. One thing to note is that we mostly deliver contents over the API without having the language in server side state