Current section
7 Versions
Jump to
Current section
7 Versions
Compare versions
5
files changed
+38
additions
-36
deletions
| @@ -1,6 +1,6 @@ | |
| 1 1 | {<<"links">>,[{<<"GitHub">>,<<"https://github.com/cozy-elixir/ecto_i18n">>}]}. |
| 2 2 | {<<"name">>,<<"ecto_i18n">>}. |
| 3 | - {<<"version">>,<<"0.3.0">>}. |
| 3 | + {<<"version">>,<<"0.3.1">>}. |
| 4 4 | {<<"description">>,<<"Provides i18n support for Ecto.">>}. |
| 5 5 | {<<"elixir">>,<<"~> 1.14">>}. |
| 6 6 | {<<"app">>,<<"ecto_i18n">>}. |
| @@ -4,13 +4,13 @@ defmodule EctoI18n do | |
| 4 4 | |
| 5 5 | ## Preface |
| 6 6 | |
| 7 | - There're [lots of strategies to localize contents in database](https://dejimata.com/2017/3/3/translating-with-mobility). |
| 8 | - |
| 7 | + There're [lots of strategies to localize contents in database](https://dejimata.com/2017/3/3/translating-with-mobility) |
| 8 | + ([archived](https://web.archive.org/web/20240528023514/https://dejimata.com/2017/3/3/translating-with-mobility)). |
| 9 9 | For now, `#{inspect(__MODULE__)}` implements only strategy 6 mentioned |
| 10 10 | above - creating an extra column for storing all the localized contents |
| 11 11 | for that table. |
| 12 12 | |
| 13 | - In this way, it can: |
| 13 | + With this strategy, it can: |
| 14 14 | |
| 15 15 | * avoid using extra tables for storing localized contents. |
| 16 16 | * avoid using complex JOINs when retrieving localized contents. |
| @@ -52,20 +52,18 @@ defmodule EctoI18n.Changeset do | |
| 52 52 | def changeset(product, attrs) do |
| 53 53 | product |
| 54 54 | |> cast(attrs, [:sku, :name]) |
| 55 | - |> cast_embed(:locales, with: &cast_locales/2) |
| 55 | + |> cast_embed(:locales, required: true, with: &cast_locales/2) |
| 56 56 | end |
| 57 57 | |
| 58 58 | defp cast_locales(locales, attrs) do |
| 59 59 | locales |
| 60 60 | |> cast(attrs, []) |
| 61 | - |> cast_embed(:"zh-Hans", with: &cast_locale/2) |
| 62 | - |> cast_embed(:"zh-Hant", with: &cast_locale/2) |
| 61 | + |> cast_embed(:"zh-Hans", required: true, with: &cast_locale/2) |
| 62 | + |> cast_embed(:"zh-Hant", required: true, with: &cast_locale/2) |
| 63 63 | end |
| 64 64 | |
| 65 65 | """ |
| 66 66 | def cast_locales(changeset, name, opts) do |
| 67 | - inner_with_fun = Keyword.fetch!(opts, :with) |
| 68 | - |
| 69 67 | struct = changeset.data |
| 70 68 | module = struct.__struct__ |
| 71 69 | |
| @@ -73,18 +71,22 @@ defmodule EctoI18n.Changeset do | |
| 73 71 | EctoI18n.schema_locales_called!(module) |
| 74 72 | EctoI18n.schema_locales_name!(module, name) |
| 75 73 | |
| 76 | - cast_embed(changeset, name, with: build_with_fun(module, inner_with_fun)) |
| 74 | + cast_embed(changeset, name, |
| 75 | + required: true, |
| 76 | + with: build_with_fun(module, opts) |
| 77 | + ) |
| 77 78 | end |
| 78 79 | |
| 79 | - defp build_with_fun(module, inner_with_fun) do |
| 80 | - locales = module.__ecto_i18n_schema__(:locales) |
| 80 | + defp build_with_fun(module, opts) do |
| 81 | + required_locales = module.__ecto_i18n_schema__(:required_locales) |
| 82 | + opts = Keyword.put_new(opts, :required, true) |
| 81 83 | |
| 82 84 | fn struct, attrs -> |
| 83 85 | struct |
| 84 86 | |> cast(attrs, []) |
| 85 87 | |> then( |
| 86 | - &Enum.reduce(locales, &1, fn locale, changeset -> |
| 87 | - cast_embed(changeset, locale, with: inner_with_fun) |
| 88 | + &Enum.reduce(required_locales, &1, fn locale, changeset -> |
| 89 | + cast_embed(changeset, locale, opts) |
| 88 90 | end) |
| 89 91 | ) |
| 90 92 | end |
| @@ -5,18 +5,18 @@ defmodule EctoI18n.Schema do | |
| 5 5 | |
| 6 6 | defmacro __using__(opts) do |
| 7 7 | quote do |
| 8 | - @ecto_i18n_schema_default_locale unquote(build_schema_default_locale(opts)) |
| 9 8 | @ecto_i18n_schema_locales unquote(build_schema_locales(opts)) |
| 9 | + @ecto_i18n_schema_default_locale unquote(build_schema_default_locale(opts)) |
| 10 | + @ecto_i18n_schema_required_locales @ecto_i18n_schema_locales -- |
| 11 | + [@ecto_i18n_schema_default_locale] |
| 10 12 | |
| 11 13 | import unquote(__MODULE__), only: [locales: 2] |
| 12 14 | |
| 13 15 | def __ecto_i18n_schema__(:used?), do: true |
| 14 16 | |
| 15 | - def __ecto_i18n_schema__(:default_locale), |
| 16 | - do: @ecto_i18n_schema_default_locale |
| 17 | - |
| 18 | - def __ecto_i18n_schema__(:locales), |
| 19 | - do: @ecto_i18n_schema_locales -- [@ecto_i18n_schema_default_locale] |
| 17 | + def __ecto_i18n_schema__(:locales), do: @ecto_i18n_schema_locales |
| 18 | + def __ecto_i18n_schema__(:default_locale), do: @ecto_i18n_schema_default_locale |
| 19 | + def __ecto_i18n_schema__(:required_locales), do: @ecto_i18n_schema_required_locales |
| 20 20 | end |
| 21 21 | end |
| 22 22 | |
| @@ -85,7 +85,7 @@ defmodule EctoI18n.Schema do | |
| 85 85 | end |
| 86 86 | |
| 87 87 | defmacro __locales_prepare__(env) do |
| 88 | - locales = Module.get_attribute(env.module, :ecto_i18n_schema_locales) |
| 88 | + required_locales = Module.get_attribute(env.module, :ecto_i18n_schema_required_locales) |
| 89 89 | |
| 90 90 | locales_name = Module.get_attribute(env.module, :ecto_i18n_schema_locales_name) |
| 91 91 | locales_module = Module.get_attribute(env.module, :ecto_i18n_schema_locales_module) |
| @@ -100,7 +100,7 @@ defmodule EctoI18n.Schema do | |
| 100 100 | |
| 101 101 | @primary_key false |
| 102 102 | embedded_schema do |
| 103 | - for locale <- List.wrap(unquote(locales)) do |
| 103 | + for locale <- List.wrap(unquote(required_locales)) do |
| 104 104 | embeds_one(locale, unquote(locales_fields_module), on_replace: :update) |
| 105 105 | end |
| 106 106 | end |
| @@ -142,19 +142,6 @@ defmodule EctoI18n.Schema do | |
| 142 142 | end |
| 143 143 | end |
| 144 144 | |
| 145 | - defp build_schema_default_locale(opts) do |
| 146 | - opt_name = :default_locale |
| 147 | - |
| 148 | - case Keyword.fetch(opts, opt_name) do |
| 149 | - {:ok, default_locale} -> |
| 150 | - to_atom(default_locale) |
| 151 | - |
| 152 | - :error -> |
| 153 | - raise ArgumentError, |
| 154 | - message: "#{inspect(__MODULE__)} requires #{inspect(opt_name)} option" |
| 155 | - end |
| 156 | - end |
| 157 | - |
| 158 145 | defp build_schema_locales(opts) do |
| 159 146 | opt_name = :locales |
| 160 147 | |
| @@ -168,6 +155,19 @@ defmodule EctoI18n.Schema do | |
| 168 155 | end |
| 169 156 | end |
| 170 157 | |
| 158 | + defp build_schema_default_locale(opts) do |
| 159 | + opt_name = :default_locale |
| 160 | + |
| 161 | + case Keyword.fetch(opts, opt_name) do |
| 162 | + {:ok, default_locale} -> |
| 163 | + to_atom(default_locale) |
| 164 | + |
| 165 | + :error -> |
| 166 | + raise ArgumentError, |
| 167 | + message: "#{inspect(__MODULE__)} requires #{inspect(opt_name)} option" |
| 168 | + end |
| 169 | + end |
| 170 | + |
| 171 171 | defp to_atom(string) when is_binary(string), do: String.to_atom(string) |
| 172 172 | defp to_atom(atom) when is_atom(atom), do: atom |
| 173 173 | end |
| @@ -1,7 +1,7 @@ | |
| 1 1 | defmodule EctoI18n.MixProject do |
| 2 2 | use Mix.Project |
| 3 3 | |
| 4 | - @version "0.3.0" |
| 4 | + @version "0.3.1" |
| 5 5 | @description "Provides i18n support for Ecto." |
| 6 6 | @source_url "https://github.com/cozy-elixir/ecto_i18n" |