README.md

# i18n-country-translations

[![Hex.pm](https://img.shields.io/hexpm/v/i18n_country_translations.svg)](https://hex.pm/packages/i18n_country_translations)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

> Localized country names for Elixir -- 168 locales, 257 territory codes, zero runtime complexity.

Building a country picker? Displaying addresses internationally? Your users expect to see country names in their own language -- not just in English. Most i18n packages cover 30-50 locales and call it a day, leaving hundreds of millions of speakers without support.

**i18n_country_translations** provides country name translations sourced from [CLDR](https://cldr.unicode.org/), the same data that powers ICU, Chrome, and Android. With **168 locales** -- more than double the coverage of alternatives -- you can serve users from Amharic to Zulu without gaps.

## Why i18n_country_translations?

- **168 locales** -- the most comprehensive coverage available on hex.pm
- **257 territory codes** -- full ISO 3166-1 alpha-2 plus EU, XK, and other commonly used codes
- **CLDR-sourced** -- accurate, professionally reviewed translations (not scraped from Wikipedia)
- **ETS-backed** -- concurrent reads with zero bottleneck, powered by OTP
- **Auto-uppercase** -- country codes are automatically uppercased, so `"us"` and `"US"` both work
- **No panic** -- all lookups return `nil` for missing data, mutations return `{:error, reason}`

## Install

```elixir
def deps do
  [
    {:i18n_country_translations, "~> 0.1"}
  ]
end
```

## Quick Start

```elixir
I18nCountryTranslations.register_locale("de")
I18nCountryTranslations.set_default_locale("de")

I18nCountryTranslations.get_name("US")
#=> "Vereinigte Staaten"
```

## Usage

### Register only what you need

```elixir
I18nCountryTranslations.register_locale("de")
I18nCountryTranslations.register_locale("ja")

I18nCountryTranslations.get_name_for_locale("de", "US")
#=> "Vereinigte Staaten"

I18nCountryTranslations.get_name_for_locale("ja", "JP")
#=> "日本"
```

### Register all locales at once

```elixir
I18nCountryTranslations.register_all_locales()
# All 168 locales now available
```

### Case-insensitive codes

```elixir
I18nCountryTranslations.get_name_for_locale("en", "us")   #=> "United States"
I18nCountryTranslations.get_name_for_locale("en", "Us")   #=> "United States"
```

### Norway works correctly (not parsed as boolean)

```elixir
I18nCountryTranslations.get_name_for_locale("en", "NO")
#=> "Norway"
```

### List available and registered locales

```elixir
I18nCountryTranslations.available_locales()    # all 168 locales in the data package
I18nCountryTranslations.registered_locales()   # only the ones you've loaded
```

## API Reference

| Function | Description |
|----------|-------------|
| `register_locale(locale)` | Load translations for a single locale. No-op if already registered. |
| `register_all_locales()` | Load all 168 available locales. |
| `set_default_locale(locale)` | Set the default locale. Returns `{:error, reason}` if not registered. |
| `get_default_locale()` | Get the current default locale, or `nil`. |
| `get_name(code)` | Get the localized country name using the default locale. Code auto-uppercased. |
| `get_name_for_locale(locale, code)` | Get the localized country name for a specific locale. Code auto-uppercased. |
| `get_all_names(locale)` | Get all translations for a locale as `{:ok, map}`. |
| `available_locales()` | List all locales in the data package. |
| `registered_locales()` | List all currently loaded locales. |

All lookups return `nil` when a code or locale is not found -- no exceptions.

## Supported Locales

168 locales covering major and regional languages worldwide:

<details>
<summary>View all 168 locales</summary>

af, ak, am, ar, as, az, be, bg, bm, bn, bo, br, bs, ca, cs, cy, da, de, dz, ee, el, en, eo, es, et, eu, fa, ff, fi, fo, fr, ga, gd, gl, gu, ha, he, hi, hr, hu, hy, ia, id, ig, is, it, ja, ka, ki, kk, kl, km, kn, ko, ky, lg, ln, lo, lt, lu, lv, mg, mk, ml, mn, mr, ms, mt, my, nb, nd, ne, nl, nn, or, pa, pl, ps, pt, pt-BR, rm, rn, ro, ru, se, sg, si, sk, sl, sn, so, sq, sr, sv, sw, ta, te, th, ti, to, tr, uk, ur, uz, vi, yo, zh, zh-CN, zh-HK, zh-TW, zu, asa, bas, bez, brx, byn, cgg, chr, dav, dje, dyo, ebu, ewo, fil, fur, gsw, guz, haw, jmc, kab, kam, kde, kea, khq, kln, ksb, ksf, ksh, lag, luo, luy, mas, mer, mfe, mgh, mua, naq, nmg, nus, nyn, rof, rwk, saq, sbp, seh, ses, shi, swc, teo, tig, twq, tzm, vai, vun, wae, wal, xog, yav

</details>

## Data Source

All translations come from the [Unicode CLDR](https://cldr.unicode.org/) (Common Locale Data Repository) -- the industry-standard source used by every major platform including iOS, Android, Chrome, and Java.

## Also Available For

- **[Ruby](https://github.com/onomojo/i18n-country-translations)** -- Rails gem with automatic Railtie integration
- **[JavaScript/TypeScript](https://github.com/onomojo/i18n-country-translations-js)** -- NPM package with tree-shaking and reverse lookups
- **[Go](https://github.com/onomojo/i18n-country-translations-go)** -- Go module with embedded data via `go:embed`
- **[Rust](https://github.com/onomojo/i18n-country-translations-rs)** -- Crate with compile-time embedded data

## License

MIT