@daanvandenbergh/i18nkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +285 -0
- package/dist/i18n/catalog.d.ts +18 -0
- package/dist/i18n/catalog.js +17 -0
- package/dist/i18n/detect.d.ts +34 -0
- package/dist/i18n/detect.js +62 -0
- package/dist/i18n/i18n.d.ts +178 -0
- package/dist/i18n/i18n.js +254 -0
- package/dist/i18n/index.d.ts +11 -0
- package/dist/i18n/index.js +10 -0
- package/dist/i18n/routing.d.ts +112 -0
- package/dist/i18n/routing.js +157 -0
- package/dist/i18n/translate.d.ts +26 -0
- package/dist/i18n/translate.js +28 -0
- package/dist/i18n/types.d.ts +155 -0
- package/dist/i18n/types.js +11 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/react/LanguagePicker.d.ts +21 -0
- package/dist/react/LanguagePicker.js +70 -0
- package/dist/react/LocaleLink.d.ts +21 -0
- package/dist/react/LocaleLink.js +23 -0
- package/dist/react/flags.d.ts +21 -0
- package/dist/react/flags.js +348 -0
- package/dist/react/index.d.ts +10 -0
- package/dist/react/index.js +10 -0
- package/dist/react/provider.d.ts +58 -0
- package/dist/react/provider.js +94 -0
- package/dist/react/styles.css +150 -0
- package/package.json +77 -0
- package/skills/i18nkit-add-locale/SKILL.md +182 -0
- package/skills/i18nkit-add-locale/reference/translation-rules.md +207 -0
- package/skills/i18nkit-add-locale/scripts/scan.sh +148 -0
- package/skills/i18nkit-sweep/SKILL.md +208 -0
- package/skills/i18nkit-sweep/reference/rules.md +174 -0
- package/skills/i18nkit-sweep/scripts/find_candidates.sh +99 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure type core of i18nkit. Every user-facing string is a {@link LanguageText} (static)
|
|
3
|
+
* or a {@link LanguageTextFn} (parameterized): an object with exactly one entry per locale in
|
|
4
|
+
* the caller's locale union `L`. Because these are mapped types over `L`, adding a locale to
|
|
5
|
+
* an {@link I18n} instance's config grows `L`, which turns every catalog entry still missing
|
|
6
|
+
* that locale into a compile error - that is the whole point: 100% type-safe coverage.
|
|
7
|
+
*
|
|
8
|
+
* This file has zero imports (no `react`, no `node:*`) so it can be shared by server, client,
|
|
9
|
+
* and edge code alike.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The URL scheme for the default locale:
|
|
13
|
+
* - `"prefix-except-default"` (the default): the default locale is served at bare URLs
|
|
14
|
+
* (`/pricing`) and every other locale under its `htmlLang` prefix (`/nl/pricing`).
|
|
15
|
+
* - `"prefix-all"`: every locale, including the default, carries its prefix (`/en/pricing`,
|
|
16
|
+
* `/nl/pricing`), so there is no bare-URL locale.
|
|
17
|
+
*/
|
|
18
|
+
export type RoutingStrategy = "prefix-except-default" | "prefix-all";
|
|
19
|
+
/**
|
|
20
|
+
* Static metadata describing one locale - used to render the picker, set `<html lang>`, and
|
|
21
|
+
* pick an `Intl` formatting locale. This is configuration, not translated UI copy.
|
|
22
|
+
*
|
|
23
|
+
* The locale's own key in the config map (e.g. `"en"`) is its code; `htmlLang` and `locale`
|
|
24
|
+
* default to that key so a BCP-47-keyed config can omit them entirely.
|
|
25
|
+
*/
|
|
26
|
+
export interface LocaleInfo {
|
|
27
|
+
/**
|
|
28
|
+
* The locale's own name (endonym) shown in the picker in every UI language alike (e.g.
|
|
29
|
+
* "English", "Nederlands"). A plain string on purpose - a language's name is not itself translated.
|
|
30
|
+
*/
|
|
31
|
+
label: string;
|
|
32
|
+
/**
|
|
33
|
+
* BCP-47 primary subtag for the document `<html lang>` attribute and the URL prefix (e.g.
|
|
34
|
+
* "en"). Defaults to the locale's key in the config map.
|
|
35
|
+
*/
|
|
36
|
+
htmlLang?: string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Full BCP-47 locale for `Intl` date/number formatting (e.g. "en-GB" -> "12 Jan 2026";
|
|
39
|
+
* "nl-NL" -> "12 jan 2026"). Defaults to {@link htmlLang}, then the locale's key. Kept
|
|
40
|
+
* separate from {@link htmlLang} because the document tag is primary-subtag only while
|
|
41
|
+
* formatting needs a concrete regional convention.
|
|
42
|
+
*/
|
|
43
|
+
locale?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A fully-resolved locale entry: {@link LocaleInfo} with its `code` and with `htmlLang`/`locale`
|
|
47
|
+
* filled in from their defaults. This is the shape exposed on an {@link I18n}'s `locales` map and
|
|
48
|
+
* `list` array, so consumers (the picker, routing) always read concrete values.
|
|
49
|
+
*
|
|
50
|
+
* @typeParam L - the locale union this entry belongs to.
|
|
51
|
+
*/
|
|
52
|
+
export interface ResolvedLocale<L extends string> {
|
|
53
|
+
/** The locale code (the key this entry had in the config map). */
|
|
54
|
+
code: L;
|
|
55
|
+
/** The endonym label, copied from {@link LocaleInfo.label}. */
|
|
56
|
+
label: string;
|
|
57
|
+
/** The resolved BCP-47 `<html lang>` / URL-prefix subtag (never undefined). */
|
|
58
|
+
htmlLang: string;
|
|
59
|
+
/** The resolved full BCP-47 `Intl` formatting locale (never undefined). */
|
|
60
|
+
locale: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The configuration object passed to `new I18n(...)`. The locale union `L` is inferred from the
|
|
64
|
+
* keys of {@link I18nConfig.locales}; `default` is wrapped in `NoInfer` so it never widens `L`.
|
|
65
|
+
*
|
|
66
|
+
* @typeParam L - the locale union, inferred from `locales`' keys.
|
|
67
|
+
*/
|
|
68
|
+
export interface I18nConfig<L extends string> {
|
|
69
|
+
/**
|
|
70
|
+
* The supported locales, keyed by their code, in the order the picker should list them
|
|
71
|
+
* (insertion order is preserved). The set of keys defines the locale union `L`.
|
|
72
|
+
*/
|
|
73
|
+
locales: Record<L, LocaleInfo>;
|
|
74
|
+
/**
|
|
75
|
+
* The fallback locale for detection/resolution: used when a cookie value or `Accept-Language`
|
|
76
|
+
* is missing, invalid, or unrecognized. It is not a per-key translation fallback - the catalog
|
|
77
|
+
* types require a string for every locale, so a translation is never missing at runtime.
|
|
78
|
+
*/
|
|
79
|
+
default: NoInfer<L>;
|
|
80
|
+
/**
|
|
81
|
+
* Name of the cookie the picker writes and locale detection reads. Site-scoped and readable
|
|
82
|
+
* by client script (not httpOnly). Defaults to `"locale"`.
|
|
83
|
+
*/
|
|
84
|
+
cookie?: string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Absolute site origin (e.g. `"https://example.com"`) used to build absolute URLs in
|
|
87
|
+
* `hreflangAlternates`. Optional; only that helper needs it.
|
|
88
|
+
*/
|
|
89
|
+
origin?: string | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Path prefixes that must never be localized (e.g. `["/api"]`), matched segment-aware so
|
|
92
|
+
* `/api` and `/api/x` are excluded but `/apis` is not. Defaults to `[]`.
|
|
93
|
+
*/
|
|
94
|
+
nonLocalizedPrefixes?: readonly string[] | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* The URL scheme for the default locale (see {@link RoutingStrategy}). `"prefix-except-default"`
|
|
97
|
+
* serves the default locale at bare URLs; `"prefix-all"` prefixes every locale including the
|
|
98
|
+
* default. Defaults to `"prefix-except-default"`.
|
|
99
|
+
*/
|
|
100
|
+
strategy?: RoutingStrategy | undefined;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A static piece of user-facing text: exactly one string per locale in `L`.
|
|
104
|
+
*
|
|
105
|
+
* @typeParam L - the locale union every key must cover.
|
|
106
|
+
* @example { en: "Answer my first call free", nl: "Beantwoord mijn eerste oproep gratis" }
|
|
107
|
+
*/
|
|
108
|
+
export type LanguageText<L extends string> = {
|
|
109
|
+
readonly [K in L]: string;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* A parameterized piece of user-facing text: one builder function per locale in `L`. Use this
|
|
113
|
+
* wherever a string interpolates a runtime value, so each locale keeps control of word order.
|
|
114
|
+
*
|
|
115
|
+
* @typeParam L - the locale union every key must cover.
|
|
116
|
+
* @typeParam A - the builder's argument tuple (inferred at the call site).
|
|
117
|
+
* @example { en: (name: string) => `Good morning, ${name}`, nl: (name: string) => `Goedemorgen, ${name}` }
|
|
118
|
+
*/
|
|
119
|
+
export type LanguageTextFn<L extends string, A extends readonly unknown[]> = {
|
|
120
|
+
readonly [K in L]: (...args: A) => string;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* The shape a co-located copy catalog is constrained to, so TypeScript forces every entry to
|
|
124
|
+
* carry all locale keys of `L` while each entry keeps its precise literal type (needed for
|
|
125
|
+
* argument inference in a {@link Translator}). The `readonly never[]` argument keeps the
|
|
126
|
+
* function arm contravariant, so any parameterized builder satisfies the constraint.
|
|
127
|
+
*
|
|
128
|
+
* @typeParam L - the locale union every entry must cover.
|
|
129
|
+
*/
|
|
130
|
+
export type LanguageTextCatalog<L extends string> = Record<string, LanguageText<L> | LanguageTextFn<L, readonly never[]>>;
|
|
131
|
+
/**
|
|
132
|
+
* A translate function bound to one locale. Overloaded so the same call resolves both static and
|
|
133
|
+
* parameterized text:
|
|
134
|
+
* - `translate(text)` for a {@link LanguageText} -> the string.
|
|
135
|
+
* - `translate(text, ...args)` for a {@link LanguageTextFn} -> the built string.
|
|
136
|
+
*
|
|
137
|
+
* @typeParam L - the locale union the text objects are keyed by.
|
|
138
|
+
*/
|
|
139
|
+
export interface Translator<L extends string> {
|
|
140
|
+
/**
|
|
141
|
+
* Resolve a static text to its string for the bound locale.
|
|
142
|
+
*
|
|
143
|
+
* @param text - the {@link LanguageText} to resolve.
|
|
144
|
+
* @returns the string for the bound locale.
|
|
145
|
+
*/
|
|
146
|
+
(text: LanguageText<L>): string;
|
|
147
|
+
/**
|
|
148
|
+
* Resolve a parameterized text, applying the arguments its per-locale builder expects.
|
|
149
|
+
*
|
|
150
|
+
* @param text - the {@link LanguageTextFn} to resolve.
|
|
151
|
+
* @param args - the arguments its builder expects.
|
|
152
|
+
* @returns the built string for the bound locale.
|
|
153
|
+
*/
|
|
154
|
+
<A extends readonly unknown[]>(text: LanguageTextFn<L, A>, ...args: A): string;
|
|
155
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure type core of i18nkit. Every user-facing string is a {@link LanguageText} (static)
|
|
3
|
+
* or a {@link LanguageTextFn} (parameterized): an object with exactly one entry per locale in
|
|
4
|
+
* the caller's locale union `L`. Because these are mapped types over `L`, adding a locale to
|
|
5
|
+
* an {@link I18n} instance's config grows `L`, which turns every catalog entry still missing
|
|
6
|
+
* that locale into a compile error - that is the whole point: 100% type-safe coverage.
|
|
7
|
+
*
|
|
8
|
+
* This file has zero imports (no `react`, no `node:*`) so it can be shared by server, client,
|
|
9
|
+
* and edge code alike.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Props for {@link LanguagePicker}. All optional - `<LanguagePicker />` works out of the box.
|
|
4
|
+
*/
|
|
5
|
+
export interface LanguagePickerProps {
|
|
6
|
+
/** Accessible name for the trigger button. Default `"Change language"`. */
|
|
7
|
+
changeLanguageLabel?: string | undefined;
|
|
8
|
+
/** Heading shown above the locale list; pass `""` to hide it. Default `"Language"`. */
|
|
9
|
+
headingLabel?: string | undefined;
|
|
10
|
+
/** Render a flag (or any node) for a locale code, shown before its label. Default: none. */
|
|
11
|
+
renderFlag?: ((locale: string) => ReactNode) | undefined;
|
|
12
|
+
/** Extra class name added to the wrapper, for positioning/scoping. */
|
|
13
|
+
className?: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Render the language picker.
|
|
17
|
+
*
|
|
18
|
+
* @param props - see {@link LanguagePickerProps}.
|
|
19
|
+
* @returns the picker control.
|
|
20
|
+
*/
|
|
21
|
+
export declare function LanguagePicker({ changeLanguageLabel, headingLabel, renderFlag, className, }?: LanguagePickerProps): ReactElement;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* A self-contained, accessible locale dropdown: its own open state, click-away, and Escape
|
|
5
|
+
* handling, so it drops into any client surface. Reads the active locale and the locale list from
|
|
6
|
+
* the {@link I18nProvider} context and switches via {@link useSetLocale}.
|
|
7
|
+
*
|
|
8
|
+
* Framework-agnostic: it shows each locale's endonym label by default. Pass `renderFlag` to prepend
|
|
9
|
+
* a flag node per locale - use the shipped {@link localeFlag} for the built-in flag set
|
|
10
|
+
* (`renderFlag={localeFlag}`) or supply your own. A `renderFlag` that returns `null` for a locale
|
|
11
|
+
* (as `localeFlag` does for locales without a known flag) simply shows no flag for it. Style it with
|
|
12
|
+
* the shipped stylesheet (`import "@daanvandenbergh/i18nkit/styles.css"`), fully overridable through
|
|
13
|
+
* its `--i18nkit-*` CSS custom properties.
|
|
14
|
+
*/
|
|
15
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
16
|
+
import { useI18n, useLocale, useSetLocale } from "./provider.js";
|
|
17
|
+
/**
|
|
18
|
+
* Render the language picker.
|
|
19
|
+
*
|
|
20
|
+
* @param props - see {@link LanguagePickerProps}.
|
|
21
|
+
* @returns the picker control.
|
|
22
|
+
*/
|
|
23
|
+
export function LanguagePicker({ changeLanguageLabel = "Change language", headingLabel = "Language", renderFlag, className, } = {}) {
|
|
24
|
+
const i18n = useI18n();
|
|
25
|
+
const locale = useLocale();
|
|
26
|
+
const setLocale = useSetLocale();
|
|
27
|
+
const [open, setOpen] = useState(false);
|
|
28
|
+
const wrapRef = useRef(null);
|
|
29
|
+
const triggerRef = useRef(null);
|
|
30
|
+
const menuId = useId();
|
|
31
|
+
// Dismiss on outside pointer-down or Escape while open. Escape returns focus to the trigger
|
|
32
|
+
// (keyboard dismissal); an outside pointer-down leaves focus wherever the user clicked.
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!open) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
function onPointerDown(event) {
|
|
38
|
+
if (wrapRef.current && !wrapRef.current.contains(event.target)) {
|
|
39
|
+
setOpen(false);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function onKey(event) {
|
|
43
|
+
if (event.key === "Escape") {
|
|
44
|
+
setOpen(false);
|
|
45
|
+
triggerRef.current?.focus();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
49
|
+
window.addEventListener("keydown", onKey);
|
|
50
|
+
return () => {
|
|
51
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
52
|
+
window.removeEventListener("keydown", onKey);
|
|
53
|
+
};
|
|
54
|
+
}, [open]);
|
|
55
|
+
/** Selects a locale, closes the list, and returns focus to the trigger. */
|
|
56
|
+
function choose(code) {
|
|
57
|
+
setLocale(code);
|
|
58
|
+
setOpen(false);
|
|
59
|
+
triggerRef.current?.focus();
|
|
60
|
+
}
|
|
61
|
+
const active = i18n.locales[locale];
|
|
62
|
+
const activeLabel = active ? active.label : locale;
|
|
63
|
+
const triggerFlag = renderFlag ? renderFlag(locale) : null;
|
|
64
|
+
return (_jsxs("div", { className: className ? `i18nkit-picker ${className}` : "i18nkit-picker", ref: wrapRef, children: [_jsxs("button", { type: "button", ref: triggerRef, className: "i18nkit-picker__trigger", onClick: () => setOpen((v) => !v), "aria-label": `${changeLanguageLabel}: ${activeLabel}`, "aria-expanded": open, "aria-controls": open ? menuId : undefined, children: [triggerFlag ? _jsx("span", { className: "i18nkit-picker__flag", children: triggerFlag }) : null, _jsx("span", { className: "i18nkit-picker__current", children: activeLabel }), _jsx("svg", { className: open
|
|
65
|
+
? "i18nkit-picker__caret i18nkit-picker__caret--open"
|
|
66
|
+
: "i18nkit-picker__caret", width: 10, height: 10, viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, focusable: false, children: _jsx("path", { d: "M6 9l6 6 6-6", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round" }) })] }), open ? (_jsxs("div", { className: "i18nkit-picker__panel", id: menuId, role: "group", "aria-label": changeLanguageLabel, children: [headingLabel ? _jsx("div", { className: "i18nkit-picker__heading", children: headingLabel }) : null, i18n.list.map((info) => {
|
|
67
|
+
const itemFlag = renderFlag ? renderFlag(info.code) : null;
|
|
68
|
+
return (_jsxs("button", { type: "button", className: "i18nkit-picker__item", "aria-current": info.code === locale ? "true" : undefined, onClick: () => choose(info.code), children: [itemFlag ? (_jsx("span", { className: "i18nkit-picker__flag", children: itemFlag })) : null, _jsx("span", { className: "i18nkit-picker__label", children: info.label }), info.code === locale ? (_jsx("svg", { className: "i18nkit-picker__check", width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, focusable: false, children: _jsx("path", { d: "M20 6L9 17l-5-5", stroke: "currentColor", strokeWidth: 2.4, strokeLinecap: "round", strokeLinejoin: "round" }) })) : null] }, info.code));
|
|
69
|
+
})] })) : null] }));
|
|
70
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ElementType, ReactElement } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Props for {@link LocaleLink}: every standard anchor attribute (except `href`, which is
|
|
4
|
+
* localized) plus the polymorphic `as`.
|
|
5
|
+
*/
|
|
6
|
+
export interface LocaleLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
|
|
7
|
+
/** The link target, written unprefixed (e.g. `"/pricing"`); localized to the active locale. */
|
|
8
|
+
href: string;
|
|
9
|
+
/**
|
|
10
|
+
* The component to render. Defaults to `"a"`. Pass your framework's link component; it receives
|
|
11
|
+
* the localized value as its `href` prop and all other props unchanged.
|
|
12
|
+
*/
|
|
13
|
+
as?: ElementType | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Render a locale-aware link.
|
|
17
|
+
*
|
|
18
|
+
* @param props - see {@link LocaleLinkProps}.
|
|
19
|
+
* @returns the rendered link element.
|
|
20
|
+
*/
|
|
21
|
+
export declare function LocaleLink({ href, as, ...rest }: LocaleLinkProps): ReactElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* A locale-aware link: a link written `href="/pricing"` on a `/nl/...` page renders as
|
|
4
|
+
* `/nl/pricing`, following the active locale. Localizes the href through the active
|
|
5
|
+
* {@link I18n} instance's `localizeHref`, then renders a plain `<a>` by default - or any framework
|
|
6
|
+
* link component passed via `as` (Next's `Link`, Astro's `<a>`, etc.), which receives the localized
|
|
7
|
+
* value as its `href` prop.
|
|
8
|
+
*/
|
|
9
|
+
import { createElement } from "react";
|
|
10
|
+
import { useI18n, useLocale } from "./provider.js";
|
|
11
|
+
/**
|
|
12
|
+
* Render a locale-aware link.
|
|
13
|
+
*
|
|
14
|
+
* @param props - see {@link LocaleLinkProps}.
|
|
15
|
+
* @returns the rendered link element.
|
|
16
|
+
*/
|
|
17
|
+
export function LocaleLink({ href, as, ...rest }) {
|
|
18
|
+
const i18n = useI18n();
|
|
19
|
+
const locale = useLocale();
|
|
20
|
+
const localized = i18n.localizeHref(href, locale);
|
|
21
|
+
const Component = as ?? "a";
|
|
22
|
+
return createElement(Component, { href: localized, ...rest });
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* The flag for a locale, drawn as a flat rounded chip - or nothing when no known flag matches.
|
|
4
|
+
*
|
|
5
|
+
* @param props.code - the locale code (e.g. `"en"`, `"pt-BR"`, `"de-CH"`).
|
|
6
|
+
* @param props.size - the rendered width in px (default 20; height is 3/4 of it).
|
|
7
|
+
* @returns the flag SVG, or `null` for an unknown locale.
|
|
8
|
+
*/
|
|
9
|
+
export declare function Flag({ code, size }: {
|
|
10
|
+
code: string;
|
|
11
|
+
size?: number;
|
|
12
|
+
}): ReactElement | null;
|
|
13
|
+
/**
|
|
14
|
+
* A ready-made `renderFlag` for {@link LanguagePicker}: `<LanguagePicker renderFlag={localeFlag} />`.
|
|
15
|
+
* Returns the built-in flag for the locale, or `null` for locales without one (the picker then
|
|
16
|
+
* shows just the label).
|
|
17
|
+
*
|
|
18
|
+
* @param locale - the locale code to draw a flag for.
|
|
19
|
+
* @returns the flag node, or `null`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function localeFlag(locale: string): ReactNode;
|