Search documentation of Localize

# Supervision

Copy Markdown View Source

Localize runs a small supervision tree at runtime — a data loader, a locale loader (which owns the locale-validation ETS table), a cache sweeper, a format cache, and the collation ICU table. By default this tree is started automatically when the `:localize` OTP application boots, so most consumers do not need to do anything.

Some applications prefer to mount Localize under their own supervision tree — typically to control startup ordering relative to other components (a database connection pool that loads locale-specific data, a background worker that formats messages on the first tick), or to run shutdown side-effects in a particular order. This guide describes that pattern.

## The default: auto-start

Out of the box, your `mix.exs` just lists the dependency:

    def deps do
      [
        {:localize, "~> 0.33"}
      ]
    end

The `:localize` OTP application starts at boot and `Localize.Supervisor` comes up as part of the BEAM's application supervisor. No further configuration is required.

## Manual supervision

To mount Localize yourself, mark the dependency `runtime: false`. This tells Mix to compile the application but not to start it automatically:

    def deps do
      [
        {:localize, "~> 0.33", runtime: false}
      ]
    end

Then add `Localize.Supervisor` to your application's `children` list:

    defmodule MyApp.Application do
      use Application

      @impl true
      def start(_type, _args) do
        children = [
          MyApp.Repo,
          Localize.Supervisor,
          MyAppWeb.Endpoint
        ]

        Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)
      end
    end

### Ordering

`Localize.Supervisor` should start before any process that calls Localize functions at startup — message formatters, importers running on first-tick, anything in `Application.start_phases/0` that touches locale data.

It can start after anything Localize itself does not depend on at boot — repos, web endpoints, registries, etc. Localize reads its bundled CLDR data from `priv/` and does not depend on any consumer-side process.

### The `Localize.Supervisor` child spec

`Localize.Supervisor` exposes the standard `child_spec/1` callback, so the bare module name works as a child reference. If you prefer the tuple form, both of these are equivalent:

    children = [
      Localize.Supervisor,
      # …same as…
      {Localize.Supervisor, []}
    ]

There are no options today. The `options` argument exists so the tuple form remains valid if options are introduced in a later release.

### Side-effects that run once

`Localize.Supervisor.start_link/1` performs two pieces of one-time post-start work after its children are running:

1. Resolves `:supported_locales` from application env and caches it.
2. Reads every bundled supplemental data set so the atoms each one references (`:USD`, `:Latn`, `:arab`, `:gregorian`, …) are interned in the BEAM atom table. The 0.30.0 atom-DOS hardening uses `binary_to_existing_atom` at many lookup sites; without this eager-load valid input like `numberingSystem=arab` could surface as a bogus "unknown numbering system" error on a fresh BEAM.

Both side-effects are idempotent — starting the supervisor twice (which OTP would not let you do anyway, since the registered name is `Localize.Supervisor`) would not double-load anything.

### Verifying

After your application starts, the Localize tree should be visible alongside your own children:

    iex> :observer.start()
    # Inspect `MyApp.Supervisor`; you should see `Localize.Supervisor` among
    # its children, with the standard Localize processes below it.

You can also confirm via `Supervisor.which_children/1`:

    iex> MyApp.Supervisor |> Supervisor.which_children() |> Enum.map(&elem(&1, 0))
    [MyApp.Repo, Localize.Supervisor, MyAppWeb.Endpoint]

## When to choose which mode

- Auto-start (the default) is right for almost every project. It is one fewer thing to think about, and OTP's startup semantics already handle the ordering between the `:localize` application and your own.

- Manual supervision is right when you need explicit ordering between Localize and another part of your own application, or when you maintain a multi-tenant host that wants to start and stop Localize as a unit alongside other tenant-scoped processes.

In either mode, the runtime behaviour of `Localize` is identical — the same processes, the same supplemental atoms, the same caches. The choice is purely about who owns the supervisor.

← Previous Page Performance Guide
Next Page → Migrating from ex_cldr to Localize