Packages

A ~t sigil for Gettext translations, to reduce boilerplate and improve readability.

Current section

Files

Jump to
gettext_sigils lib gettext_sigils options.ex
Raw

lib/gettext_sigils/options.ex

defmodule GettextSigils.Options do
@modifier_value_schema NimbleOptions.new!(
domain: [
type: :any,
doc: "Gettext domain to use when using this modifier."
],
context: [
type: :any,
doc: "Gettext context to use when using this modifier."
]
)
@schema NimbleOptions.new!(
domain: [
type: :any,
doc: "Default Gettext domain within the module that is using `GettextSigils`."
],
context: [
type: :any,
doc: "Default Gettext context within the module that is using `GettextSigils`."
],
modifiers: [
type: {:list, {:custom, __MODULE__, :validate_modifier, []}},
default: [],
doc: """
A keyword list of options applied when using the `~t` sigil with modifiers.
The key has to be an atom between `:a` and `:z`. Uppercase modifiers are used by the library (eg. `N` for pluralization).
Each modifier can define the following options:
#{NimbleOptions.docs(@modifier_value_schema, nest_level: 1)}
"""
],
pluralization: [
type: :keyword_list,
default: [],
doc: "Pluralization options.",
keys: [
separator: [
type: {:custom, __MODULE__, :validate_separator, []},
doc: """
The string used to split singular and plural forms. Can also be set globally in the config.
```elixir
config :gettext_sigils, pluralization: [separator: "<plural>"]
```
The default is `"||"` (double pipe).
"""
]
]
]
)
@moduledoc """
Validates `:sigils` options passed to `use GettextSigils`. All other options are passed through to `use Gettext`.
## Options
#{NimbleOptions.docs(@schema)}
## Example
use GettextSigils,
backend: MyApp.Gettext,
sigils: [
domain: "default",
context: "dashboard",
modifiers: [
e: [domain: "errors"],
a: [context: "admin"]
],
pluralization: [
separator: "||"
]
]
"""
@modifier_keys Enum.map(?a..?z, &List.to_atom([&1]))
@doc "Validates the given options or raises a `NimbleOptions.ValidationError` if invalid."
@spec validate!(keyword()) :: keyword() | no_return()
def validate!(opts) do
NimbleOptions.validate!(opts, @schema)
end
@doc false
def pluralization_separator(opts) do
opts
|> Keyword.get(:pluralization, [])
|> Keyword.get_lazy(:separator, &GettextSigils.Pluralization.default_separator/0)
end
@doc false
def validate_modifier({key, value}) when key in @modifier_keys and is_list(value) do
case NimbleOptions.validate(value, @modifier_value_schema) do
{:ok, validated} -> {:ok, {key, validated}}
{:error, error} -> {:error, "modifier #{inspect(key)}: #{Exception.message(error)}"}
end
end
def validate_modifier({key, value}) when key in @modifier_keys do
{:error, "modifier #{inspect(key)}: options must be a keyword list, got: #{inspect(value)}"}
end
def validate_modifier({key, _value}) do
{:error, "modifier keys must be lowercase letters (a-z), got: #{inspect(key)}"}
end
@doc false
def validate_separator(sep) when is_binary(sep) and byte_size(sep) > 0, do: {:ok, sep}
def validate_separator(value) do
{:error, "separator must be a non-empty string, got: #{inspect(value)}"}
end
end