feat: more complete i18n infrastructure
This commit is contained in:
158
lib/bds/i18n.ex
Normal file
158
lib/bds/i18n.ex
Normal file
@@ -0,0 +1,158 @@
|
||||
defmodule BDS.I18n do
|
||||
@moduledoc false
|
||||
|
||||
@supported_languages [
|
||||
%{code: "en", flag: "GB"},
|
||||
%{code: "de", flag: "DE"},
|
||||
%{code: "fr", flag: "FR"},
|
||||
%{code: "it", flag: "IT"},
|
||||
%{code: "es", flag: "ES"}
|
||||
]
|
||||
@supported_language_codes Enum.map(@supported_languages, & &1.code)
|
||||
|
||||
@format_locales %{
|
||||
"en" => "en-US",
|
||||
"de" => "de-DE",
|
||||
"fr" => "fr-FR",
|
||||
"it" => "it-IT",
|
||||
"es" => "es-ES"
|
||||
}
|
||||
|
||||
@flag_emoji %{
|
||||
"GB" => "🇬🇧",
|
||||
"DE" => "🇩🇪",
|
||||
"FR" => "🇫🇷",
|
||||
"IT" => "🇮🇹",
|
||||
"ES" => "🇪🇸"
|
||||
}
|
||||
|
||||
@default_language "en"
|
||||
@default_format_locale "en-US"
|
||||
@locale_files Path.expand("../../priv/i18n/locales/*.json", __DIR__)
|
||||
|> Path.wildcard()
|
||||
|> Enum.sort()
|
||||
|
||||
for file <- @locale_files do
|
||||
@external_resource file
|
||||
end
|
||||
|
||||
@catalogs Enum.into(@locale_files, %{}, fn file ->
|
||||
locale = file |> Path.basename(".json") |> String.downcase()
|
||||
{locale, Jason.decode!(File.read!(file))}
|
||||
end)
|
||||
|
||||
def supported_languages, do: @supported_languages
|
||||
|
||||
def default_language, do: @default_language
|
||||
|
||||
def normalize_language(language) do
|
||||
language
|
||||
|> normalize_locale_prefix()
|
||||
|> case do
|
||||
value when value in @supported_language_codes -> value
|
||||
_other -> @default_language
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_ui_locale(locale), do: resolve_supported_locale(locale) || @default_language
|
||||
|
||||
def current_ui_locale do
|
||||
(System.get_env("LC_ALL") || System.get_env("LC_MESSAGES") || System.get_env("LANG"))
|
||||
|> resolve_ui_locale()
|
||||
end
|
||||
|
||||
def resolve_render_locale(language), do: resolve_supported_locale(language) || @default_language
|
||||
|
||||
def format_locale(language) do
|
||||
language
|
||||
|> resolve_supported_locale()
|
||||
|> case do
|
||||
nil -> @default_format_locale
|
||||
locale -> Map.get(@format_locales, locale, @default_format_locale)
|
||||
end
|
||||
end
|
||||
|
||||
def locale_mapping(language) do
|
||||
ui_locale = resolve_ui_locale(language)
|
||||
|
||||
%{
|
||||
ui_locale: ui_locale,
|
||||
format_locale: format_locale(ui_locale)
|
||||
}
|
||||
end
|
||||
|
||||
def get_render_translations(language) do
|
||||
language
|
||||
|> resolve_render_locale()
|
||||
|> catalog_for_locale()
|
||||
end
|
||||
|
||||
def get_ui_translations(locale) do
|
||||
locale
|
||||
|> resolve_ui_locale()
|
||||
|> catalog_for_locale()
|
||||
end
|
||||
|
||||
def translate(language, key) do
|
||||
key = key |> to_string() |> String.trim()
|
||||
|
||||
case resolve_supported_locale(language) do
|
||||
nil ->
|
||||
Map.get(catalog_for_locale(@default_language), key, key)
|
||||
|
||||
locale ->
|
||||
Map.get(catalog_for_locale(locale), key, key)
|
||||
end
|
||||
end
|
||||
|
||||
def translate_render(language, key), do: translate(language, key)
|
||||
def translate_ui(locale, key), do: translate(locale, key)
|
||||
|
||||
def flag(language) do
|
||||
language
|
||||
|> resolve_supported_locale()
|
||||
|> case do
|
||||
nil -> @default_language
|
||||
locale -> locale
|
||||
end
|
||||
|> flag_code()
|
||||
|> then(&Map.get(@flag_emoji, &1, &1))
|
||||
end
|
||||
|
||||
def flag_code(language) do
|
||||
language
|
||||
|> resolve_supported_locale()
|
||||
|> case do
|
||||
nil -> @default_language
|
||||
locale -> locale
|
||||
end
|
||||
|> then(fn locale ->
|
||||
@supported_languages
|
||||
|> Enum.find(hd(@supported_languages), &(&1.code == locale))
|
||||
|> Map.fetch!(:flag)
|
||||
end)
|
||||
end
|
||||
|
||||
defp resolve_supported_locale(language) do
|
||||
language
|
||||
|> normalize_locale_prefix()
|
||||
|> case do
|
||||
value when value in @supported_language_codes -> value
|
||||
_other -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp normalize_locale_prefix(language) do
|
||||
language
|
||||
|> to_string()
|
||||
|> String.trim()
|
||||
|> String.replace("_", "-")
|
||||
|> String.downcase()
|
||||
|> String.split("-", parts: 2)
|
||||
|> List.first()
|
||||
end
|
||||
|
||||
defp catalog_for_locale(locale) do
|
||||
Map.get(@catalogs, locale, Map.get(@catalogs, @default_language, %{}))
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user