Add a language with a script resolver

v0.0.1

The built-in table of Mishka Slug maps 88 language codes to scripts. A code outside it gives {:error, {:unknown_locale, code}}. This guide plugs in a script resolver, a function that returns the scripts of a code, so any language can appear in locales:.

Before you begin

  • Mishka Slug installed. See Get Started.
  • A language code that gives {:error, {:unknown_locale, code}}, such as tt (Tatar).

See the error

elixir
MishkaSlug.slugify("Сәлам", locales: ["tt"])
#=> {:error, {:unknown_locale, "tt"}}

Write the resolver

A resolver is a function in a module. It is called as apply(module, function, [code | args]) and returns {:ok, [script]} or :error. The scripts are atoms such as :latin, :arabic, :cyrillic and :han. MishkaSlug.Scripts.from_iso15924/1 turns a script code of CLDR and BCP 47 ("Arab", "Cyrl", "Jpan") into them.

elixir
defmodule MyApp.LocaleScripts do
  def scripts("tt"), do: MishkaSlug.Scripts.from_iso15924("Cyrl")
  def scripts(_code), do: :error
end

Latin is always allowed, so the resolver does not list it. An :error gives {:error, {:unknown_locale, code}}, and the built-in table is not asked.

Pass it to a call

elixir
MishkaSlug.slugify("Сәлам", locales: ["tt"], script_resolver: {MyApp.LocaleScripts, :scripts, []})
#=> {:ok, "сәлам"}

MishkaSlug.slugify("Сәлам", locales: ["zz"], script_resolver: {MyApp.LocaleScripts, :scripts, []})
#=> {:error, {:unknown_locale, "zz"}}

The option takes {module, function, args}. MishkaSlug.Change accepts it too.

Set it for the whole app

To use one resolver for every call, put it in the application config:

elixir
config :mishka_slug, :script_resolver, {MyApp.LocaleScripts, :scripts, []}

The :script_resolver option of a call wins over the config for that call.

Take the scripts from CLDR

If your project already uses the Localize package, let it find the likely script of any language code:

elixir
defmodule MyApp.LocaleScripts do
  def scripts(code) do
    with {:ok, tag} <- Localize.LanguageTag.parse(code),
         {:ok, tag} <- Localize.LanguageTag.add_likely_subtags(tag) do
      MishkaSlug.Scripts.from_iso15924(tag.script)
    else
      _ -> :error
    end
  end
end

MishkaSlug.slugify("Сәлам", locales: ["tt"], script_resolver: {MyApp.LocaleScripts, :scripts, []})
#=> {:ok, "сәлам"}

Japanese (Han with kana), Korean (Hangul with Han) and Chinese with Bopomofo count as one script family, so their words are never cut.

Next steps