ScriptProvider
Show content in the script the user picks — Latin or Cyrillic Uzbek, remembered across visits.
Oʻzbekiston boʻylab yetkazib berish
Buyurtmangiz 2–3 kun ichida eshigingizgacha yetkaziladi. Toʻlov — naqd yoki karta orqali.
'use client';
import { ScriptProvider, ScriptToggle, Translit } from '@akhatmirzo/ui';
export default function ScriptOverview() {
return (
<ScriptProvider defaultScript="latin">
<div className="flex w-full max-w-md flex-col items-start gap-4">
<ScriptToggle size="sm" />
<Translit as="h3" className="text-lg font-semibold text-text">
Oʻzbekiston boʻylab yetkazib berish
</Translit>
<Translit as="p" className="text-sm text-text-muted">
Buyurtmangiz 2–3 kun ichida eshigingizgacha yetkaziladi. Toʻlov — naqd yoki karta orqali.
</Translit>
</div>
</ScriptProvider>
);
}
Import
import { ScriptProvider, ScriptToggle, Translit, useScript } from '@akhatmirzo/ui';You store text in one script (usually Latin) and each user reads it in the script they prefer.
Conversion uses toScript from @akhatmirzo/core. It detects the source script on its own, so
text stored in Cyrillic converts to Latin just as well.
| Part | What it does |
|---|---|
ScriptProvider | Holds the current script (optionally in localStorage) |
ScriptToggle | A "Lotin | Кирилл" switch built on SegmentedControl |
Translit | Renders text in the current script and sets the lang attribute |
useScript | { script, setScript, t } for your own components and attributes |
When to use
- Uzbek-language apps — some users prefer reading Cyrillic. You don't have to write the content twice.
- Headings, buttons and short copy — use
Translitort(). Don't convert user input (names, addresses); keep it as typed. - Attributes (
placeholder,aria-label,title) — useuseScript().t, becauseTranslitrenders an element. - Not for other languages — this is transliteration between the two Uzbek scripts, not translation.
ScriptToggle
Inside a provider it drives the provider's state. The default labels are "Lotin", "Кирилл" and
the group name (aria-label) "Alifbo"; change them with labels. SegmentedControl
props (size, fullWidth, disabled …) work too.
'use client';
import { ScriptProvider, ScriptToggle, Translit } from '@akhatmirzo/ui';
export default function ScriptPersist() {
return (
<ScriptProvider defaultScript="latin" storageKey="docs-script-demo">
<div className="flex flex-col items-start gap-3">
<ScriptToggle labels={{ latin: 'Lotincha', cyrillic: 'Кириллча' }} />
<Translit className="text-sm text-text-muted">
Tanlovingiz eslab qolinadi — sahifani yangilab koʻring.
</Translit>
</div>
</ScriptProvider>
);
}
It also works without a provider as a plain controlled component with value and
onValueChange.
useScript
t(text) converts text to the current script. Outside a provider script is 'latin' and t
returns the text unchanged, so your component never breaks without one.
script: cyrillic
'use client';
import { Button, ScriptProvider, ScriptToggle, useScript } from '@akhatmirzo/ui';
function Cart() {
const { script, t } = useScript();
return (
<div className="flex flex-col items-start gap-3">
<p className="text-sm text-text-muted">
script: <code>{script}</code>
</p>
<Button variant="primary">{t('Savatga qoʻshish')}</Button>
<input
className="h-10 w-full rounded-lg border border-border bg-surface px-3 text-sm text-text"
placeholder={t('Mahsulot qidirish')}
aria-label={t('Mahsulot qidirish')}
/>
</div>
);
}
export default function UseScriptDemo() {
return (
<ScriptProvider defaultScript="cyrillic">
<div className="flex w-full max-w-sm flex-col gap-4">
<ScriptToggle />
<Cart />
</div>
</ScriptProvider>
);
}
const { script, setScript, t } = useScript();
t('Salom'); // "Салом" when Cyrillic is selected
setScript('cyrillic');Persistence and SSR
With storageKey, the choice is saved in localStorage under that key and synced across tabs.
The server render and the first client render always use defaultScript; the stored value is
read after hydration. That means no hydration mismatch in Next.js. If localStorage is blocked
(private mode), the choice lives only for the current session.
<ScriptProvider defaultScript="latin" storageKey="script">
{children}
</ScriptProvider>Controlled mode: script + onScriptChange (for example, to store the choice in a user
profile).
With other components
Inside a provider, RegionSelect shows region names and
MoneyInput showWords spells amounts in the current script.
Props
ScriptProvider
| Prop | Type | Default | Description |
|---|---|---|---|
script | 'latin' | 'cyrillic' | — | Current script (controlled) |
defaultScript | 'latin' | 'cyrillic' | 'latin' | Initial script; used for SSR and the first render |
onScriptChange | (script: UzScript) => void | — | Called when the script changes |
storageKey | string | — | Remember the choice in localStorage under this key |
children | ReactNode | — |
ScriptToggle
Accepts SegmentedControl props except value, defaultValue,
onValueChange and children.
| Prop | Type | Default | Description |
|---|---|---|---|
value | 'latin' | 'cyrillic' | — | Controlled value; defaults to the provider's script |
defaultValue | 'latin' | 'cyrillic' | 'latin' | Used when there is neither a provider nor a value |
onValueChange | (script: UzScript) => void | — | Called on change (the provider updates too) |
labels | { latin?: string; cyrillic?: string; group?: string } | { latin: "Lotin", cyrillic: "Кирилл", group: "Alifbo" } | |
size | 'sm' | 'md' | 'lg' | 'md' |
Translit
Other HTML attributes are passed to the element.
| Prop | Type | Default | Description |
|---|---|---|---|
childrenrequired | string | — | Text to convert (Latin or Cyrillic) |
as | ElementType | 'span' | Element to render |
lang | string | — | Defaults to uz-Latn or uz-Cyrl based on the current script |
useScript
| Prop | Type | Default | Description |
|---|---|---|---|
script | 'latin' | 'cyrillic' | — | Current script |
setScript | (script: UzScript) => void | — | Switch the script |
t | (text: string) => string | — | Convert text to the current script |
Accessibility
langattribute.Translitsetslang="uz-Latn"orlang="uz-Cyrl"on its element, so screen readers pick the right pronunciation and search engines see the script. Without a provider,langis detected from the text itself.<html lang>is left alone.- ScriptToggle is a
radiogroup(aria-label"Alifbo") navigated with ←→. The "Кирилл" option carrieslang="uz-Cyrl", so it is read correctly in a Latin interface. - Focus is kept. Switching scripts only changes text; elements are not re-created.