Kanzo UI
Forms

Language picker

A searchable picker for BCP 47 language tags, with each language named in its own language.

Ark UI
lang="es"

Usage

import { LanguagePicker } from "@kanzo-tech/ui";
<LanguagePicker value={tag} onValueChange={setTag} />

The value is a BCP 47 tag — the lang of a string, a page or a document — or "" for none. Each row shows the language's name in its own language beside its tag, "Español · es", so a reader finds theirs without knowing the code, and the search matches either: "spa", "es" and "español" all find it. The names come from the runtime's Intl.DisplayNames, so a language it cannot name is listed by its tag.

Underneath it is Combobox, which is why it reads its state from an ancestor Field and is that field's control. What this adds is the vocabulary: the names, a default set, and what counts as a tag.

A closed set

Pass languages and the list is exactly those tags. A tag outside it cannot be entered, and an input that matches nothing reverts on blur.

Published in English, Spanish and Catalan.

Without it, the list is a broad default set of suggestions and any well-formed tag can be typed: es-mx is reported as es-MX, and e_ is not reported at all. A typed tag is reported when the input is left, not per keystroke — "es" is a tag on the way to "es-MX", and reporting it early would swap the text for the name of the language the user was still spelling. A tag picked from the list is reported at once. Well-formedness is the runtime's (Intl.getCanonicalLocales), not a pattern of ours; it says a tag is shaped like one, not that anybody speaks it.

Beside the text it tags

inline draws only the input, for a slot inside another field's control: the trailing addon of an InputGroup. The group around it supplies the box, so the picker draws no border, ring or chevron of its own. It also gives its input an id of its own, because inside a Field the machine would otherwise take the id the text input has already claimed.

Words

The three phrases it draws — the placeholder, the filter placeholder and "no matches" — are English by default and replaceable with translations, which takes any subset:

<LanguagePicker translations={{ noMatches: "Sin resultados" }} value={tag} onValueChange={setTag} />

API Reference

LanguagePicker

Props are LanguagePickerProps; translations takes a Partial<LanguagePickerTranslations>.

PropTypeDefault
valuestringrequired
onValueChange(tag: string) => voidrequired
languagesreadonly string[] — the closed seta broad default set, and free entry
inlinebooleanfalse
size"sm" | "md" | "lg"; ignored with inline, which is the height of the field it sits in"md"
disabled / readOnly / invalidbooleanfrom the Field
translationsPartial<{ placeholder, filterPlaceholder, noMatches }>English
aria-labelstringnone — give one when there is no FieldLabel

On this page