Current section

7 Versions

Jump to

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"