Get Started

v0.0.1

Mishka Slug is an Elixir library that turns a title into a URL slug in its own writing system. Persian stays Persian, Hindi stays Hindi and Japanese stays Japanese, and Latin text loses its accents the way WordPress writes them. Mishka CMS uses it to make the address of a post or a page. This tutorial installs version 0.0.1, makes slugs from titles in several scripts and shows how to read the result.

What you will build

A few calls to MishkaSlug.slugify/2 in iex. You slug an English title, titles in other scripts and a title with nothing to slug, and then you limit a slug to the languages your site uses.

Before you begin

  • A Mix project on Elixir 1.20 or later.
  • Mishka Slug depends on guarded_struct and gettext, and Mix fetches them for you. Ash is optional. It is needed only for the MishkaSlug.Change module (see Write the slug in an Ash resource).

Step 1: Add the dependency

Add the package to the deps of your mix.exs, then run mix deps.get.

elixir
def deps do
  [
    {:mishka_slug, "~> 0.0.1"}
  ]
end

The package is on Hex and its source is on GitHub. It is licensed under Apache-2.0.

Step 2: Make a slug

Start iex -S mix and call slugify/2 with a title. It returns {:ok, slug}.

elixir
MishkaSlug.slugify("Hello World: Getting Started with Elixir!")
#=> {:ok, "hello-world-getting-started-with-elixir"}

MishkaSlug.slugify("Café Crème")
#=> {:ok, "cafe-creme"}

A slug is lowercase words joined by -. Punctuation separates words, and Latin letters lose their accents.

Step 3: Keep the script of the title

A title in another writing system keeps its letters. Nothing is transliterated.

elixir
MishkaSlug.slugify("قیمت‌گذاری نرم‌افزار")
#=> {:ok, "قیمتگذاری-نرمافزار"}

MishkaSlug.slugify("हिन्दी भाषा नमस्ते")
#=> {:ok, "हिन्दी-भाषा-नमस्ते"}

MishkaSlug.slugify("東京キャブ乗り場 ラーメン")
#=> {:ok, "東京キャブ乗り場-ラーメン"}

MishkaSlug.slugify("Привет, мир!")
#=> {:ok, "привет-мир"}

In the Persian title, the half-space (the zero-width non-joiner) is removed and the two parts are glued. Hindi vowel signs and Thai tone marks stay, because in those scripts the marks spell the word. See How a slug is made for the rules.

Step 4: Read an error

A title can have nothing left to slug. slugify/2 then returns {:error, reason} and never an empty string.

elixir
MishkaSlug.slugify("😀🚀")
#=> {:error, :empty}

Use slugify!/2 when you know the text has letters or digits, such as a seed or a constant. It returns the slug, or raises ArgumentError.

elixir
MishkaSlug.slugify!("Привет, мир!")
#=> "привет-мир"

Step 5: Limit the slug to your site's languages

Pass the languages of your site as locales:. The slug keeps the letters and digits of their scripts, and Latin, and drops the rest.

elixir
MishkaSlug.slugify("آموزش React در ۱۰ دقیقه", locales: ["fa", "en"])
#=> {:ok, "آموزش-react-در-۱۰-دقیقه"}

MishkaSlug.slugify("Привет мир Hello", locales: ["en"])
#=> {:ok, "hello"}

MishkaSlug.slugify("قیمت", locales: ["en"])
#=> {:error, :no_allowed_script}

The last call returns :no_allowed_script because the title has letters, but none in a script of the site's languages.

What you learned

  • slugify/2 returns {:ok, slug} or {:error, reason}.
  • Latin letters lose their accents, and every other script keeps its letters.
  • locales: keeps only the scripts of your site's languages.

Next steps