Skip to content

Commit c602ea9

Browse files
Introduce "use Gettext.Backend" (#390)
Co-authored-by: José Valim <jose.valim@dashbit.co>
1 parent e6e9fe8 commit c602ea9

3 files changed

Lines changed: 100 additions & 48 deletions

File tree

lib/gettext.ex

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ defmodule Gettext do
7878
7979
## Gettext API
8080
81-
To use `Gettext`, a module that calls `use Gettext` (referred to below as a
81+
To use `Gettext`, a module that calls `use Gettext.Backend` (referred to below as a
8282
"backend") has to be defined:
8383
8484
defmodule MyApp.Gettext do
85-
use Gettext, otp_app: :my_app
85+
use Gettext.Backend, otp_app: :my_app
8686
end
8787
8888
This automatically defines some macros in the `MyApp.Gettext` backend module.
@@ -627,55 +627,16 @@ defmodule Gettext do
627627

628628
@doc false
629629
defmacro __using__(opts) do
630-
# From Elixir v1.13 onwards, use compile_env
631-
env_fun = if function_exported?(Module, :attributes_in, 1), do: :compile_env, else: :get_env
632-
633630
quote do
634-
require Logger
635-
636631
opts = unquote(opts)
637-
otp_app = Keyword.fetch!(opts, :otp_app)
638-
639-
@gettext_opts opts
640-
|> Keyword.merge(Application.unquote(env_fun)(otp_app, __MODULE__, []))
641-
|> Keyword.put_new(:interpolation, Gettext.Interpolation.Default)
642-
643-
@interpolation Keyword.fetch!(@gettext_opts, :interpolation)
644-
645-
@before_compile Gettext.Compiler
646-
647-
def handle_missing_bindings(exception, incomplete) do
648-
_ = Logger.error(Exception.message(exception))
649-
incomplete
650-
end
651-
652-
defoverridable handle_missing_bindings: 2
653632

654-
def handle_missing_translation(_locale, domain, _msgctxt, msgid, bindings) do
655-
Gettext.Compiler.warn_if_domain_contains_slashes(domain)
656-
657-
with {:ok, interpolated} <- @interpolation.runtime_interpolate(msgid, bindings),
658-
do: {:default, interpolated}
659-
end
660-
661-
def handle_missing_plural_translation(
662-
_locale,
663-
domain,
664-
_msgctxt,
665-
msgid,
666-
msgid_plural,
667-
n,
668-
bindings
669-
) do
670-
Gettext.Compiler.warn_if_domain_contains_slashes(domain)
671-
string = if n == 1, do: msgid, else: msgid_plural
672-
bindings = Map.put(bindings, :count, n)
673-
674-
with {:ok, interpolated} <- @interpolation.runtime_interpolate(string, bindings),
675-
do: {:default, interpolated}
633+
if Keyword.has_key?(opts, :backend) do
634+
raise "not implemented yet"
635+
else
636+
# TODO: Deprecate this branch
637+
require Gettext.Backend
638+
Gettext.Backend.__using__(opts)
676639
end
677-
678-
defoverridable handle_missing_translation: 5, handle_missing_plural_translation: 7
679640
end
680641
end
681642

lib/gettext/backend.ex

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,81 @@
11
defmodule Gettext.Backend do
22
@moduledoc """
3-
Behaviour that defines the macros that a Gettext backend has to implement.
3+
Defines a Gettext backend.
4+
5+
## Usage
6+
7+
A Gettext **backend** must `use` this module.
8+
9+
defmodule MyApp.Gettext do
10+
use Gettext.Backend, otp_app: :my_app
11+
end
12+
13+
Using this module generates all the callbacks required by the `Gettext.Backend`
14+
behaviour into the module that uses it. For more options and information,
15+
see `Gettext`.
16+
17+
> #### `use Gettext.Backend` Is a Recent Feature {: .info}
18+
>
19+
> Before version v0.26.0, you could only `use Gettext` to generate a backend.
20+
>
21+
> Version v0.26.0 changes the way backends work so that now a Gettext backend
22+
> must `use Gettext.Backend`, while to use the functions in the backend you
23+
> will do `use Gettext, backend: MyApp.Gettext`.
424
"""
525

26+
defmacro __using__(opts) do
27+
# TODO: From Elixir v1.13 onwards, use compile_env and remove this if.
28+
env_fun = if function_exported?(Module, :attributes_in, 1), do: :compile_env, else: :get_env
29+
30+
quote do
31+
require Logger
32+
33+
opts = unquote(opts)
34+
otp_app = Keyword.fetch!(opts, :otp_app)
35+
36+
@gettext_opts opts
37+
|> Keyword.merge(Application.unquote(env_fun)(otp_app, __MODULE__, []))
38+
|> Keyword.put_new(:interpolation, Gettext.Interpolation.Default)
39+
40+
@interpolation Keyword.fetch!(@gettext_opts, :interpolation)
41+
42+
@before_compile Gettext.Compiler
43+
44+
def handle_missing_bindings(exception, incomplete) do
45+
_ = Logger.error(Exception.message(exception))
46+
incomplete
47+
end
48+
49+
defoverridable handle_missing_bindings: 2
50+
51+
def handle_missing_translation(_locale, domain, _msgctxt, msgid, bindings) do
52+
Gettext.Compiler.warn_if_domain_contains_slashes(domain)
53+
54+
with {:ok, interpolated} <- @interpolation.runtime_interpolate(msgid, bindings),
55+
do: {:default, interpolated}
56+
end
57+
58+
def handle_missing_plural_translation(
59+
_locale,
60+
domain,
61+
_msgctxt,
62+
msgid,
63+
msgid_plural,
64+
n,
65+
bindings
66+
) do
67+
Gettext.Compiler.warn_if_domain_contains_slashes(domain)
68+
string = if n == 1, do: msgid, else: msgid_plural
69+
bindings = Map.put(bindings, :count, n)
70+
71+
with {:ok, interpolated} <- @interpolation.runtime_interpolate(string, bindings),
72+
do: {:default, interpolated}
73+
end
74+
75+
defoverridable handle_missing_translation: 5, handle_missing_plural_translation: 7
76+
end
77+
end
78+
679
@doc """
780
Default handling for missing bindings.
881

test/gettext/backend_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
defmodule Gettext.BackendTest do
2+
use ExUnit.Case, async: true
3+
4+
describe "use Gettext.Backend" do
5+
test "creates a backend" do
6+
body =
7+
quote do
8+
use Gettext.Backend,
9+
otp_app: :test_application
10+
end
11+
12+
{:module, mod, _bytecode, :ok} = Module.create(TestBackend, body, __ENV__)
13+
14+
assert mod.__gettext__(:otp_app) == :test_application
15+
assert mod.__info__(:attributes)[:behaviour] == [Gettext.Backend]
16+
end
17+
end
18+
end

0 commit comments

Comments
 (0)