tera-system-ui 0.1.64 → 0.1.66
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/dist/COMPONENT_API.md +2 -539
- package/dist/components/accordion/Accordion.d.ts +24 -0
- package/dist/components/accordion/Accordion.js +4 -0
- package/dist/components/accordion/components/Accordion.svelte +2 -8
- package/dist/components/accordion/components/AccordionContent.svelte +5 -12
- package/dist/components/accordion/components/AccordionItem.svelte +3 -9
- package/dist/components/accordion/components/AccordionTrigger.svelte +5 -15
- package/dist/components/ai/ChatBubble.svelte +35 -0
- package/dist/components/ai/ChatBubble.svelte.d.ts +12 -0
- package/dist/components/ai/PromptInput.svelte +58 -0
- package/dist/components/ai/PromptInput.svelte.d.ts +13 -0
- package/dist/components/ai/StreamText.svelte +41 -0
- package/dist/components/ai/StreamText.svelte.d.ts +11 -0
- package/dist/components/ai/SuggestionChips.svelte +34 -0
- package/dist/components/ai/SuggestionChips.svelte.d.ts +10 -0
- package/dist/components/ai/ThinkingLoader.svelte +34 -0
- package/dist/components/ai/ThinkingLoader.svelte.d.ts +11 -0
- package/dist/components/ai/index.d.ts +5 -0
- package/dist/components/ai/index.js +5 -0
- package/dist/components/alert/Alert.svelte +47 -0
- package/dist/components/alert/Alert.svelte.d.ts +15 -0
- package/dist/components/alert/index.d.ts +1 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/avatar/Avatar.svelte +9 -25
- package/dist/components/badge/Badge.d.ts +52 -0
- package/dist/components/badge/Badge.js +22 -0
- package/dist/components/badge/Badge.svelte +22 -0
- package/dist/components/badge/Badge.svelte.d.ts +4 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/brand-logo/BrandLogo.svelte +12 -10
- package/dist/components/button/Button.d.ts +2 -2
- package/dist/components/button/Button.js +12 -12
- package/dist/components/button/Button.svelte +7 -34
- package/dist/components/card/Card.d.ts +68 -0
- package/dist/components/card/Card.js +28 -0
- package/dist/components/card/Card.svelte +33 -0
- package/dist/components/card/Card.svelte.d.ts +4 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/checkbox/Checkbox.d.ts +25 -4
- package/dist/components/checkbox/Checkbox.js +4 -0
- package/dist/components/checkbox/Checkbox.svelte +13 -16
- package/dist/components/checkbox/Checkbox.svelte.d.ts +2 -2
- package/dist/components/combobox/Combobox.d.ts +45 -9
- package/dist/components/combobox/Combobox.js +5 -7
- package/dist/components/combobox/Combobox.svelte +226 -8
- package/dist/components/combobox/Combobox.svelte.d.ts +2 -2
- package/dist/components/combobox/index.d.ts +1 -1
- package/dist/components/command/components/command-empty.svelte +3 -8
- package/dist/components/command/components/command-group.svelte +3 -13
- package/dist/components/command/components/command-input.svelte +5 -13
- package/dist/components/command/components/command-item.svelte +3 -9
- package/dist/components/command/components/command-link-item.svelte +3 -8
- package/dist/components/command/components/command-list.svelte +3 -8
- package/dist/components/command/components/command-separator.svelte +3 -8
- package/dist/components/command/components/command-shortcut.svelte +2 -10
- package/dist/components/command/components/command.svelte +29 -42
- package/dist/components/date-range-picker/DateRangePicker.svelte +490 -0
- package/dist/components/date-range-picker/DateRangePicker.svelte.d.ts +4 -0
- package/dist/components/date-range-picker/DateRangePicker.types.d.ts +38 -0
- package/dist/components/date-range-picker/DateRangePicker.types.js +1 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/dialog/Dialog.d.ts +43 -121
- package/dist/components/dialog/Dialog.js +1 -39
- package/dist/components/dialog/Dialog.svelte +103 -113
- package/dist/components/dialog/Dialog.svelte.d.ts +1 -2
- package/dist/components/dialog/dialog.scss +21 -24
- package/dist/components/drawer/Drawer.svelte +63 -0
- package/dist/components/drawer/Drawer.svelte.d.ts +16 -0
- package/dist/components/drawer/index.d.ts +1 -0
- package/dist/components/drawer/index.js +1 -0
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +51 -24
- package/dist/components/dropdown-menu/DropdownMenu.js +1 -15
- package/dist/components/dropdown-menu/components/DropdownMenu.svelte +36 -34
- package/dist/components/dropdown-menu/components/DropdownMenu.svelte.d.ts +1 -1
- package/dist/components/dropdown-menu/components/DropdownMenuGroup.svelte +8 -12
- package/dist/components/dropdown-menu/components/DropdownMenuGroup.svelte.d.ts +2 -4
- package/dist/components/dropdown-menu/components/DropdownMenuHeader.svelte +11 -12
- package/dist/components/dropdown-menu/components/DropdownMenuHeader.svelte.d.ts +2 -4
- package/dist/components/dropdown-menu/components/DropdownMenuItem.svelte +27 -30
- package/dist/components/dropdown-menu/components/DropdownMenuItem.svelte.d.ts +1 -1
- package/dist/components/dropdown-menu/components/DropdownMenuSeparator.svelte +9 -11
- package/dist/components/dropdown-menu/components/DropdownMenuSeparator.svelte.d.ts +2 -4
- package/dist/components/fonts/TeraFontMono.svelte +4 -4
- package/dist/components/fonts/TeraFontMono.svelte.d.ts +1 -0
- package/dist/components/fonts/TeraFontSansSerif.svelte +4 -4
- package/dist/components/fonts/TeraFontSansSerif.svelte.d.ts +1 -1
- package/dist/components/header/Header.svelte +6 -9
- package/dist/components/header/header.scss +1 -1
- package/dist/components/icons/IconArrowBigRightFilled.svelte +3 -7
- package/dist/components/icons/IconBook.svelte +3 -6
- package/dist/components/icons/IconBookmarkPlus.svelte +3 -6
- package/dist/components/icons/IconCalculator.svelte +3 -6
- package/dist/components/icons/IconCheck.svelte +3 -6
- package/dist/components/icons/IconChevronDown.svelte +3 -6
- package/dist/components/icons/IconCoin.svelte +3 -6
- package/dist/components/icons/IconCoinConvert.svelte +2 -5
- package/dist/components/icons/IconCopy.svelte +3 -6
- package/dist/components/icons/IconCopyCheckFilled.svelte +3 -6
- package/dist/components/icons/IconHamburger.svelte +3 -6
- package/dist/components/icons/IconLanguage.svelte +3 -6
- package/dist/components/icons/IconLoader2.svelte +3 -6
- package/dist/components/icons/IconLogout.svelte +3 -6
- package/dist/components/icons/IconMoon.svelte +3 -6
- package/dist/components/icons/IconPointFilled.svelte +3 -6
- package/dist/components/icons/IconSearch.svelte +3 -6
- package/dist/components/icons/IconSettings.svelte +3 -6
- package/dist/components/icons/IconSun.svelte +3 -6
- package/dist/components/icons/IconSwitchHorizontal.svelte +3 -6
- package/dist/components/icons/IconSwitchVertical.svelte +3 -6
- package/dist/components/icons/IconTransform.svelte +3 -6
- package/dist/components/icons/IconX.svelte +3 -6
- package/dist/components/input/Input.d.ts +2 -2
- package/dist/components/input/Input.js +10 -10
- package/dist/components/input/Input.svelte +10 -26
- package/dist/components/label/Label.d.ts +2 -2
- package/dist/components/label/Label.js +2 -2
- package/dist/components/label/Label.svelte +4 -12
- package/dist/components/language-picker-button/LanguagePickerButton.svelte +23 -42
- package/dist/components/light-dark-toggle/LightDarkToggle.svelte +21 -26
- package/dist/components/marketing/FeatureCard.svelte +37 -0
- package/dist/components/marketing/FeatureCard.svelte.d.ts +13 -0
- package/dist/components/marketing/PricingCard.svelte +48 -0
- package/dist/components/marketing/PricingCard.svelte.d.ts +15 -0
- package/dist/components/marketing/StatBlock.svelte +14 -0
- package/dist/components/marketing/StatBlock.svelte.d.ts +10 -0
- package/dist/components/marketing/TestimonialCard.svelte +24 -0
- package/dist/components/marketing/TestimonialCard.svelte.d.ts +12 -0
- package/dist/components/marketing/index.d.ts +4 -0
- package/dist/components/marketing/index.js +4 -0
- package/dist/components/popover/Popover.d.ts +32 -13
- package/dist/components/popover/Popover.js +1 -7
- package/dist/components/popover/Popover.svelte +40 -158
- package/dist/components/popover/Popover.svelte.d.ts +2 -2
- package/dist/components/popover-responsive/PopoverResponsive.d.ts +18 -7
- package/dist/components/popover-responsive/PopoverResponsive.js +1 -7
- package/dist/components/popover-responsive/PopoverResponsive.svelte +25 -87
- package/dist/components/popover-responsive/PopoverResponsive.svelte.d.ts +2 -11
- package/dist/components/select/Select.d.ts +60 -23
- package/dist/components/select/Select.js +14 -35
- package/dist/components/select/Select.svelte +157 -28
- package/dist/components/select/Select.svelte.d.ts +2 -3
- package/dist/components/select/index.d.ts +1 -1
- package/dist/components/side-navigation/SideNavigation.svelte +73 -96
- package/dist/components/side-navigation/SideNavigationItem.svelte +2 -2
- package/dist/components/side-navigation/SideNavigationLayout.svelte +3 -5
- package/dist/components/side-navigation/sidenav.scss +17 -13
- package/dist/components/skeleton/Skeleton.svelte +48 -0
- package/dist/components/skeleton/Skeleton.svelte.d.ts +12 -0
- package/dist/components/skeleton/index.d.ts +1 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/slider/Slider.d.ts +25 -15
- package/dist/components/slider/Slider.js +1 -7
- package/dist/components/slider/Slider.svelte +38 -164
- package/dist/components/slider/Slider.svelte.d.ts +1 -1
- package/dist/components/spinner/Spinner.svelte +39 -0
- package/dist/components/spinner/Spinner.svelte.d.ts +10 -0
- package/dist/components/spinner/index.d.ts +1 -0
- package/dist/components/spinner/index.js +1 -0
- package/dist/components/star-rating/StarRating.svelte +33 -49
- package/dist/components/switch/Switch.d.ts +19 -4
- package/dist/components/switch/Switch.js +4 -0
- package/dist/components/switch/Switch.svelte +13 -17
- package/dist/components/switch/Switch.svelte.d.ts +2 -2
- package/dist/components/table/Table.svelte +68 -0
- package/dist/components/table/Table.svelte.d.ts +40 -0
- package/dist/components/table/index.d.ts +1 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/tabs/Tabs.svelte.d.ts +45 -16
- package/dist/components/tabs/Tabs.svelte.js +8 -18
- package/dist/components/tabs/components/Tabs.svelte +27 -33
- package/dist/components/tabs/components/Tabs.svelte.d.ts +1 -1
- package/dist/components/tabs/components/TabsContent.svelte +13 -36
- package/dist/components/tabs/components/TabsContent.svelte.d.ts +2 -5
- package/dist/components/tabs/components/TabsItem.svelte +43 -32
- package/dist/components/tabs/components/TabsItem.svelte.d.ts +2 -5
- package/dist/components/tabs/components/TabsList.svelte +90 -58
- package/dist/components/tabs/components/TabsList.svelte.d.ts +2 -4
- package/dist/components/tera-ui-context/TeraUiContext.svelte +13 -26
- package/dist/components/text-area/TextArea.d.ts +2 -2
- package/dist/components/text-area/TextArea.js +9 -9
- package/dist/components/text-area/TextArea.svelte +41 -65
- package/dist/components/toast/ToastContainer.svelte +50 -0
- package/dist/components/toast/ToastContainer.svelte.d.ts +18 -0
- package/dist/components/toast/index.d.ts +3 -0
- package/dist/components/toast/index.js +2 -0
- package/dist/components/toast/toast.svelte.d.ts +22 -0
- package/dist/components/toast/toast.svelte.js +18 -0
- package/dist/components/tooltip/Tooltip.d.ts +23 -0
- package/dist/components/tooltip/Tooltip.js +1 -0
- package/dist/components/tooltip/Tooltip.svelte +30 -0
- package/dist/components/tooltip/Tooltip.svelte.d.ts +4 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/user-avatar-with-menu/UserAvatarWithMenu.svelte +48 -69
- package/dist/index.d.ts +19 -2
- package/dist/index.js +12 -0
- package/dist/llms/accordion.md +90 -0
- package/dist/llms/ai.md +110 -0
- package/dist/llms/alert.md +29 -0
- package/dist/llms/avatar.md +34 -0
- package/dist/llms/badge.md +31 -0
- package/dist/llms/brand-logo.md +30 -0
- package/dist/llms/button.md +37 -0
- package/dist/llms/card.md +32 -0
- package/dist/llms/checkbox.md +35 -0
- package/dist/llms/colors.md +161 -0
- package/dist/llms/combobox.md +40 -0
- package/dist/llms/command.md +7 -0
- package/dist/llms/date-range-picker.md +36 -0
- package/dist/llms/dialog.md +45 -0
- package/dist/llms/drawer.md +30 -0
- package/dist/llms/dropdown-menu.md +112 -0
- package/dist/llms/fonts.md +7 -0
- package/dist/llms/header.md +26 -0
- package/dist/llms/icons.md +43 -0
- package/dist/llms/index.md +65 -0
- package/dist/llms/input.md +37 -0
- package/dist/llms/label.md +30 -0
- package/dist/llms/language-picker-button.md +30 -0
- package/dist/llms/light-dark-toggle.md +26 -0
- package/dist/llms/marketing.md +95 -0
- package/dist/llms/popover-responsive.md +32 -0
- package/dist/llms/popover.md +40 -0
- package/dist/llms/select.md +44 -0
- package/dist/llms/side-navigation.md +30 -0
- package/dist/llms/skeleton.md +28 -0
- package/dist/llms/slider.md +36 -0
- package/dist/llms/spinner.md +25 -0
- package/dist/llms/star-rating.md +31 -0
- package/dist/llms/switch.md +33 -0
- package/dist/llms/table.md +30 -0
- package/dist/llms/tabs.md +92 -0
- package/dist/llms/tera-ui-context.md +30 -0
- package/dist/llms/text-area.md +39 -0
- package/dist/llms/toast.md +7 -0
- package/dist/llms/tooltip.md +32 -0
- package/dist/llms/user-avatar-with-menu.md +28 -0
- package/dist/paraglide/README.md +72 -3
- package/dist/paraglide/messages/text_account_settings.d.ts +14 -2
- package/dist/paraglide/messages/text_account_settings.js +53 -58
- package/dist/paraglide/messages/text_calces_documentation.d.ts +14 -2
- package/dist/paraglide/messages/text_calces_documentation.js +53 -58
- package/dist/paraglide/messages/text_calces_scientific_calculator.d.ts +14 -2
- package/dist/paraglide/messages/text_calces_scientific_calculator.js +53 -58
- package/dist/paraglide/messages/text_currency_converter.d.ts +14 -2
- package/dist/paraglide/messages/text_currency_converter.js +53 -58
- package/dist/paraglide/messages/text_logout.d.ts +14 -2
- package/dist/paraglide/messages/text_logout.js +53 -58
- package/dist/paraglide/messages/text_select_language.d.ts +14 -2
- package/dist/paraglide/messages/text_select_language.js +53 -58
- package/dist/paraglide/messages/text_unit_converter.d.ts +14 -2
- package/dist/paraglide/messages/text_unit_converter.js +53 -58
- package/dist/paraglide/registry.d.ts +13 -0
- package/dist/paraglide/registry.js +15 -0
- package/dist/paraglide/runtime.d.ts +243 -126
- package/dist/paraglide/runtime.js +473 -148
- package/dist/paraglide/server.d.ts +13 -20
- package/dist/paraglide/server.js +92 -40
- package/dist/stories/ComponentOverview.stories.svelte +533 -0
- package/dist/stories/ComponentOverview.stories.svelte.d.ts +6 -0
- package/dist/themes/tera-ui-base.css +242 -77
- package/dist/themes/theme-ai.css +100 -0
- package/dist/themes/theme-marketing.css +91 -0
- package/dist/themes/theme-professional.css +41 -0
- package/package.json +35 -29
- package/dist/tera-i18n/projects/tera-system-ui/project.inlang/.meta.json +0 -3
- package/dist/tera-i18n/projects/tera-system-ui/project.inlang/README.md +0 -103
- package/dist/tera-i18n/projects/tera-system-ui/project.inlang/project_id +0 -1
- package/dist/themes/tw-preset.cjs +0 -160
- package/dist/themes/tw-preset.d.cts +0 -157
|
@@ -20,7 +20,7 @@ export const baseLocale = "en";
|
|
|
20
20
|
* throw new Error('Locale is not available');
|
|
21
21
|
* }
|
|
22
22
|
*/
|
|
23
|
-
export const locales = /** @type {const} */ (["ar",
|
|
23
|
+
export const locales = /** @type {const} */ (["ar","bg","bn","ca","cs","da","de","el","en","es","fi","fr","he","hi","hu","id","it","ja","ko","lt","lv","ms","nl","no","pl","pt","ro","ru","sk","sl","sq","sr","sv","sw","ta","te","th","tl","tr","uk","vi","zh-CN","zh-TW"]);
|
|
24
24
|
/** @type {string} */
|
|
25
25
|
export const cookieName = "PARAGLIDE_LOCALE";
|
|
26
26
|
/** @type {number} */
|
|
@@ -33,14 +33,27 @@ export const localStorageKey = "PARAGLIDE_LOCALE";
|
|
|
33
33
|
* @type {Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage" | `custom-${string}`>}
|
|
34
34
|
*/
|
|
35
35
|
export const strategy = [
|
|
36
|
+
"url",
|
|
36
37
|
"cookie",
|
|
37
|
-
"
|
|
38
|
+
"preferredLanguage",
|
|
38
39
|
"baseLocale"
|
|
39
40
|
];
|
|
41
|
+
/**
|
|
42
|
+
* Route-level strategy overrides.
|
|
43
|
+
*
|
|
44
|
+
* `match` uses URLPattern syntax.
|
|
45
|
+
*
|
|
46
|
+
* @type {Array<{
|
|
47
|
+
* match: string;
|
|
48
|
+
* strategy?: Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage" | `custom-${string}`>;
|
|
49
|
+
* exclude?: boolean;
|
|
50
|
+
* }>}
|
|
51
|
+
*/
|
|
52
|
+
export const routeStrategies = [];
|
|
40
53
|
/**
|
|
41
54
|
* The used URL patterns.
|
|
42
55
|
*
|
|
43
|
-
* @type {Array<{ pattern: string, localized: Array<[Locale, string]> }>
|
|
56
|
+
* @type {Array<{ pattern: string, localized: Array<[Locale, string]> }>}
|
|
44
57
|
*/
|
|
45
58
|
export const urlPatterns = [
|
|
46
59
|
{
|
|
@@ -221,6 +234,62 @@ export const urlPatterns = [
|
|
|
221
234
|
]
|
|
222
235
|
}
|
|
223
236
|
];
|
|
237
|
+
/** @type {string | undefined} */
|
|
238
|
+
let cachedRouteStrategyUrl;
|
|
239
|
+
/** @type {{ match: string; strategy?: typeof strategy; exclude?: boolean } | undefined} */
|
|
240
|
+
let cachedRouteStrategy;
|
|
241
|
+
/**
|
|
242
|
+
* @param {string | URL} url
|
|
243
|
+
* @returns {{ match: string; strategy?: typeof strategy; exclude?: boolean } | undefined}
|
|
244
|
+
*/
|
|
245
|
+
function findMatchingRouteStrategy(url) {
|
|
246
|
+
if (routeStrategies.length === 0) {
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
const urlString = typeof url === "string" ? url : url.href;
|
|
250
|
+
if (cachedRouteStrategyUrl === urlString) {
|
|
251
|
+
return cachedRouteStrategy;
|
|
252
|
+
}
|
|
253
|
+
const urlObject = new URL(urlString, "http://dummy.com");
|
|
254
|
+
let match;
|
|
255
|
+
for (const routeStrategy of routeStrategies) {
|
|
256
|
+
const pattern = new URLPattern(routeStrategy.match, urlObject.href);
|
|
257
|
+
if (pattern.exec(urlObject.href)) {
|
|
258
|
+
match = routeStrategy;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
cachedRouteStrategyUrl = urlString;
|
|
263
|
+
cachedRouteStrategy = match;
|
|
264
|
+
return match;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Returns the strategy to use for a specific URL.
|
|
268
|
+
*
|
|
269
|
+
* If no route strategy matches (or the matching rule is `exclude: true`),
|
|
270
|
+
* the global strategy is returned.
|
|
271
|
+
*
|
|
272
|
+
* @param {string | URL} url
|
|
273
|
+
* @returns {typeof strategy}
|
|
274
|
+
*/
|
|
275
|
+
export function getStrategyForUrl(url) {
|
|
276
|
+
const routeStrategy = findMatchingRouteStrategy(url);
|
|
277
|
+
if (routeStrategy &&
|
|
278
|
+
routeStrategy.exclude !== true &&
|
|
279
|
+
Array.isArray(routeStrategy.strategy)) {
|
|
280
|
+
return routeStrategy.strategy;
|
|
281
|
+
}
|
|
282
|
+
return strategy;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Returns whether the given URL is excluded from middleware i18n processing.
|
|
286
|
+
*
|
|
287
|
+
* @param {string | URL} url
|
|
288
|
+
* @returns {boolean}
|
|
289
|
+
*/
|
|
290
|
+
export function isExcludedByRouteStrategy(url) {
|
|
291
|
+
return findMatchingRouteStrategy(url)?.exclude === true;
|
|
292
|
+
}
|
|
224
293
|
/**
|
|
225
294
|
* @typedef {{
|
|
226
295
|
* getStore(): {
|
|
@@ -243,9 +312,8 @@ export const urlPatterns = [
|
|
|
243
312
|
export let serverAsyncLocalStorage = undefined;
|
|
244
313
|
export const disableAsyncLocalStorage = false;
|
|
245
314
|
export const experimentalMiddlewareLocaleSplitting = false;
|
|
246
|
-
export const isServer = typeof window === 'undefined';
|
|
315
|
+
export const isServer = import.meta.env?.SSR ?? typeof window === 'undefined';
|
|
247
316
|
/** @type {Locale | undefined} */
|
|
248
|
-
// @ts-ignore - injected by bundlers at compile time
|
|
249
317
|
export const experimentalStaticLocale = undefined;
|
|
250
318
|
/**
|
|
251
319
|
* Sets the server side async local storage.
|
|
@@ -261,22 +329,25 @@ export function overwriteServerAsyncLocalStorage(value) {
|
|
|
261
329
|
serverAsyncLocalStorage = value;
|
|
262
330
|
}
|
|
263
331
|
const TREE_SHAKE_COOKIE_STRATEGY_USED = true;
|
|
264
|
-
const TREE_SHAKE_URL_STRATEGY_USED =
|
|
265
|
-
const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED =
|
|
266
|
-
const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED =
|
|
332
|
+
const TREE_SHAKE_URL_STRATEGY_USED = true;
|
|
333
|
+
const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = false;
|
|
334
|
+
const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = true;
|
|
267
335
|
const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = true;
|
|
268
336
|
const TREE_SHAKE_LOCAL_STORAGE_STRATEGY_USED = false;
|
|
269
337
|
|
|
270
|
-
globalThis.__paraglide =
|
|
338
|
+
/** @type {any} */ (globalThis).__paraglide =
|
|
339
|
+
/** @type {any} */ (globalThis).__paraglide ?? {};
|
|
340
|
+
/** @type {any} */ (globalThis).__paraglide.ssr =
|
|
341
|
+
/** @type {any} */ (globalThis).__paraglide.ssr ?? {};
|
|
271
342
|
|
|
272
343
|
/**
|
|
273
344
|
* This is a fallback to get started with a custom
|
|
274
345
|
* strategy and avoid type errors.
|
|
275
346
|
*
|
|
276
347
|
* The implementation is overwritten
|
|
277
|
-
* by
|
|
348
|
+
* by `overwriteGetLocale()` and `defineSetLocale()`.
|
|
278
349
|
*
|
|
279
|
-
* @type {Locale|undefined}
|
|
350
|
+
* @type {Locale | undefined}
|
|
280
351
|
*/
|
|
281
352
|
let _locale;
|
|
282
353
|
let localeInitiallySet = false;
|
|
@@ -296,14 +367,12 @@ let localeInitiallySet = false;
|
|
|
296
367
|
* console.log('Netherlands 🇳🇱');
|
|
297
368
|
* }
|
|
298
369
|
*
|
|
299
|
-
* @
|
|
370
|
+
* @returns {Locale} The current locale.
|
|
300
371
|
*/
|
|
301
372
|
export let getLocale = () => {
|
|
302
373
|
if (experimentalStaticLocale !== undefined) {
|
|
303
|
-
return
|
|
374
|
+
return experimentalStaticLocale;
|
|
304
375
|
}
|
|
305
|
-
/** @type {string | undefined} */
|
|
306
|
-
let locale;
|
|
307
376
|
// if running in a server-side rendering context
|
|
308
377
|
// retrieve the locale from the async local storage
|
|
309
378
|
if (serverAsyncLocalStorage) {
|
|
@@ -312,7 +381,48 @@ export let getLocale = () => {
|
|
|
312
381
|
return locale;
|
|
313
382
|
}
|
|
314
383
|
}
|
|
315
|
-
|
|
384
|
+
let strategyToUse = strategy;
|
|
385
|
+
if (!isServer && typeof window !== "undefined" && window.location?.href) {
|
|
386
|
+
strategyToUse = getStrategyForUrl(window.location.href);
|
|
387
|
+
}
|
|
388
|
+
const resolved = resolveLocaleWithStrategies(strategyToUse, typeof window !== "undefined" ? window.location?.href : undefined);
|
|
389
|
+
if (resolved) {
|
|
390
|
+
if (!localeInitiallySet) {
|
|
391
|
+
_locale = resolved;
|
|
392
|
+
// https://github.com/opral/inlang-paraglide-js/issues/455
|
|
393
|
+
localeInitiallySet = true;
|
|
394
|
+
setLocale(resolved, { reload: false });
|
|
395
|
+
}
|
|
396
|
+
return resolved;
|
|
397
|
+
}
|
|
398
|
+
throw new Error("No locale found. Read the docs https://inlang.com/m/gerre34r/library-inlang-paraglideJs/errors#no-locale-found");
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Resolve locale for a given URL using route-aware strategies.
|
|
402
|
+
*
|
|
403
|
+
* @param {string | URL} url
|
|
404
|
+
* @returns {Locale}
|
|
405
|
+
*/
|
|
406
|
+
export function getLocaleForUrl(url) {
|
|
407
|
+
if (experimentalStaticLocale !== undefined) {
|
|
408
|
+
return experimentalStaticLocale;
|
|
409
|
+
}
|
|
410
|
+
const strategyToUse = getStrategyForUrl(url);
|
|
411
|
+
const resolved = resolveLocaleWithStrategies(strategyToUse, typeof url === "string" ? url : url.href);
|
|
412
|
+
if (resolved) {
|
|
413
|
+
return resolved;
|
|
414
|
+
}
|
|
415
|
+
throw new Error("No locale found. Read the docs https://inlang.com/m/gerre34r/library-inlang-paraglideJs/errors#no-locale-found");
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* @param {typeof strategy} strategyToUse
|
|
419
|
+
* @param {string | undefined} urlForUrlStrategy
|
|
420
|
+
* @returns {Locale | undefined}
|
|
421
|
+
*/
|
|
422
|
+
function resolveLocaleWithStrategies(strategyToUse, urlForUrlStrategy) {
|
|
423
|
+
/** @type {string | undefined} */
|
|
424
|
+
let locale;
|
|
425
|
+
for (const strat of strategyToUse) {
|
|
316
426
|
if (TREE_SHAKE_COOKIE_STRATEGY_USED && strat === "cookie") {
|
|
317
427
|
locale = extractLocaleFromCookie();
|
|
318
428
|
}
|
|
@@ -322,8 +432,8 @@ export let getLocale = () => {
|
|
|
322
432
|
else if (TREE_SHAKE_URL_STRATEGY_USED &&
|
|
323
433
|
strat === "url" &&
|
|
324
434
|
!isServer &&
|
|
325
|
-
typeof
|
|
326
|
-
locale = extractLocaleFromUrl(
|
|
435
|
+
typeof urlForUrlStrategy === "string") {
|
|
436
|
+
locale = extractLocaleFromUrl(urlForUrlStrategy);
|
|
327
437
|
}
|
|
328
438
|
else if (TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED &&
|
|
329
439
|
strat === "globalVariable" &&
|
|
@@ -349,23 +459,18 @@ export let getLocale = () => {
|
|
|
349
459
|
// Can't await in sync function, skip async strategies
|
|
350
460
|
continue;
|
|
351
461
|
}
|
|
352
|
-
|
|
462
|
+
if (result !== undefined) {
|
|
463
|
+
return assertIsLocale(result);
|
|
464
|
+
}
|
|
353
465
|
}
|
|
354
466
|
}
|
|
355
|
-
|
|
356
|
-
if (
|
|
357
|
-
|
|
358
|
-
if (!localeInitiallySet) {
|
|
359
|
-
_locale = asserted;
|
|
360
|
-
// https://github.com/opral/inlang-paraglide-js/issues/455
|
|
361
|
-
localeInitiallySet = true;
|
|
362
|
-
setLocale(asserted, { reload: false });
|
|
363
|
-
}
|
|
364
|
-
return asserted;
|
|
467
|
+
const matchedLocale = toLocale(locale);
|
|
468
|
+
if (matchedLocale) {
|
|
469
|
+
return matchedLocale;
|
|
365
470
|
}
|
|
366
471
|
}
|
|
367
|
-
|
|
368
|
-
}
|
|
472
|
+
return undefined;
|
|
473
|
+
}
|
|
369
474
|
/**
|
|
370
475
|
* Overwrite the `getLocale()` function.
|
|
371
476
|
*
|
|
@@ -379,17 +484,61 @@ export let getLocale = () => {
|
|
|
379
484
|
* return Cookies.get('locale') ?? baseLocale
|
|
380
485
|
* });
|
|
381
486
|
*
|
|
382
|
-
* @
|
|
487
|
+
* @param {() => Locale} fn - The new implementation for `getLocale()`.
|
|
383
488
|
*/
|
|
384
489
|
export const overwriteGetLocale = (fn) => {
|
|
385
490
|
getLocale = fn;
|
|
386
491
|
};
|
|
387
492
|
|
|
493
|
+
const rtlLanguages = new Set([
|
|
494
|
+
"ar",
|
|
495
|
+
"dv",
|
|
496
|
+
"fa",
|
|
497
|
+
"he",
|
|
498
|
+
"ks",
|
|
499
|
+
"ku",
|
|
500
|
+
"ps",
|
|
501
|
+
"sd",
|
|
502
|
+
"ug",
|
|
503
|
+
"ur",
|
|
504
|
+
"yi",
|
|
505
|
+
]);
|
|
506
|
+
/**
|
|
507
|
+
* Get writing direction for a locale.
|
|
508
|
+
*
|
|
509
|
+
* Uses `Intl.Locale` text info when available and falls back to a
|
|
510
|
+
* language-based RTL check for runtimes without `getTextInfo()`.
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* getTextDirection(); // "ltr" or "rtl" for current locale
|
|
514
|
+
* getTextDirection("ar"); // "rtl"
|
|
515
|
+
* getTextDirection("en"); // "ltr"
|
|
516
|
+
*
|
|
517
|
+
* @param {string} [locale] - Target locale. If not provided, uses `getLocale()`
|
|
518
|
+
* @returns {"ltr" | "rtl"}
|
|
519
|
+
*/
|
|
520
|
+
export function getTextDirection(locale = getLocale()) {
|
|
521
|
+
try {
|
|
522
|
+
const intlLocale = /** @type {Intl.Locale & {
|
|
523
|
+
getTextInfo?: () => { direction?: string };
|
|
524
|
+
textInfo?: { direction?: string };
|
|
525
|
+
}} */ (new Intl.Locale(locale));
|
|
526
|
+
const direction = intlLocale.getTextInfo?.().direction ?? intlLocale.textInfo?.direction;
|
|
527
|
+
if (direction === "ltr" || direction === "rtl") {
|
|
528
|
+
return direction;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
catch {
|
|
532
|
+
// Ignore Intl.Locale parsing/runtime errors and use fallback below.
|
|
533
|
+
}
|
|
534
|
+
const language = locale.split("-")[0]?.toLowerCase();
|
|
535
|
+
return rtlLanguages.has(language ?? "") ? "rtl" : "ltr";
|
|
536
|
+
}
|
|
537
|
+
|
|
388
538
|
/**
|
|
389
539
|
* Navigates to the localized URL, or reloads the current page
|
|
390
540
|
*
|
|
391
541
|
* @param {string} [newLocation] The new location
|
|
392
|
-
* @return {undefined}
|
|
393
542
|
*/
|
|
394
543
|
const navigateOrReload = (newLocation) => {
|
|
395
544
|
if (newLocation) {
|
|
@@ -440,11 +589,15 @@ export let setLocale = (newLocale, options) => {
|
|
|
440
589
|
catch {
|
|
441
590
|
// do nothing, no locale has been set yet.
|
|
442
591
|
}
|
|
443
|
-
/** @type {Array<Promise<
|
|
592
|
+
/** @type {Array<Promise<void>>} */
|
|
444
593
|
const customSetLocalePromises = [];
|
|
445
594
|
/** @type {string | undefined} */
|
|
446
595
|
let newLocation = undefined;
|
|
447
|
-
|
|
596
|
+
let strategyToUse = strategy;
|
|
597
|
+
if (!isServer && typeof window !== "undefined" && window.location?.href) {
|
|
598
|
+
strategyToUse = getStrategyForUrl(window.location.href);
|
|
599
|
+
}
|
|
600
|
+
for (const strat of strategyToUse) {
|
|
448
601
|
if (TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED &&
|
|
449
602
|
strat === "globalVariable") {
|
|
450
603
|
// a default for a custom strategy to get started quickly
|
|
@@ -521,7 +674,7 @@ export let setLocale = (newLocale, options) => {
|
|
|
521
674
|
return;
|
|
522
675
|
};
|
|
523
676
|
/**
|
|
524
|
-
* Overwrite the
|
|
677
|
+
* Overwrite the `setLocale()` function.
|
|
525
678
|
*
|
|
526
679
|
* Use this function to overwrite how the locale is set. For example,
|
|
527
680
|
* modify a cookie, env variable, or a user's preference.
|
|
@@ -535,7 +688,7 @@ export let setLocale = (newLocale, options) => {
|
|
|
535
688
|
* @param {SetLocaleFn} fn
|
|
536
689
|
*/
|
|
537
690
|
export const overwriteSetLocale = (fn) => {
|
|
538
|
-
setLocale =
|
|
691
|
+
setLocale = fn;
|
|
539
692
|
};
|
|
540
693
|
|
|
541
694
|
/**
|
|
@@ -562,14 +715,32 @@ export let getUrlOrigin = () => {
|
|
|
562
715
|
* Use this function in server environments to
|
|
563
716
|
* define how the URL origin is resolved.
|
|
564
717
|
*
|
|
565
|
-
* @
|
|
718
|
+
* @param {() => string} fn - The new implementation for `getUrlOrigin()`.
|
|
566
719
|
*/
|
|
567
720
|
export let overwriteGetUrlOrigin = (fn) => {
|
|
568
721
|
getUrlOrigin = fn;
|
|
569
722
|
};
|
|
570
723
|
|
|
571
724
|
/**
|
|
572
|
-
*
|
|
725
|
+
* Coerces a locale-like string to the canonical locale value used by the runtime.
|
|
726
|
+
*
|
|
727
|
+
* @param {unknown} value
|
|
728
|
+
* @returns {Locale | undefined}
|
|
729
|
+
*/
|
|
730
|
+
export function toLocale(value) {
|
|
731
|
+
if (typeof value !== "string") {
|
|
732
|
+
return undefined;
|
|
733
|
+
}
|
|
734
|
+
const lowerValue = value.toLowerCase();
|
|
735
|
+
for (const locale of locales) {
|
|
736
|
+
if (locale.toLowerCase() === lowerValue) {
|
|
737
|
+
return locale;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return undefined;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Check if something is an available locale with the canonical project casing.
|
|
573
744
|
*
|
|
574
745
|
* @example
|
|
575
746
|
* if (isLocale(params.locale)) {
|
|
@@ -578,36 +749,32 @@ export let overwriteGetUrlOrigin = (fn) => {
|
|
|
578
749
|
* setLocale('en');
|
|
579
750
|
* }
|
|
580
751
|
*
|
|
581
|
-
*
|
|
752
|
+
* Use `toLocale()` when you want case-insensitive matching and canonicalization.
|
|
753
|
+
*
|
|
754
|
+
* @param {unknown} locale
|
|
582
755
|
* @returns {locale is Locale}
|
|
583
756
|
*/
|
|
584
757
|
export function isLocale(locale) {
|
|
585
|
-
|
|
586
|
-
return false;
|
|
587
|
-
return !locale
|
|
588
|
-
? false
|
|
589
|
-
: locales.some((item) => item.toLowerCase() === locale.toLowerCase());
|
|
758
|
+
return !!locale && locales.some((item) => item === locale);
|
|
590
759
|
}
|
|
591
|
-
|
|
592
760
|
/**
|
|
593
|
-
* Asserts that the input
|
|
761
|
+
* Asserts that the input can be normalized to a locale.
|
|
594
762
|
*
|
|
595
|
-
* @param {
|
|
596
|
-
* @returns {Locale} The input
|
|
763
|
+
* @param {unknown} input - The input to check.
|
|
764
|
+
* @returns {Locale} The input normalized to a Locale.
|
|
597
765
|
* @throws {Error} If the input is not a locale.
|
|
598
766
|
*/
|
|
599
767
|
export function assertIsLocale(input) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const matchedLocale = locales.find((item) => item.toLowerCase() === lowerInput);
|
|
605
|
-
if (!matchedLocale) {
|
|
606
|
-
throw new Error(`Invalid locale: ${input}. Expected one of: ${locales.join(", ")}`);
|
|
607
|
-
}
|
|
608
|
-
return matchedLocale;
|
|
768
|
+
const locale = toLocale(input);
|
|
769
|
+
if (locale)
|
|
770
|
+
return locale;
|
|
771
|
+
throw new Error(`Invalid locale: ${input}. Expected one of: ${locales.join(", ")}`);
|
|
609
772
|
}
|
|
610
773
|
|
|
774
|
+
/**
|
|
775
|
+
* @typedef {object} ExtractLocaleFromRequestOptions
|
|
776
|
+
* @property {string | URL} [effectiveRequestUrl] - Effective request URL to use for route matching and locale detection with the URL strategy.
|
|
777
|
+
*/
|
|
611
778
|
/**
|
|
612
779
|
* Extracts a locale from a request.
|
|
613
780
|
*
|
|
@@ -624,12 +791,27 @@ export function assertIsLocale(input) {
|
|
|
624
791
|
* @example
|
|
625
792
|
* const locale = extractLocaleFromRequest(request);
|
|
626
793
|
*
|
|
627
|
-
* @
|
|
794
|
+
* @param {Request} request
|
|
795
|
+
* @param {ExtractLocaleFromRequestOptions} [options]
|
|
796
|
+
* @returns {Locale}
|
|
797
|
+
*/
|
|
798
|
+
export const extractLocaleFromRequest = (request, options = {}) => {
|
|
799
|
+
const effectiveRequestUrl = resolveEffectiveRequestUrl(request, options.effectiveRequestUrl);
|
|
800
|
+
return extractLocaleFromRequestWithStrategies(request, getStrategyForUrl(effectiveRequestUrl), effectiveRequestUrl);
|
|
801
|
+
};
|
|
802
|
+
/**
|
|
803
|
+
* Extracts a locale from a request using the provided strategy order.
|
|
804
|
+
*
|
|
805
|
+
* @param {Request} request
|
|
806
|
+
* @param {typeof strategy} strategies
|
|
807
|
+
* @param {string | URL} [url]
|
|
808
|
+
* @returns {Locale}
|
|
628
809
|
*/
|
|
629
|
-
export const
|
|
810
|
+
export const extractLocaleFromRequestWithStrategies = (request, strategies, url = request.url) => {
|
|
811
|
+
const effectiveRequestUrl = resolveEffectiveRequestUrl(request, url);
|
|
630
812
|
/** @type {string|undefined} */
|
|
631
813
|
let locale;
|
|
632
|
-
for (const strat of
|
|
814
|
+
for (const strat of strategies) {
|
|
633
815
|
if (TREE_SHAKE_COOKIE_STRATEGY_USED && strat === "cookie") {
|
|
634
816
|
locale = request.headers
|
|
635
817
|
.get("cookie")
|
|
@@ -638,7 +820,7 @@ export const extractLocaleFromRequest = (request) => {
|
|
|
638
820
|
?.split("=")[1];
|
|
639
821
|
}
|
|
640
822
|
else if (TREE_SHAKE_URL_STRATEGY_USED && strat === "url") {
|
|
641
|
-
locale = extractLocaleFromUrl(
|
|
823
|
+
locale = extractLocaleFromUrl(effectiveRequestUrl);
|
|
642
824
|
}
|
|
643
825
|
else if (TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED &&
|
|
644
826
|
strat === "preferredLanguage") {
|
|
@@ -658,17 +840,24 @@ export const extractLocaleFromRequest = (request) => {
|
|
|
658
840
|
// Use extractLocaleFromRequestAsync for custom server strategies
|
|
659
841
|
continue;
|
|
660
842
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
return assertIsLocale(locale);
|
|
667
|
-
}
|
|
843
|
+
const matchedLocale = toLocale(locale);
|
|
844
|
+
if (matchedLocale) {
|
|
845
|
+
return matchedLocale;
|
|
668
846
|
}
|
|
669
847
|
}
|
|
670
848
|
throw new Error("No locale found. There is an error in your strategy. Try adding 'baseLocale' as the very last strategy. Read more here https://inlang.com/m/gerre34r/library-inlang-paraglideJs/errors#no-locale-found");
|
|
671
849
|
};
|
|
850
|
+
/**
|
|
851
|
+
* @param {Request} request
|
|
852
|
+
* @param {string | URL | undefined} effectiveRequestUrl
|
|
853
|
+
* @returns {URL}
|
|
854
|
+
*/
|
|
855
|
+
function resolveEffectiveRequestUrl(request, effectiveRequestUrl = request.url) {
|
|
856
|
+
if (effectiveRequestUrl instanceof URL) {
|
|
857
|
+
return new URL(effectiveRequestUrl.href);
|
|
858
|
+
}
|
|
859
|
+
return new URL(effectiveRequestUrl, request.url);
|
|
860
|
+
}
|
|
672
861
|
|
|
673
862
|
/**
|
|
674
863
|
* Asynchronously extracts a locale from a request.
|
|
@@ -697,11 +886,15 @@ export const extractLocaleFromRequest = (request) => {
|
|
|
697
886
|
*
|
|
698
887
|
* const locale = await extractLocaleFromRequestAsync(request);
|
|
699
888
|
*
|
|
700
|
-
* @
|
|
889
|
+
* @param {Request} request - The request object to extract the locale from.
|
|
890
|
+
* @param {{ effectiveRequestUrl?: string | URL }} [options] - Effective request URL to use for route matching and locale detection with the URL strategy.
|
|
891
|
+
* @returns {Promise<Locale>} The extracted locale.
|
|
701
892
|
*/
|
|
702
|
-
export const extractLocaleFromRequestAsync = async (request) => {
|
|
893
|
+
export const extractLocaleFromRequestAsync = async (request, options = {}) => {
|
|
703
894
|
/** @type {string|undefined} */
|
|
704
895
|
let locale;
|
|
896
|
+
const effectiveRequestUrl = resolveEffectiveRequestUrlFromRequestAsync(request, options.effectiveRequestUrl);
|
|
897
|
+
const strategy = getStrategyForUrl(effectiveRequestUrl);
|
|
705
898
|
// Process custom strategies first, in order
|
|
706
899
|
for (const strat of strategy) {
|
|
707
900
|
if (isCustomStrategy(strat) && customServerStrategies.has(strat)) {
|
|
@@ -711,15 +904,26 @@ export const extractLocaleFromRequestAsync = async (request) => {
|
|
|
711
904
|
locale = await handler.getLocale(request);
|
|
712
905
|
}
|
|
713
906
|
// If we got a valid locale from this custom strategy, use it
|
|
714
|
-
|
|
715
|
-
|
|
907
|
+
const matchedLocale = toLocale(locale);
|
|
908
|
+
if (matchedLocale) {
|
|
909
|
+
return matchedLocale;
|
|
716
910
|
}
|
|
717
911
|
}
|
|
718
912
|
}
|
|
719
913
|
// If no custom strategy provided a valid locale, fall back to sync version
|
|
720
|
-
|
|
721
|
-
return assertIsLocale(locale);
|
|
914
|
+
return extractLocaleFromRequestWithStrategies(request, strategy, effectiveRequestUrl);
|
|
722
915
|
};
|
|
916
|
+
/**
|
|
917
|
+
* @param {Request} request
|
|
918
|
+
* @param {string | URL | undefined} effectiveRequestUrl
|
|
919
|
+
* @returns {URL}
|
|
920
|
+
*/
|
|
921
|
+
function resolveEffectiveRequestUrlFromRequestAsync(request, effectiveRequestUrl = request.url) {
|
|
922
|
+
if (effectiveRequestUrl instanceof URL) {
|
|
923
|
+
return new URL(effectiveRequestUrl.href);
|
|
924
|
+
}
|
|
925
|
+
return new URL(effectiveRequestUrl, request.url);
|
|
926
|
+
}
|
|
723
927
|
|
|
724
928
|
/**
|
|
725
929
|
* Extracts a cookie from the document.
|
|
@@ -727,7 +931,7 @@ export const extractLocaleFromRequestAsync = async (request) => {
|
|
|
727
931
|
* Will return undefined if the document is not available or if the cookie is not set.
|
|
728
932
|
* The `document` object is not available in server-side rendering, so this function should not be called in that context.
|
|
729
933
|
*
|
|
730
|
-
* @returns {
|
|
934
|
+
* @returns {Locale | undefined}
|
|
731
935
|
*/
|
|
732
936
|
export function extractLocaleFromCookie() {
|
|
733
937
|
if (typeof document === "undefined" || !document.cookie) {
|
|
@@ -735,10 +939,7 @@ export function extractLocaleFromCookie() {
|
|
|
735
939
|
}
|
|
736
940
|
const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
|
|
737
941
|
const locale = match?.[2];
|
|
738
|
-
|
|
739
|
-
return locale;
|
|
740
|
-
}
|
|
741
|
-
return undefined;
|
|
942
|
+
return toLocale(locale);
|
|
742
943
|
}
|
|
743
944
|
|
|
744
945
|
/**
|
|
@@ -750,9 +951,8 @@ export function extractLocaleFromCookie() {
|
|
|
750
951
|
* @example
|
|
751
952
|
* const locale = extractLocaleFromHeader(request);
|
|
752
953
|
*
|
|
753
|
-
* @type {(request: Request) => Locale}
|
|
754
954
|
* @param {Request} request - The request object to extract the locale from.
|
|
755
|
-
* @returns {
|
|
955
|
+
* @returns {Locale | undefined} The negotiated preferred language.
|
|
756
956
|
*/
|
|
757
957
|
export function extractLocaleFromHeader(request) {
|
|
758
958
|
const acceptLanguageHeader = request.headers.get("accept-language");
|
|
@@ -763,20 +963,22 @@ export function extractLocaleFromHeader(request) {
|
|
|
763
963
|
.map((lang) => {
|
|
764
964
|
const [tag, q = "1"] = lang.trim().split(";q=");
|
|
765
965
|
// Get both the full tag and base language code
|
|
766
|
-
const baseTag = tag?.split("-")[0]
|
|
966
|
+
const baseTag = tag?.split("-")[0];
|
|
767
967
|
return {
|
|
768
|
-
fullTag: tag
|
|
968
|
+
fullTag: tag,
|
|
769
969
|
baseTag,
|
|
770
970
|
q: Number(q),
|
|
771
971
|
};
|
|
772
972
|
})
|
|
773
973
|
.sort((a, b) => b.q - a.q);
|
|
774
974
|
for (const lang of languages) {
|
|
775
|
-
|
|
776
|
-
|
|
975
|
+
const fullLocale = toLocale(lang.fullTag);
|
|
976
|
+
if (fullLocale) {
|
|
977
|
+
return fullLocale;
|
|
777
978
|
}
|
|
778
|
-
|
|
779
|
-
|
|
979
|
+
const baseLocale = toLocale(lang.baseTag);
|
|
980
|
+
if (baseLocale) {
|
|
981
|
+
return baseLocale;
|
|
780
982
|
}
|
|
781
983
|
}
|
|
782
984
|
return undefined;
|
|
@@ -793,23 +995,24 @@ export function extractLocaleFromHeader(request) {
|
|
|
793
995
|
* @example
|
|
794
996
|
* const locale = extractLocaleFromNavigator();
|
|
795
997
|
*
|
|
796
|
-
* @
|
|
797
|
-
* @returns {string | undefined}
|
|
998
|
+
* @returns {Locale | undefined}
|
|
798
999
|
*/
|
|
799
1000
|
export function extractLocaleFromNavigator() {
|
|
800
1001
|
if (!navigator?.languages?.length) {
|
|
801
1002
|
return undefined;
|
|
802
1003
|
}
|
|
803
1004
|
const languages = navigator.languages.map((lang) => ({
|
|
804
|
-
fullTag: lang
|
|
805
|
-
baseTag: lang.split("-")[0]
|
|
1005
|
+
fullTag: lang,
|
|
1006
|
+
baseTag: lang.split("-")[0],
|
|
806
1007
|
}));
|
|
807
1008
|
for (const lang of languages) {
|
|
808
|
-
|
|
809
|
-
|
|
1009
|
+
const fullLocale = toLocale(lang.fullTag);
|
|
1010
|
+
if (fullLocale) {
|
|
1011
|
+
return fullLocale;
|
|
810
1012
|
}
|
|
811
|
-
|
|
812
|
-
|
|
1013
|
+
const baseLocale = toLocale(lang.baseTag);
|
|
1014
|
+
if (baseLocale) {
|
|
1015
|
+
return baseLocale;
|
|
813
1016
|
}
|
|
814
1017
|
}
|
|
815
1018
|
return undefined;
|
|
@@ -828,6 +1031,10 @@ let cachedLocale;
|
|
|
828
1031
|
/**
|
|
829
1032
|
* Extracts the locale from a given URL using native URLPattern.
|
|
830
1033
|
*
|
|
1034
|
+
* The built-in default `/:locale/...` routing is case-insensitive because it
|
|
1035
|
+
* canonicalizes the first path segment with `toLocale()`. Custom `urlPatterns`
|
|
1036
|
+
* keep URLPattern's normal exact matching semantics for path segments.
|
|
1037
|
+
*
|
|
831
1038
|
* @param {URL|string} url - The full URL from which to extract the locale.
|
|
832
1039
|
* @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
|
|
833
1040
|
*/
|
|
@@ -836,6 +1043,7 @@ export function extractLocaleFromUrl(url) {
|
|
|
836
1043
|
if (cachedUrl === urlString) {
|
|
837
1044
|
return cachedLocale;
|
|
838
1045
|
}
|
|
1046
|
+
/** @type {Locale | undefined} */
|
|
839
1047
|
let result;
|
|
840
1048
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
841
1049
|
result = defaultUrlPatternExtractLocale(url);
|
|
@@ -846,11 +1054,7 @@ export function extractLocaleFromUrl(url) {
|
|
|
846
1054
|
for (const element of urlPatterns) {
|
|
847
1055
|
for (const [locale, localizedPattern] of element.localized) {
|
|
848
1056
|
const match = new URLPattern(localizedPattern, urlObj.href).exec(urlObj.href);
|
|
849
|
-
if (
|
|
850
|
-
continue;
|
|
851
|
-
}
|
|
852
|
-
// Check if the locale is valid
|
|
853
|
-
if (assertIsLocale(locale)) {
|
|
1057
|
+
if (match) {
|
|
854
1058
|
result = locale;
|
|
855
1059
|
break;
|
|
856
1060
|
}
|
|
@@ -866,20 +1070,13 @@ export function extractLocaleFromUrl(url) {
|
|
|
866
1070
|
/**
|
|
867
1071
|
* https://github.com/opral/inlang-paraglide-js/issues/381
|
|
868
1072
|
*
|
|
869
|
-
* @param {URL|string} url - The full URL from which to extract the locale.
|
|
870
|
-
* @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
|
|
1073
|
+
* @param {URL | string} url - The full URL from which to extract the locale.
|
|
1074
|
+
* @returns {Locale | undefined} The extracted locale, or undefined if no locale is found.
|
|
871
1075
|
*/
|
|
872
1076
|
function defaultUrlPatternExtractLocale(url) {
|
|
873
1077
|
const urlObj = new URL(url, "http://dummy.com");
|
|
874
1078
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
875
|
-
|
|
876
|
-
const potentialLocale = pathSegments[0];
|
|
877
|
-
if (isLocale(potentialLocale)) {
|
|
878
|
-
return potentialLocale;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
// everything else has to be the base locale
|
|
882
|
-
return baseLocale;
|
|
1079
|
+
return toLocale(pathSegments[0]) || baseLocale;
|
|
883
1080
|
}
|
|
884
1081
|
|
|
885
1082
|
/**
|
|
@@ -922,15 +1119,17 @@ function defaultUrlPatternExtractLocale(url) {
|
|
|
922
1119
|
* ```
|
|
923
1120
|
*
|
|
924
1121
|
* @param {string | URL} url - The URL to localize. If string, must be absolute.
|
|
925
|
-
* @param {
|
|
926
|
-
* @param {
|
|
1122
|
+
* @param {object} [options] - Options for localization
|
|
1123
|
+
* @param {Locale} [options.locale] - Target locale. If not provided, uses getLocale()
|
|
927
1124
|
* @returns {URL} The localized URL, always absolute
|
|
928
1125
|
*/
|
|
929
1126
|
export function localizeUrl(url, options) {
|
|
1127
|
+
const targetLocale = options?.locale
|
|
1128
|
+
? assertIsLocale(options?.locale)
|
|
1129
|
+
: getLocale();
|
|
930
1130
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
931
|
-
return localizeUrlDefaultPattern(url,
|
|
1131
|
+
return localizeUrlDefaultPattern(url, targetLocale);
|
|
932
1132
|
}
|
|
933
|
-
const targetLocale = options?.locale ?? getLocale();
|
|
934
1133
|
const urlObj = typeof url === "string" ? new URL(url) : url;
|
|
935
1134
|
// Iterate over URL patterns
|
|
936
1135
|
for (const element of urlPatterns) {
|
|
@@ -963,13 +1162,11 @@ export function localizeUrl(url, options) {
|
|
|
963
1162
|
* https://github.com/opral/inlang-paraglide-js/issues/381
|
|
964
1163
|
*
|
|
965
1164
|
* @param {string | URL} url
|
|
966
|
-
* @param {
|
|
967
|
-
* @param {string} [options.locale]
|
|
1165
|
+
* @param {Locale} locale
|
|
968
1166
|
* @returns {URL}
|
|
969
1167
|
*/
|
|
970
|
-
function localizeUrlDefaultPattern(url,
|
|
1168
|
+
function localizeUrlDefaultPattern(url, locale) {
|
|
971
1169
|
const urlObj = typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url);
|
|
972
|
-
const locale = options?.locale ?? getLocale();
|
|
973
1170
|
const currentLocale = extractLocaleFromUrl(urlObj);
|
|
974
1171
|
// If current locale matches target locale, no change needed
|
|
975
1172
|
if (currentLocale === locale) {
|
|
@@ -977,7 +1174,7 @@ function localizeUrlDefaultPattern(url, options) {
|
|
|
977
1174
|
}
|
|
978
1175
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
979
1176
|
// If current path starts with a locale, remove it
|
|
980
|
-
if (pathSegments.length > 0 &&
|
|
1177
|
+
if (pathSegments.length > 0 && toLocale(pathSegments[0])) {
|
|
981
1178
|
pathSegments.shift();
|
|
982
1179
|
}
|
|
983
1180
|
// For base locale, don't add prefix
|
|
@@ -1065,7 +1262,7 @@ function deLocalizeUrlDefaultPattern(url) {
|
|
|
1065
1262
|
const urlObj = typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url);
|
|
1066
1263
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
1067
1264
|
// If first segment is a locale, remove it
|
|
1068
|
-
if (pathSegments.length > 0 &&
|
|
1265
|
+
if (pathSegments.length > 0 && toLocale(pathSegments[0])) {
|
|
1069
1266
|
urlObj.pathname = "/" + pathSegments.slice(1).join("/");
|
|
1070
1267
|
}
|
|
1071
1268
|
return urlObj;
|
|
@@ -1178,7 +1375,8 @@ function fillPattern(pattern, values, origin) {
|
|
|
1178
1375
|
* Aggregates named groups from various parts of the URLPattern match result.
|
|
1179
1376
|
*
|
|
1180
1377
|
*
|
|
1181
|
-
* @
|
|
1378
|
+
* @param {any} match - The URLPattern match result object.
|
|
1379
|
+
* @returns {Record<string, string | null | undefined>} An object containing all named groups from the match.
|
|
1182
1380
|
*/
|
|
1183
1381
|
export function aggregateGroups(match) {
|
|
1184
1382
|
return {
|
|
@@ -1196,19 +1394,19 @@ export function aggregateGroups(match) {
|
|
|
1196
1394
|
/**
|
|
1197
1395
|
* @typedef {object} ShouldRedirectServerInput
|
|
1198
1396
|
* @property {Request} request
|
|
1199
|
-
* @property {string | URL} [
|
|
1200
|
-
* @property {
|
|
1397
|
+
* @property {string | URL} [effectiveRequestUrl] - Effective request URL to use for route matching, locale detection with the URL strategy, and redirect targets.
|
|
1398
|
+
* @property {Locale} [locale]
|
|
1201
1399
|
*
|
|
1202
1400
|
* @typedef {object} ShouldRedirectClientInput
|
|
1203
1401
|
* @property {undefined} [request]
|
|
1204
1402
|
* @property {string | URL} [url]
|
|
1205
|
-
* @property {
|
|
1403
|
+
* @property {Locale} [locale]
|
|
1206
1404
|
*
|
|
1207
1405
|
* @typedef {ShouldRedirectServerInput | ShouldRedirectClientInput} ShouldRedirectInput
|
|
1208
1406
|
*
|
|
1209
1407
|
* @typedef {object} ShouldRedirectResult
|
|
1210
1408
|
* @property {boolean} shouldRedirect - Indicates whether the consumer should perform a redirect.
|
|
1211
|
-
* @property {
|
|
1409
|
+
* @property {Locale} locale - Locale resolved using the configured strategies.
|
|
1212
1410
|
* @property {URL | undefined} redirectUrl - Destination URL when a redirect is required.
|
|
1213
1411
|
*/
|
|
1214
1412
|
/**
|
|
@@ -1244,15 +1442,33 @@ export function aggregateGroups(match) {
|
|
|
1244
1442
|
* return render(request, decision.locale);
|
|
1245
1443
|
* }
|
|
1246
1444
|
*
|
|
1445
|
+
* @example
|
|
1446
|
+
* // Server side usage behind a proxy where request.url is not public-facing
|
|
1447
|
+
* export async function handle(request) {
|
|
1448
|
+
* const effectiveRequestUrl = new URL(request.url);
|
|
1449
|
+
* effectiveRequestUrl.protocol = "https:";
|
|
1450
|
+
* effectiveRequestUrl.host = "example.com";
|
|
1451
|
+
*
|
|
1452
|
+
* const decision = await shouldRedirect({
|
|
1453
|
+
* request,
|
|
1454
|
+
* effectiveRequestUrl,
|
|
1455
|
+
* });
|
|
1456
|
+
*
|
|
1457
|
+
* if (decision.shouldRedirect) {
|
|
1458
|
+
* return Response.redirect(decision.redirectUrl, 307);
|
|
1459
|
+
* }
|
|
1460
|
+
* }
|
|
1461
|
+
*
|
|
1247
1462
|
* @param {ShouldRedirectInput} [input]
|
|
1248
1463
|
* @returns {Promise<ShouldRedirectResult>}
|
|
1249
1464
|
*/
|
|
1250
1465
|
export async function shouldRedirect(input = {}) {
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1466
|
+
const currentUrl = resolveUrl(input);
|
|
1467
|
+
const locale = await resolveLocale(input, currentUrl);
|
|
1468
|
+
const strategy = getStrategyForUrl(currentUrl.href);
|
|
1469
|
+
if (isExcludedByRouteStrategy(currentUrl.href) || !strategy.includes("url")) {
|
|
1253
1470
|
return { shouldRedirect: false, locale, redirectUrl: undefined };
|
|
1254
1471
|
}
|
|
1255
|
-
const currentUrl = resolveUrl(input);
|
|
1256
1472
|
const localizedUrl = localizeUrl(currentUrl.href, { locale });
|
|
1257
1473
|
const shouldRedirectToLocalizedUrl = normalizeUrl(localizedUrl.href) !== normalizeUrl(currentUrl.href);
|
|
1258
1474
|
return {
|
|
@@ -1265,14 +1481,21 @@ export async function shouldRedirect(input = {}) {
|
|
|
1265
1481
|
* Resolves the locale either from the provided input or by using the configured strategies.
|
|
1266
1482
|
*
|
|
1267
1483
|
* @param {ShouldRedirectInput} input
|
|
1268
|
-
* @
|
|
1484
|
+
* @param {URL} currentUrl
|
|
1485
|
+
* @returns {Promise<Locale>}
|
|
1269
1486
|
*/
|
|
1270
|
-
async function resolveLocale(input) {
|
|
1271
|
-
|
|
1272
|
-
|
|
1487
|
+
async function resolveLocale(input, currentUrl) {
|
|
1488
|
+
const locale = toLocale(input.locale);
|
|
1489
|
+
if (locale) {
|
|
1490
|
+
return locale;
|
|
1273
1491
|
}
|
|
1274
1492
|
if (input.request) {
|
|
1275
|
-
return extractLocaleFromRequestAsync(input.request
|
|
1493
|
+
return extractLocaleFromRequestAsync(input.request, {
|
|
1494
|
+
effectiveRequestUrl: currentUrl,
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
if ("url" in input && typeof input.url !== "undefined") {
|
|
1498
|
+
return getLocaleForUrl(currentUrl.href);
|
|
1276
1499
|
}
|
|
1277
1500
|
return getLocale();
|
|
1278
1501
|
}
|
|
@@ -1283,13 +1506,19 @@ async function resolveLocale(input) {
|
|
|
1283
1506
|
* @returns {URL}
|
|
1284
1507
|
*/
|
|
1285
1508
|
function resolveUrl(input) {
|
|
1509
|
+
if ("effectiveRequestUrl" in input && input.effectiveRequestUrl instanceof URL) {
|
|
1510
|
+
return new URL(input.effectiveRequestUrl.href);
|
|
1511
|
+
}
|
|
1512
|
+
if ("effectiveRequestUrl" in input && typeof input.effectiveRequestUrl === "string") {
|
|
1513
|
+
return new URL(input.effectiveRequestUrl, input.request ? input.request.url : getUrlOrigin());
|
|
1514
|
+
}
|
|
1286
1515
|
if (input.request) {
|
|
1287
1516
|
return new URL(input.request.url);
|
|
1288
1517
|
}
|
|
1289
|
-
if (input.url instanceof URL) {
|
|
1518
|
+
if ("url" in input && input.url instanceof URL) {
|
|
1290
1519
|
return new URL(input.url.href);
|
|
1291
1520
|
}
|
|
1292
|
-
if (typeof input.url === "string") {
|
|
1521
|
+
if ("url" in input && typeof input.url === "string") {
|
|
1293
1522
|
return new URL(input.url, getUrlOrigin());
|
|
1294
1523
|
}
|
|
1295
1524
|
if (typeof window !== "undefined" && window?.location?.href) {
|
|
@@ -1345,8 +1574,8 @@ function normalizeUrl(url) {
|
|
|
1345
1574
|
* which provides more precise control over URL handling.
|
|
1346
1575
|
*
|
|
1347
1576
|
* @param {string} href - The href to localize (can be relative or absolute)
|
|
1348
|
-
* @param {
|
|
1349
|
-
* @param {
|
|
1577
|
+
* @param {object} [options] - Options for localization
|
|
1578
|
+
* @param {Locale} [options.locale] - Target locale. If not provided, uses `getLocale()`
|
|
1350
1579
|
* @returns {string} The localized href, relative if input was relative
|
|
1351
1580
|
*/
|
|
1352
1581
|
export function localizeHref(href, options) {
|
|
@@ -1478,6 +1707,7 @@ export function trackMessageCall(safeModuleId, locale) {
|
|
|
1478
1707
|
* The order follows each input URL with all its locale variants before moving to the next URL.
|
|
1479
1708
|
*/
|
|
1480
1709
|
export function generateStaticLocalizedUrls(urls) {
|
|
1710
|
+
/** @type {Set<URL>} */
|
|
1481
1711
|
const localizedUrls = new Set();
|
|
1482
1712
|
// For default URL pattern, we can optimize the generation
|
|
1483
1713
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
@@ -1570,7 +1800,7 @@ export const customClientStrategies = new Map();
|
|
|
1570
1800
|
/**
|
|
1571
1801
|
* Checks if the given strategy is a custom strategy.
|
|
1572
1802
|
*
|
|
1573
|
-
* @param {
|
|
1803
|
+
* @param {unknown} strategy The name of the custom strategy to validate.
|
|
1574
1804
|
* Must be a string that starts with "custom-" followed by alphanumeric characters, hyphens, or underscores.
|
|
1575
1805
|
* @returns {boolean} Returns true if it is a custom strategy, false otherwise.
|
|
1576
1806
|
*/
|
|
@@ -1582,7 +1812,7 @@ export function isCustomStrategy(strategy) {
|
|
|
1582
1812
|
*
|
|
1583
1813
|
* @see https://inlang.com/m/gerre34r/library-inlang-paraglideJs/strategy#write-your-own-strategy
|
|
1584
1814
|
*
|
|
1585
|
-
* @param {
|
|
1815
|
+
* @param {string} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
|
|
1586
1816
|
* @param {CustomServerStrategyHandler} handler The handler for the custom strategy, which should implement
|
|
1587
1817
|
* the method getLocale.
|
|
1588
1818
|
* @returns {void}
|
|
@@ -1598,7 +1828,7 @@ export function defineCustomServerStrategy(strategy, handler) {
|
|
|
1598
1828
|
*
|
|
1599
1829
|
* @see https://inlang.com/m/gerre34r/library-inlang-paraglideJs/strategy#write-your-own-strategy
|
|
1600
1830
|
*
|
|
1601
|
-
* @param {
|
|
1831
|
+
* @param {string} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
|
|
1602
1832
|
* @param {CustomClientStrategyHandler} handler The handler for the custom strategy, which should implement the
|
|
1603
1833
|
* methods getLocale and setLocale.
|
|
1604
1834
|
* @returns {void}
|
|
@@ -1611,26 +1841,25 @@ export function defineCustomClientStrategy(strategy, handler) {
|
|
|
1611
1841
|
}
|
|
1612
1842
|
|
|
1613
1843
|
// ------ TYPES ------
|
|
1614
|
-
|
|
1844
|
+
export {};
|
|
1615
1845
|
/**
|
|
1616
1846
|
* A locale that is available in the project.
|
|
1617
1847
|
*
|
|
1618
1848
|
* @example
|
|
1619
1849
|
* setLocale(request.locale as Locale)
|
|
1620
1850
|
*
|
|
1621
|
-
* @typedef {
|
|
1851
|
+
* @typedef {typeof locales[number]} Locale
|
|
1622
1852
|
*/
|
|
1623
|
-
|
|
1624
1853
|
/**
|
|
1625
1854
|
* A branded type representing a localized string.
|
|
1626
1855
|
*
|
|
1627
|
-
* Message functions return this type instead of
|
|
1856
|
+
* Message functions return this type instead of \`string\`, enabling TypeScript
|
|
1628
1857
|
* to distinguish translated strings from regular strings at compile time.
|
|
1629
1858
|
* This allows you to enforce that only properly localized content is used
|
|
1630
1859
|
* in your UI components.
|
|
1631
1860
|
*
|
|
1632
|
-
* Since
|
|
1633
|
-
* backward compatible—you can pass it anywhere a
|
|
1861
|
+
* Since \`LocalizedString\` is a branded subtype of \`string\`, it remains fully
|
|
1862
|
+
* backward compatible—you can pass it anywhere a \`string\` is expected.
|
|
1634
1863
|
*
|
|
1635
1864
|
* @example
|
|
1636
1865
|
* // Enforce localized strings in your components
|
|
@@ -1662,4 +1891,100 @@ export function defineCustomClientStrategy(strategy, handler) {
|
|
|
1662
1891
|
*
|
|
1663
1892
|
* @typedef {string & { readonly __brand: 'LocalizedString' }} LocalizedString
|
|
1664
1893
|
*/
|
|
1665
|
-
|
|
1894
|
+
/**
|
|
1895
|
+
* A single markup option passed to a tag instance.
|
|
1896
|
+
*
|
|
1897
|
+
* @typedef {{
|
|
1898
|
+
* name: string;
|
|
1899
|
+
* value: unknown;
|
|
1900
|
+
* }} MessageMarkupOption
|
|
1901
|
+
*/
|
|
1902
|
+
/**
|
|
1903
|
+
* A single static markup attribute attached to a tag instance.
|
|
1904
|
+
*
|
|
1905
|
+
* @typedef {{
|
|
1906
|
+
* name: string;
|
|
1907
|
+
* value: string | true;
|
|
1908
|
+
* }} MessageMarkupAttribute
|
|
1909
|
+
*/
|
|
1910
|
+
/**
|
|
1911
|
+
* Record of markup options for a tag instance.
|
|
1912
|
+
*
|
|
1913
|
+
* @typedef {Record<string, unknown>} MessageMarkupOptions
|
|
1914
|
+
*/
|
|
1915
|
+
/**
|
|
1916
|
+
* Record of markup attributes for a tag instance.
|
|
1917
|
+
*
|
|
1918
|
+
* @typedef {Record<string, string | true>} MessageMarkupAttributes
|
|
1919
|
+
*/
|
|
1920
|
+
/**
|
|
1921
|
+
* Type-level schema for a single markup tag.
|
|
1922
|
+
*
|
|
1923
|
+
* @typedef {{
|
|
1924
|
+
* options: MessageMarkupOptions;
|
|
1925
|
+
* attributes: MessageMarkupAttributes;
|
|
1926
|
+
* children: boolean;
|
|
1927
|
+
* }} MessageMarkupTag
|
|
1928
|
+
*/
|
|
1929
|
+
/**
|
|
1930
|
+
* Type-level schema for all markup tags in a message.
|
|
1931
|
+
*
|
|
1932
|
+
* @typedef {Record<string, MessageMarkupTag>} MessageMarkupSchema
|
|
1933
|
+
*/
|
|
1934
|
+
/**
|
|
1935
|
+
* Type-only metadata attached to compiled message functions.
|
|
1936
|
+
*
|
|
1937
|
+
* @template Inputs
|
|
1938
|
+
* @template Options
|
|
1939
|
+
* @template {MessageMarkupSchema} [Markup = MessageMarkupSchema]
|
|
1940
|
+
* @typedef {{
|
|
1941
|
+
* readonly __paraglide?: {
|
|
1942
|
+
* inputs: Inputs;
|
|
1943
|
+
* options: Options;
|
|
1944
|
+
* markup: Markup;
|
|
1945
|
+
* };
|
|
1946
|
+
* }} MessageMetadata
|
|
1947
|
+
*/
|
|
1948
|
+
/**
|
|
1949
|
+
* A compiled, framework-neutral message part.
|
|
1950
|
+
*
|
|
1951
|
+
* @typedef {{
|
|
1952
|
+
* type: "text";
|
|
1953
|
+
* value: string;
|
|
1954
|
+
* } | {
|
|
1955
|
+
* type: "markup-start";
|
|
1956
|
+
* name: string;
|
|
1957
|
+
* options: MessageMarkupOptions;
|
|
1958
|
+
* attributes: MessageMarkupAttributes;
|
|
1959
|
+
* } | {
|
|
1960
|
+
* type: "markup-end";
|
|
1961
|
+
* name: string;
|
|
1962
|
+
* options: MessageMarkupOptions;
|
|
1963
|
+
* attributes: MessageMarkupAttributes;
|
|
1964
|
+
* } | {
|
|
1965
|
+
* type: "markup-standalone";
|
|
1966
|
+
* name: string;
|
|
1967
|
+
* options: MessageMarkupOptions;
|
|
1968
|
+
* attributes: MessageMarkupAttributes;
|
|
1969
|
+
* }} MessagePart
|
|
1970
|
+
*/
|
|
1971
|
+
/**
|
|
1972
|
+
* A message function is a message for a specific locale.
|
|
1973
|
+
*
|
|
1974
|
+
* @example
|
|
1975
|
+
* m.hello({ name: 'world' })
|
|
1976
|
+
*
|
|
1977
|
+
* @typedef {(inputs?: Record<string, never>) => LocalizedString} MessageFunction
|
|
1978
|
+
*/
|
|
1979
|
+
/**
|
|
1980
|
+
* A message bundle function that selects the message to be returned.
|
|
1981
|
+
*
|
|
1982
|
+
* Uses `getLocale()` under the hood to determine the locale with an option.
|
|
1983
|
+
*
|
|
1984
|
+
* @template {string} T
|
|
1985
|
+
*
|
|
1986
|
+
* @example
|
|
1987
|
+
* * m.hello({ name: 'world' }, { locale: "en" })
|
|
1988
|
+
*
|
|
1989
|
+
* @typedef {(params: Record<string, never>, options: { locale: T }) => LocalizedString} MessageBundleFunction
|
|
1990
|
+
*/
|