You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@ The format is based on
12
12
13
13
* Runtime locale downloading is now **opt-in**. The new `:allow_runtime_locale_download` application config key (default `false`) gates whether the `PersistentTerm` provider may download locale ETF files from the CDN when a cache miss occurs. When disabled (the default), a missing locale returns `{:error, %Localize.LocaleNotFoundInCacheError{}}` with a message that tells the user how to fix it (either run `mix localize.download_locales` or enable the config key). The `Localize.Locale.Provider` behaviour gains an optional `allow_download?/0` callback so alternative providers can implement their own download-gating logic.
14
14
15
-
*`mix localize.download_locales` — new Mix task (shipped with the hex package) that downloads locale ETF files from the Localize CDN and writes them to the configured cache directory. Three modes: `mix localize.download_locales en fr de` for specific locales, `--preload` to download the configured `:preload_locales`, and`--all` for all 766 CLDR locales. Intended for Dockerfiles, CI pipelines, and release builds.
15
+
*`mix localize.download_locales` — new Mix task (shipped with the hex package) that downloads locale ETF files from the Localize CDN and writes them to the configured cache directory. With no arguments, downloads the configured `:supported_locales`. Also accepts explicit locale names (`mix localize.download_locales en fr de`) or`--all` for all CLDR locales. Intended for Dockerfiles, CI pipelines, and release builds.
16
16
17
17
*`Localize.Locale.expand_locale_list/2` — extracted from `Localize.Application` as a public function so mix tasks and user code can expand wildcard locale lists (e.g. `"en-*"`) against the known CLDR locale set.
18
18
@@ -104,6 +104,8 @@ The format is based on
104
104
105
105
* Configuration option `:data_dir` renamed to `:locale_cache_dir`. Defaults to `Path.join(:code.priv_dir(:localize), "localize/locales")`.
106
106
107
+
***`:preload_locales` is deprecated and ignored.** Use `:supported_locales` to declare your locale set and `mix localize.download_locales` to pre-populate the cache at build time. Locale data is loaded lazily into `:persistent_term` on first access. A deprecation warning is logged at application startup if `:preload_locales` is still configured.
108
+
107
109
*`Localize.List.to_string/2` and `Localize.List.intersperse/2` option `:format` renamed to `:list_style`. The companion helpers `known_list_formats/0` and `list_formats_for/1` were renamed to `known_list_styles/0` and `list_styles_for/1` for consistency. Freeing `:format` from list-specific use means it now passes through to per-element formatters: `Localize.List.to_string([~D[2025-07-10], ~D[2025-08-15]], locale: :en, format: :long)` produces `"July 10, 2025 and August 15, 2025"` because `:format` reaches `Localize.Date.to_string/2` for each element while the list join uses the default `:standard` style. The `list_patterns_for/1` helper is unchanged — it returns the underlying CLDR pattern data, not the style names.
|`:default_locale`| Derived from `LOCALIZE_DEFAULT_LOCALE` env var, then `LANG` env var, then `:en`. | The application-wide default locale. Can also be set at runtime with `Localize.put_default_locale/1`. |
133
-
|`:supported_locales`|`nil`| A list of locale identifiers that your application supports. Each entry is an atom matching a known CLDR locale (e.g., `:en`, `:"fr-CA"`) or a wildcard string (e.g., `"en-*"`) that expands to all matching CLDR locales. Invalid entries log a warning and are skipped. When set, `validate_locale/1` resolves locale identifiers against this list rather than all ~766 CLDR locales. Accessible at runtime via `Localize.supported_locales/0`. See below for how this interacts with `:preload_locales`. |
134
-
|`:preload_locales`|`nil`|A list of locale identifiers to load at application startup. Accepts atoms and wildcard strings like `:supported_locales`. Locale data is fetched and cached in `:persistent_term` before any formatting calls. Invalid entries log a warning and are skipped. See below for how this interacts with `:supported_locales`. |
132
+
|`:supported_locales`|`nil`| A list of locale identifiers that your application supports. Each entry is an atom matching a known CLDR locale (e.g., `:en`, `:"fr-CA"`), a wildcard string (e.g., `"en-*"`), a coverage-level keyword (`:modern`, `:moderate`, `:basic`), or a Gettext-style string (e.g., `"pt_BR"`, `"zh_Hans"`). POSIX-style underscores are normalised to hyphens and entries are resolved to their CLDR canonical form via likely-subtag resolution (e.g. `"pt_BR"` → `:pt`). Only exact matches (score 0) are accepted — entries that cannot be resolved log a warning with `domain: :localize`and are skipped. When set, `validate_locale/1` resolves locale identifiers against this list rather than all ~766 CLDR locales. Accessible at runtime via `Localize.supported_locales/0`. |
133
+
|`:preload_locales`|**deprecated**|Deprecated and ignored. Use `:supported_locales` to declare your locale set and `mix localize.download_locales` to pre-populate the cache at build time. |
135
134
|`:locale_provider`|`Localize.Locale.Provider.PersistentTerm`| Module that implements the `Localize.Locale.Provider` behaviour for loading and caching per-locale data. |
136
135
|`:locale_cache_max_entries`|`1_000`| Maximum number of validated locales to hold in the ETS cache. A background sweeper runs every 10 seconds and evicts excess entries to prevent unbounded growth. |
137
136
|`:format_cache_max_entries`|`2_000`| Maximum number of compiled format patterns (number and date/time) to hold in the ETS cache. A background sweeper runs every 10 seconds and evicts excess entries to prevent unbounded growth. |
@@ -141,20 +140,30 @@ config :localize,
141
140
|`:cacertfile`| System default | Path to a custom CA certificate file for HTTPS connections (used when downloading locale data). |
142
141
|`:https_proxy`|`nil`| HTTPS proxy URL. Also reads the `HTTPS_PROXY` environment variable. |
143
142
144
-
### Supported and preload locale interaction
143
+
### Using Gettext locales
145
144
146
-
When `:supported_locales` is configured, the effective supported locale list is the **union** of `:supported_locales`and `:preload_locales`. This means any locale you preload is automatically considered supported — you don't need to list it in both places.
145
+
If your application uses Gettext, you can derive `:supported_locales`from your Gettext backend in `config/runtime.exs` (where the module is already compiled and available):
POSIX-style locale names returned by Gettext (e.g. `"pt_BR"`, `"zh_Hans"`) are automatically normalized to BCP 47 and resolved to their CLDR canonical form (`:pt`, `:zh`). No manual mapping is needed.
Use `mix localize.download_locales` at build time to download locale data into the on-disk cache. By default it downloads the configured `:supported_locales`:
158
+
159
+
```bash
160
+
# Dockerfile
161
+
RUN mix localize.download_locales
155
162
```
156
163
157
-
When `:supported_locales` is **not** configured (the default), `validate_locale/1` matches against all ~766 CLDR locales and `:preload_locales` simply controls which locale data is loaded eagerly.
164
+
Specific locales can also be downloaded explicitly: `mix localize.download_locales en fr de`. Use `--all` for all CLDR locales. Locale data is loaded lazily into `:persistent_term` on first access from the cache.
165
+
166
+
When `:supported_locales` is **not** configured (the default), `validate_locale/1` matches against all ~766 CLDR locales.
Copy file name to clipboardExpand all lines: guides/migration.md
+33-8Lines changed: 33 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,25 +24,50 @@ Localize requires no compile-time configuration. All options are set in your app
24
24
25
25
### Recommended migration config
26
26
27
-
Most ex_cldr projects configure a fixed set of locales in the backend module. The Localize equivalent is `:supported_locales` (constrains validation) and `:preload_locales` (eagerly loads locale data at startup):
27
+
Most ex_cldr projects configure a fixed set of locales in the backend module. The Localize equivalent is `:supported_locales` (constrains validation) plus `mix localize.download_locales` (pre-populates the cache at build time):
28
28
29
29
```elixir
30
30
# config/config.exs
31
31
config :localize,
32
32
default_locale::en,
33
-
supported_locales: [:en, :fr, :de, :ja],
34
-
preload_locales: [:en, :fr, :de, :ja]
33
+
supported_locales: [:en, :fr, :de, :ja]
35
34
```
36
35
37
-
In ex_cldr, these were declared inside `use Cldr, locales: [...]`. In Localize they are application environment keys, so no recompilation is needed when the list changes.
36
+
```bash
37
+
# At build time (Dockerfile, CI, or local)
38
+
mix localize.download_locales
39
+
```
40
+
41
+
In ex_cldr, locales were declared inside `use Cldr, locales: [...]` and embedded at compile time. In Localize, `:supported_locales` is an application environment key (no recompilation needed), and locale data is downloaded once at build time and loaded lazily into `:persistent_term` on first access.
42
+
43
+
### Using Gettext locales
44
+
45
+
If your application uses Gettext, you can derive `:supported_locales` from your Gettext backend. Since the Gettext module must be compiled first, use `config/runtime.exs`:
POSIX-style locale names returned by Gettext (e.g. `"pt_BR"`, `"zh_Hans"`) are automatically normalised to BCP 47 and resolved to their CLDR canonical form via likely-subtag resolution. For example, `"pt_BR"` resolves to `:pt` (CLDR treats bare `pt` as Brazilian Portuguese) and `"zh_Hans"` resolves to `:zh`. No manual mapping is needed.
54
+
55
+
Only exact matches (distance score 0 in the CLDR matching algorithm) are accepted for `:supported_locales` — this ensures that misspelled or unrecognised locale names are caught at startup rather than silently mapping to a distant locale. Entries that cannot be resolved log a warning with `domain: :localize` and are skipped.
56
+
57
+
Coverage-level keywords (`:modern`, `:moderate`, `:basic`) are also accepted and expand to all CLDR locales at or above that level:
58
+
59
+
```elixir
60
+
config :localize,
61
+
supported_locales: [:modern] # ~104 locales with modern CLDR coverage
62
+
```
38
63
39
64
### Full options reference
40
65
41
66
| Option | Default | Description |
42
67
|---|---|---|
43
68
|`:default_locale`| Derived from `LOCALIZE_DEFAULT_LOCALE` env var → `LANG` env var → `:en`| Application-wide default locale. |
44
-
|`:supported_locales`|`nil` (all 766 CLDR locales) | List of locale atoms and/or wildcard strings (e.g. `"en-*"`). When set, `validate_locale/1` resolves against this list instead of all CLDR locales. |
45
-
|`:preload_locales`|`nil`|List of locales to load into `:persistent_term` at application startup. Anything in `:preload_locales` is automatically considered supported. |
69
+
|`:supported_locales`|`nil` (all 766 CLDR locales) | List of locale atoms, wildcard strings (e.g. `"en-*"`), coverage-level keywords (`:modern`, `:moderate`, `:basic`), or Gettext-style strings (e.g. `"pt_BR"`). POSIX underscores are normalised and entries are resolved via likely-subtag resolution — only exact matches (score 0) are accepted. Invalid entries log a warning and are skipped. When set, `validate_locale/1` resolves against this list instead of all CLDR locales. |
70
+
|`:preload_locales`|**deprecated**|Deprecated and ignored. Use `:supported_locales` and `mix localize.download_locales`. |
46
71
|`:locale_cache_dir`|`Application.app_dir(:localize, "priv/localize/locales")`| Directory where downloaded locale ETF files are cached. |
47
72
|`:allow_runtime_locale_download`|`false`| When `true`, locales not in the cache are downloaded from the CDN on first access. Default `false` — use `mix localize.download_locales` to pre-populate at build time. |
48
73
|`:locale_provider`|`Localize.Locale.Provider.PersistentTerm`| Module implementing `Localize.Locale.Provider` for locale data loading. |
When `:supported_locales` is configured, the effective supported locale list is the **union** of `:supported_locales` and `:preload_locales`. Any locale you preload is automatically considered supported — you don't need to list it in both places.
118
+
Run `mix localize.download_locales` at build time to download locale data for all configured `:supported_locales`. Locale data is then loaded lazily into `:persistent_term` on first access — no runtime downloads needed.
0 commit comments