# `Locale`

A language and region together, which decides how dates and numbers look: `en-GB`.

Use it whenever you format something for a person, and to store which they prefer. To say only which language a document is in, use [`Language`](/docs/types/type-language.md).

## Shape

One of 534 values, such as `Locale.af`, written `af`. Details has them.

## Example

```jadpo
Locale.en_gb
```

`text.parse(raw, as: Locale)` reads one from text that comes from outside. Text that isn't one at all fails `malformed`, such as `english` or `xx-YY`.

This operation gives one: `locale.from_accept_language`.

## Good to know

- Each value is its tag in lower case with `_` for `-`: `Locale.en_gb` is `en-GB`.
- `locale.from_accept_language` picks one from a browser's request header.
- `==` tells you whether two are the same. `<` and `list.sort_by` don't take it.

## In JSON

A string, in a request, a response or `json.write`:

```json
"en-GB"
"fr-FR"
```

## Details

<details>
<summary>Text form, storage, how it is shown, and operations</summary>

`Locale` is in the group Places, and has been in Jadpo since 0.1.0.

### Every value

The first 40 of 534; `jadpo help Locale --json` lists every one:

`af`, `af_na` (`af-NA`), `af_za` (`af-ZA`), `ak`, `ak_gh` (`ak-GH`), `am`, `am_et` (`am-ET`), `ar`, `ar_ae` (`ar-AE`), `ar_bh` (`ar-BH`), `ar_dj` (`ar-DJ`), `ar_dz` (`ar-DZ`), `ar_eg` (`ar-EG`), `ar_eh` (`ar-EH`), `ar_er` (`ar-ER`), `ar_il` (`ar-IL`), `ar_iq` (`ar-IQ`), `ar_jo` (`ar-JO`), `ar_km` (`ar-KM`), `ar_kw` (`ar-KW`), `ar_lb` (`ar-LB`), `ar_ly` (`ar-LY`), `ar_ma` (`ar-MA`), `ar_mr` (`ar-MR`), `ar_om` (`ar-OM`), `ar_ps` (`ar-PS`), `ar_qa` (`ar-QA`), `ar_sa` (`ar-SA`), `ar_sd` (`ar-SD`), `ar_so` (`ar-SO`), `ar_ss` (`ar-SS`), `ar_sy` (`ar-SY`), `ar_td` (`ar-TD`), `ar_tn` (`ar-TN`), `ar_ye` (`ar-YE`), `as`, `as_in` (`as-IN`), `az`, `az_az` (`az-AZ`), `az_latn` (`az-Latn`).

### Text form

`text.from` writes one standard text form, the same form `text.parse` reads back: `en-GB` and `fr-FR`.

### How it is stored

It is stored in one column named for the field, of type `text`. `fr-FR` is stored as `'fr-FR'`.

### How it is shown to people

`text.format(value, locale:)` shows it to people in their locale.

With `locale: Locale.en_gb`:

| Value | Shown |
|---|---|
| `en-GB` | `British English` |
| `fr-FR` | `French (France)` |

### Operations

- `list.sort_by(items: List<T>, key: Function<T, K>, locale: Locale?) -> List<T>`: A new list ordered by `key`, smallest first; items with equal keys keep their order. Text keys go by code point, or by `locale`'s rules when it is given.
- `locale.direction(value: Locale) -> TextDirection`: Which way `value`'s text runs, as CLDR says: `TextDirection.left_to_right` for English, `TextDirection.right_to_left` for Arabic and Hebrew.
- `locale.from_accept_language(header: Text?) -> Locale`: The supported `Locale` an `Accept-Language` header asks for, or `locales { default: }` when it names none the application supports, is malformed or is `none`.
- `temporal.format_relative(value: T, now: Instant, zone: Zone?, locale: Locale) -> PresentationText`: `value` shown to a person in `locale` as how long ago it was from `now`: "just now", minutes, "Today at", "Yesterday at", the weekday, then the long date.
- `text.lower(value: Text, locale: Locale?) -> Text`: `value` in lower case, by `locale`'s rules when it is given.
- `text.pick(value: LocalisedText, locale: Locale) -> Text`: The text in `value` for `locale`: its entry, else the entry of its language (the locale CLDR's likely subtags give for the language first), else the application's default locale's, else the first.
- `text.upper(value: Text, locale: Locale?) -> Text`: `value` in upper case, by `locale`'s rules when it is given.

It also takes `text.parse`, `text.from`, `text.format`, `json.read`, `json.write` and `==`. [How every standard type behaves](/docs/every-standard-type-meets-one-contract.md) says how they work.

</details>
