Current section
Files
Jump to
Current section
Files
lib/glossary.ex
defmodule Glossary do
@external_resource Path.join(__DIR__, "glossary.md")
@moduledoc File.read!(Path.join(__DIR__, "glossary.md"))
@doc """
Injects the `t/2` function into the caller module for lexeme localization.
`sources` is a list of relative paths (without extensions or locale suffixes) to YAML files
containing lexeme–expression mappings.
Example:
use Glossary, ["../common", "project"]
"""
defmacro __using__(sources) do
expressions =
__CALLER__.file
|> Path.dirname()
|> Glossary.Lexicon.compile(sources, __CALLER__.module)
require Logger
Logger.debug(
"[Glossary] built for #{__CALLER__.module} #{inspect(expressions, pretty: true)}"
)
quote do
require Logger
@glossary unquote(Macro.escape(expressions))
@doc """
Returns the expression of a lexeme in the given locale.
Falls back to returning the `lexeme` itself if no expression is found,
and logs a warning with the full key.
## Example
t("motto.glossary", "la")
#=> "Clavis interpretandi"
t("motto.glossary", "en")
#=> "The key to understanding"
"""
def t(lexeme, locale) when is_binary(lexeme) and is_binary(locale) do
key = "#{locale}.#{lexeme}"
if expression = Map.get(@glossary, key) do
expression
else
Logger.warning("[Glossary] Missing: #{key}")
key
end
end
@doc """
Returns the expression of a lexeme in the given locale with interpolated bindings.
Placeholders in the form `{{key}}` (without spaces) are replaced by corresponding values.
Falls back to returning the `lexeme` itself if no expression is found.
## Examples
t("game.score", "en", score: 42)
#=> "Score: 42"
t("greeting", "en", name: "Alice")
#=> "Hello, Alice!"
"""
@spec t(String.t(), String.t(), keyword()) :: String.t()
def t(lexeme, locale, bindings)
when is_binary(lexeme) and is_binary(locale) and is_list(bindings) do
Enum.reduce(bindings, t(lexeme, locale), fn {key, value}, acc ->
String.replace(acc, "{{#{key}}}", to_string(value))
end)
end
end
end
end