tera-system-ui 0.1.63 → 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 -0
- 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 +71 -2
- package/dist/paraglide/messages/_index.d.ts +7 -21
- package/dist/paraglide/messages/_index.js +7 -485
- package/dist/paraglide/messages/text_account_settings.d.ts +16 -0
- package/dist/paraglide/messages/text_account_settings.js +234 -0
- package/dist/paraglide/messages/text_calces_documentation.d.ts +16 -0
- package/dist/paraglide/messages/text_calces_documentation.js +234 -0
- package/dist/paraglide/messages/text_calces_scientific_calculator.d.ts +16 -0
- package/dist/paraglide/messages/text_calces_scientific_calculator.js +234 -0
- package/dist/paraglide/messages/text_currency_converter.d.ts +16 -0
- package/dist/paraglide/messages/text_currency_converter.js +234 -0
- package/dist/paraglide/messages/text_logout.d.ts +16 -0
- package/dist/paraglide/messages/text_logout.js +234 -0
- package/dist/paraglide/messages/text_select_language.d.ts +16 -0
- package/dist/paraglide/messages/text_select_language.js +234 -0
- package/dist/paraglide/messages/text_unit_converter.d.ts +16 -0
- package/dist/paraglide/messages/text_unit_converter.js +234 -0
- package/dist/paraglide/registry.d.ts +13 -0
- package/dist/paraglide/registry.js +15 -0
- package/dist/paraglide/runtime.d.ts +242 -125
- package/dist/paraglide/runtime.js +467 -143
- 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/tera-i18n/dev-tools/translator/gpt-translator-i18n-message.js +130 -9
- package/dist/tera-i18n/dev-tools/translator/package-lock.json +14 -224
- package/dist/tera-i18n/dev-tools/translator/package.json +1 -1
- package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-calculator.md +34 -0
- package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-cv-maker.md +149 -0
- package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-system.txt +1 -1
- package/dist/tera-i18n/projects/common/all-language-data.js +70 -13
- package/dist/tera-i18n/projects/cv-maker/messages/ar-AE.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/ar-EG.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/ar-IQ.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/ar-SA.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/ar-SD.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/ar-YE.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/ar.json +58 -15
- package/dist/tera-i18n/projects/cv-maker/messages/bg.json +57 -14
- package/dist/tera-i18n/projects/cv-maker/messages/bn.json +65 -22
- package/dist/tera-i18n/projects/cv-maker/messages/ca.json +54 -11
- package/dist/tera-i18n/projects/cv-maker/messages/cs.json +59 -16
- package/dist/tera-i18n/projects/cv-maker/messages/da.json +51 -8
- package/dist/tera-i18n/projects/cv-maker/messages/de.json +58 -15
- package/dist/tera-i18n/projects/cv-maker/messages/el.json +71 -28
- package/dist/tera-i18n/projects/cv-maker/messages/en-AE.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/en-AU.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/en-CA.json +51 -8
- package/dist/tera-i18n/projects/cv-maker/messages/en-GB.json +50 -7
- package/dist/tera-i18n/projects/cv-maker/messages/en-ID.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/en-IN.json +54 -11
- package/dist/tera-i18n/projects/cv-maker/messages/en-NZ.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/en-PH.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/en-PK.json +58 -15
- package/dist/tera-i18n/projects/cv-maker/messages/en-SA.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/en-US.json +51 -8
- package/dist/tera-i18n/projects/cv-maker/messages/en-ZA.json +52 -9
- package/dist/tera-i18n/projects/cv-maker/messages/en.json +45 -16
- package/dist/tera-i18n/projects/cv-maker/messages/es-419.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/es-AR.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/es-ES.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/es-MX.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/es.json +53 -10
- package/dist/tera-i18n/projects/cv-maker/messages/fi.json +52 -9
- package/dist/tera-i18n/projects/cv-maker/messages/fr-MA.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/fr.json +54 -11
- package/dist/tera-i18n/projects/cv-maker/messages/he.json +55 -12
- package/dist/tera-i18n/projects/cv-maker/messages/hi.json +59 -16
- package/dist/tera-i18n/projects/cv-maker/messages/hr.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/messages/hu.json +63 -20
- package/dist/tera-i18n/projects/cv-maker/messages/id.json +60 -17
- package/dist/tera-i18n/projects/cv-maker/messages/it.json +53 -10
- package/dist/tera-i18n/projects/cv-maker/messages/ja.json +62 -19
- package/dist/tera-i18n/projects/cv-maker/messages/ko.json +61 -18
- package/dist/tera-i18n/projects/cv-maker/messages/lt.json +61 -18
- package/dist/tera-i18n/projects/cv-maker/messages/lv.json +61 -18
- package/dist/tera-i18n/projects/cv-maker/messages/ms-MY.json +60 -17
- package/dist/tera-i18n/projects/cv-maker/messages/ms.json +61 -18
- package/dist/tera-i18n/projects/cv-maker/messages/nl.json +53 -10
- package/dist/tera-i18n/projects/cv-maker/messages/no.json +54 -11
- package/dist/tera-i18n/projects/cv-maker/messages/pl.json +59 -16
- package/dist/tera-i18n/projects/cv-maker/messages/pt-BR.json +58 -15
- package/dist/tera-i18n/projects/cv-maker/messages/pt-PT.json +59 -16
- package/dist/tera-i18n/projects/cv-maker/messages/pt.json +66 -23
- package/dist/tera-i18n/projects/cv-maker/messages/ro.json +52 -9
- package/dist/tera-i18n/projects/cv-maker/messages/ru.json +57 -14
- package/dist/tera-i18n/projects/cv-maker/messages/sk.json +62 -19
- package/dist/tera-i18n/projects/cv-maker/messages/sl.json +57 -14
- package/dist/tera-i18n/projects/cv-maker/messages/sq.json +59 -16
- package/dist/tera-i18n/projects/cv-maker/messages/sr.json +91 -48
- package/dist/tera-i18n/projects/cv-maker/messages/sv.json +56 -13
- package/dist/tera-i18n/projects/cv-maker/messages/sw.json +62 -19
- package/dist/tera-i18n/projects/cv-maker/messages/ta.json +72 -29
- package/dist/tera-i18n/projects/cv-maker/messages/te.json +75 -32
- package/dist/tera-i18n/projects/cv-maker/messages/th.json +62 -19
- package/dist/tera-i18n/projects/cv-maker/messages/tl.json +77 -34
- package/dist/tera-i18n/projects/cv-maker/messages/tr.json +63 -20
- package/dist/tera-i18n/projects/cv-maker/messages/uk.json +63 -20
- package/dist/tera-i18n/projects/cv-maker/messages/vi.json +64 -21
- package/dist/tera-i18n/projects/cv-maker/messages/zh-CN.json +63 -20
- package/dist/tera-i18n/projects/cv-maker/messages/zh-TW.json +58 -15
- package/dist/tera-i18n/projects/cv-maker/messages/zh.json +94 -0
- package/dist/tera-i18n/projects/cv-maker/project.inlang/settings.json +82 -68
- package/dist/tera-i18n/projects/cv-maker/supported-language.js +36 -9
- package/dist/tera-i18n/projects/mathda/messages/en.json +4 -0
- package/dist/tera-i18n/projects/mathda/messages/vi.json +4 -0
- package/dist/tera-i18n/projects/mathda/project.inlang/settings.json +15 -0
- package/dist/tera-i18n/projects/mathda/supported-language.d.ts +1 -0
- package/dist/tera-i18n/projects/mathda/supported-language.js +4 -0
- package/dist/tera-i18n/projects/tera-calculator/messages/bg.json +149 -72
- package/dist/tera-i18n/projects/tera-calculator/messages/bn.json +149 -72
- package/dist/tera-i18n/projects/tera-calculator/messages/ca.json +139 -62
- package/dist/tera-i18n/projects/tera-calculator/messages/cs.json +132 -55
- package/dist/tera-i18n/projects/tera-calculator/messages/da.json +132 -55
- package/dist/tera-i18n/projects/tera-calculator/messages/de.json +181 -104
- package/dist/tera-i18n/projects/tera-calculator/messages/el.json +145 -68
- package/dist/tera-i18n/projects/tera-calculator/messages/en-IN.json +183 -0
- package/dist/tera-i18n/projects/tera-calculator/messages/en-PH.json +183 -0
- package/dist/tera-i18n/projects/tera-calculator/messages/en-US.json +183 -0
- package/dist/tera-i18n/projects/tera-calculator/messages/en.json +187 -104
- package/dist/tera-i18n/projects/tera-calculator/messages/es.json +181 -104
- package/dist/tera-i18n/projects/tera-calculator/messages/fi.json +137 -60
- package/dist/tera-i18n/projects/tera-calculator/messages/fr.json +180 -103
- package/dist/tera-i18n/projects/tera-calculator/messages/hi.json +136 -59
- package/dist/tera-i18n/projects/tera-calculator/messages/hu.json +141 -64
- package/dist/tera-i18n/projects/tera-calculator/messages/id.json +132 -55
- package/dist/tera-i18n/projects/tera-calculator/messages/it.json +180 -103
- package/dist/tera-i18n/projects/tera-calculator/messages/ja.json +136 -59
- package/dist/tera-i18n/projects/tera-calculator/messages/ko.json +133 -56
- package/dist/tera-i18n/projects/tera-calculator/messages/lt.json +140 -63
- package/dist/tera-i18n/projects/tera-calculator/messages/lv.json +141 -64
- package/dist/tera-i18n/projects/tera-calculator/messages/ms.json +139 -62
- package/dist/tera-i18n/projects/tera-calculator/messages/nl.json +145 -68
- package/dist/tera-i18n/projects/tera-calculator/messages/no.json +131 -54
- package/dist/tera-i18n/projects/tera-calculator/messages/pl.json +134 -57
- package/dist/tera-i18n/projects/tera-calculator/messages/pt.json +180 -103
- package/dist/tera-i18n/projects/tera-calculator/messages/ro.json +136 -59
- package/dist/tera-i18n/projects/tera-calculator/messages/ru.json +180 -103
- package/dist/tera-i18n/projects/tera-calculator/messages/sk.json +135 -58
- package/dist/tera-i18n/projects/tera-calculator/messages/sl.json +139 -62
- package/dist/tera-i18n/projects/tera-calculator/messages/sq.json +148 -71
- package/dist/tera-i18n/projects/tera-calculator/messages/sr.json +141 -64
- package/dist/tera-i18n/projects/tera-calculator/messages/sv.json +134 -57
- package/dist/tera-i18n/projects/tera-calculator/messages/sw.json +152 -75
- package/dist/tera-i18n/projects/tera-calculator/messages/ta.json +159 -82
- package/dist/tera-i18n/projects/tera-calculator/messages/te.json +165 -88
- package/dist/tera-i18n/projects/tera-calculator/messages/th.json +136 -59
- package/dist/tera-i18n/projects/tera-calculator/messages/tl.json +146 -69
- package/dist/tera-i18n/projects/tera-calculator/messages/tr.json +135 -58
- package/dist/tera-i18n/projects/tera-calculator/messages/uk.json +142 -65
- package/dist/tera-i18n/projects/tera-calculator/messages/vi.json +181 -104
- package/dist/tera-i18n/projects/tera-calculator/messages/zh-CN.json +129 -52
- package/dist/tera-i18n/projects/tera-calculator/messages/zh-TW.json +135 -58
- package/dist/tera-i18n/projects/tera-calculator/project.inlang/settings.json +51 -53
- package/dist/tera-i18n/projects/tera-calculator/supported-language.js +6 -3
- 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 +36 -29
- package/dist/paraglide/messages/ar.d.ts +0 -9
- package/dist/paraglide/messages/ar.js +0 -31
- package/dist/paraglide/messages/bg.d.ts +0 -9
- package/dist/paraglide/messages/bg.js +0 -31
- package/dist/paraglide/messages/bn.d.ts +0 -9
- package/dist/paraglide/messages/bn.js +0 -31
- package/dist/paraglide/messages/ca.d.ts +0 -9
- package/dist/paraglide/messages/ca.js +0 -31
- package/dist/paraglide/messages/cs.d.ts +0 -9
- package/dist/paraglide/messages/cs.js +0 -31
- package/dist/paraglide/messages/da.d.ts +0 -9
- package/dist/paraglide/messages/da.js +0 -31
- package/dist/paraglide/messages/de.d.ts +0 -9
- package/dist/paraglide/messages/de.js +0 -31
- package/dist/paraglide/messages/el.d.ts +0 -9
- package/dist/paraglide/messages/el.js +0 -31
- package/dist/paraglide/messages/en.d.ts +0 -9
- package/dist/paraglide/messages/en.js +0 -31
- package/dist/paraglide/messages/es.d.ts +0 -9
- package/dist/paraglide/messages/es.js +0 -31
- package/dist/paraglide/messages/fi.d.ts +0 -9
- package/dist/paraglide/messages/fi.js +0 -31
- package/dist/paraglide/messages/fr.d.ts +0 -9
- package/dist/paraglide/messages/fr.js +0 -31
- package/dist/paraglide/messages/he.d.ts +0 -9
- package/dist/paraglide/messages/he.js +0 -31
- package/dist/paraglide/messages/hi.d.ts +0 -9
- package/dist/paraglide/messages/hi.js +0 -31
- package/dist/paraglide/messages/hu.d.ts +0 -9
- package/dist/paraglide/messages/hu.js +0 -31
- package/dist/paraglide/messages/id.d.ts +0 -9
- package/dist/paraglide/messages/id.js +0 -31
- package/dist/paraglide/messages/it.d.ts +0 -9
- package/dist/paraglide/messages/it.js +0 -31
- package/dist/paraglide/messages/ja.d.ts +0 -9
- package/dist/paraglide/messages/ja.js +0 -31
- package/dist/paraglide/messages/ko.d.ts +0 -9
- package/dist/paraglide/messages/ko.js +0 -31
- package/dist/paraglide/messages/lt.d.ts +0 -9
- package/dist/paraglide/messages/lt.js +0 -31
- package/dist/paraglide/messages/lv.d.ts +0 -9
- package/dist/paraglide/messages/lv.js +0 -31
- package/dist/paraglide/messages/ms.d.ts +0 -9
- package/dist/paraglide/messages/ms.js +0 -31
- package/dist/paraglide/messages/nl.d.ts +0 -9
- package/dist/paraglide/messages/nl.js +0 -31
- package/dist/paraglide/messages/no.d.ts +0 -9
- package/dist/paraglide/messages/no.js +0 -31
- package/dist/paraglide/messages/pl.d.ts +0 -9
- package/dist/paraglide/messages/pl.js +0 -31
- package/dist/paraglide/messages/pt.d.ts +0 -9
- package/dist/paraglide/messages/pt.js +0 -31
- package/dist/paraglide/messages/ro.d.ts +0 -9
- package/dist/paraglide/messages/ro.js +0 -31
- package/dist/paraglide/messages/ru.d.ts +0 -9
- package/dist/paraglide/messages/ru.js +0 -31
- package/dist/paraglide/messages/sk.d.ts +0 -9
- package/dist/paraglide/messages/sk.js +0 -31
- package/dist/paraglide/messages/sl.d.ts +0 -9
- package/dist/paraglide/messages/sl.js +0 -31
- package/dist/paraglide/messages/sq.d.ts +0 -9
- package/dist/paraglide/messages/sq.js +0 -31
- package/dist/paraglide/messages/sr.d.ts +0 -9
- package/dist/paraglide/messages/sr.js +0 -31
- package/dist/paraglide/messages/sv.d.ts +0 -9
- package/dist/paraglide/messages/sv.js +0 -31
- package/dist/paraglide/messages/sw.d.ts +0 -9
- package/dist/paraglide/messages/sw.js +0 -31
- package/dist/paraglide/messages/ta.d.ts +0 -9
- package/dist/paraglide/messages/ta.js +0 -31
- package/dist/paraglide/messages/te.d.ts +0 -9
- package/dist/paraglide/messages/te.js +0 -31
- package/dist/paraglide/messages/th.d.ts +0 -9
- package/dist/paraglide/messages/th.js +0 -31
- package/dist/paraglide/messages/tl.d.ts +0 -9
- package/dist/paraglide/messages/tl.js +0 -31
- package/dist/paraglide/messages/tr.d.ts +0 -9
- package/dist/paraglide/messages/tr.js +0 -31
- package/dist/paraglide/messages/uk.d.ts +0 -9
- package/dist/paraglide/messages/uk.js +0 -31
- package/dist/paraglide/messages/vi.d.ts +0 -9
- package/dist/paraglide/messages/vi.js +0 -31
- package/dist/paraglide/messages/zh-CN.d.ts +0 -9
- package/dist/paraglide/messages/zh-CN.js +0 -31
- package/dist/paraglide/messages/zh-TW.d.ts +0 -9
- package/dist/paraglide/messages/zh-TW.js +0 -31
- package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-cv-maker.txt +0 -21
- package/dist/tera-i18n/projects/cv-maker/project.inlang/project_id +0 -1
- package/dist/tera-i18n/projects/tera-calculator/messages/ar.json +0 -106
- package/dist/tera-i18n/projects/tera-calculator/messages/he.json +0 -106
- package/dist/tera-i18n/projects/tera-calculator/project.inlang/project_id +0 -1
- 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} */
|
|
@@ -38,10 +38,22 @@ export const strategy = [
|
|
|
38
38
|
"preferredLanguage",
|
|
39
39
|
"baseLocale"
|
|
40
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 = [];
|
|
41
53
|
/**
|
|
42
54
|
* The used URL patterns.
|
|
43
55
|
*
|
|
44
|
-
* @type {Array<{ pattern: string, localized: Array<[Locale, string]> }>
|
|
56
|
+
* @type {Array<{ pattern: string, localized: Array<[Locale, string]> }>}
|
|
45
57
|
*/
|
|
46
58
|
export const urlPatterns = [
|
|
47
59
|
{
|
|
@@ -222,6 +234,62 @@ export const urlPatterns = [
|
|
|
222
234
|
]
|
|
223
235
|
}
|
|
224
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
|
+
}
|
|
225
293
|
/**
|
|
226
294
|
* @typedef {{
|
|
227
295
|
* getStore(): {
|
|
@@ -246,7 +314,6 @@ export const disableAsyncLocalStorage = false;
|
|
|
246
314
|
export const experimentalMiddlewareLocaleSplitting = false;
|
|
247
315
|
export const isServer = import.meta.env?.SSR ?? typeof window === 'undefined';
|
|
248
316
|
/** @type {Locale | undefined} */
|
|
249
|
-
// @ts-ignore - injected by bundlers at compile time
|
|
250
317
|
export const experimentalStaticLocale = undefined;
|
|
251
318
|
/**
|
|
252
319
|
* Sets the server side async local storage.
|
|
@@ -268,16 +335,19 @@ const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = true;
|
|
|
268
335
|
const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = true;
|
|
269
336
|
const TREE_SHAKE_LOCAL_STORAGE_STRATEGY_USED = false;
|
|
270
337
|
|
|
271
|
-
globalThis.__paraglide =
|
|
338
|
+
/** @type {any} */ (globalThis).__paraglide =
|
|
339
|
+
/** @type {any} */ (globalThis).__paraglide ?? {};
|
|
340
|
+
/** @type {any} */ (globalThis).__paraglide.ssr =
|
|
341
|
+
/** @type {any} */ (globalThis).__paraglide.ssr ?? {};
|
|
272
342
|
|
|
273
343
|
/**
|
|
274
344
|
* This is a fallback to get started with a custom
|
|
275
345
|
* strategy and avoid type errors.
|
|
276
346
|
*
|
|
277
347
|
* The implementation is overwritten
|
|
278
|
-
* by
|
|
348
|
+
* by `overwriteGetLocale()` and `defineSetLocale()`.
|
|
279
349
|
*
|
|
280
|
-
* @type {Locale|undefined}
|
|
350
|
+
* @type {Locale | undefined}
|
|
281
351
|
*/
|
|
282
352
|
let _locale;
|
|
283
353
|
let localeInitiallySet = false;
|
|
@@ -297,14 +367,12 @@ let localeInitiallySet = false;
|
|
|
297
367
|
* console.log('Netherlands 🇳🇱');
|
|
298
368
|
* }
|
|
299
369
|
*
|
|
300
|
-
* @
|
|
370
|
+
* @returns {Locale} The current locale.
|
|
301
371
|
*/
|
|
302
372
|
export let getLocale = () => {
|
|
303
373
|
if (experimentalStaticLocale !== undefined) {
|
|
304
|
-
return
|
|
374
|
+
return experimentalStaticLocale;
|
|
305
375
|
}
|
|
306
|
-
/** @type {string | undefined} */
|
|
307
|
-
let locale;
|
|
308
376
|
// if running in a server-side rendering context
|
|
309
377
|
// retrieve the locale from the async local storage
|
|
310
378
|
if (serverAsyncLocalStorage) {
|
|
@@ -313,7 +381,48 @@ export let getLocale = () => {
|
|
|
313
381
|
return locale;
|
|
314
382
|
}
|
|
315
383
|
}
|
|
316
|
-
|
|
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) {
|
|
317
426
|
if (TREE_SHAKE_COOKIE_STRATEGY_USED && strat === "cookie") {
|
|
318
427
|
locale = extractLocaleFromCookie();
|
|
319
428
|
}
|
|
@@ -323,8 +432,8 @@ export let getLocale = () => {
|
|
|
323
432
|
else if (TREE_SHAKE_URL_STRATEGY_USED &&
|
|
324
433
|
strat === "url" &&
|
|
325
434
|
!isServer &&
|
|
326
|
-
typeof
|
|
327
|
-
locale = extractLocaleFromUrl(
|
|
435
|
+
typeof urlForUrlStrategy === "string") {
|
|
436
|
+
locale = extractLocaleFromUrl(urlForUrlStrategy);
|
|
328
437
|
}
|
|
329
438
|
else if (TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED &&
|
|
330
439
|
strat === "globalVariable" &&
|
|
@@ -350,23 +459,18 @@ export let getLocale = () => {
|
|
|
350
459
|
// Can't await in sync function, skip async strategies
|
|
351
460
|
continue;
|
|
352
461
|
}
|
|
353
|
-
|
|
462
|
+
if (result !== undefined) {
|
|
463
|
+
return assertIsLocale(result);
|
|
464
|
+
}
|
|
354
465
|
}
|
|
355
466
|
}
|
|
356
|
-
|
|
357
|
-
if (
|
|
358
|
-
|
|
359
|
-
if (!localeInitiallySet) {
|
|
360
|
-
_locale = asserted;
|
|
361
|
-
// https://github.com/opral/inlang-paraglide-js/issues/455
|
|
362
|
-
localeInitiallySet = true;
|
|
363
|
-
setLocale(asserted, { reload: false });
|
|
364
|
-
}
|
|
365
|
-
return asserted;
|
|
467
|
+
const matchedLocale = toLocale(locale);
|
|
468
|
+
if (matchedLocale) {
|
|
469
|
+
return matchedLocale;
|
|
366
470
|
}
|
|
367
471
|
}
|
|
368
|
-
|
|
369
|
-
}
|
|
472
|
+
return undefined;
|
|
473
|
+
}
|
|
370
474
|
/**
|
|
371
475
|
* Overwrite the `getLocale()` function.
|
|
372
476
|
*
|
|
@@ -380,17 +484,61 @@ export let getLocale = () => {
|
|
|
380
484
|
* return Cookies.get('locale') ?? baseLocale
|
|
381
485
|
* });
|
|
382
486
|
*
|
|
383
|
-
* @
|
|
487
|
+
* @param {() => Locale} fn - The new implementation for `getLocale()`.
|
|
384
488
|
*/
|
|
385
489
|
export const overwriteGetLocale = (fn) => {
|
|
386
490
|
getLocale = fn;
|
|
387
491
|
};
|
|
388
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
|
+
|
|
389
538
|
/**
|
|
390
539
|
* Navigates to the localized URL, or reloads the current page
|
|
391
540
|
*
|
|
392
541
|
* @param {string} [newLocation] The new location
|
|
393
|
-
* @return {undefined}
|
|
394
542
|
*/
|
|
395
543
|
const navigateOrReload = (newLocation) => {
|
|
396
544
|
if (newLocation) {
|
|
@@ -441,11 +589,15 @@ export let setLocale = (newLocale, options) => {
|
|
|
441
589
|
catch {
|
|
442
590
|
// do nothing, no locale has been set yet.
|
|
443
591
|
}
|
|
444
|
-
/** @type {Array<Promise<
|
|
592
|
+
/** @type {Array<Promise<void>>} */
|
|
445
593
|
const customSetLocalePromises = [];
|
|
446
594
|
/** @type {string | undefined} */
|
|
447
595
|
let newLocation = undefined;
|
|
448
|
-
|
|
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) {
|
|
449
601
|
if (TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED &&
|
|
450
602
|
strat === "globalVariable") {
|
|
451
603
|
// a default for a custom strategy to get started quickly
|
|
@@ -522,7 +674,7 @@ export let setLocale = (newLocale, options) => {
|
|
|
522
674
|
return;
|
|
523
675
|
};
|
|
524
676
|
/**
|
|
525
|
-
* Overwrite the
|
|
677
|
+
* Overwrite the `setLocale()` function.
|
|
526
678
|
*
|
|
527
679
|
* Use this function to overwrite how the locale is set. For example,
|
|
528
680
|
* modify a cookie, env variable, or a user's preference.
|
|
@@ -536,7 +688,7 @@ export let setLocale = (newLocale, options) => {
|
|
|
536
688
|
* @param {SetLocaleFn} fn
|
|
537
689
|
*/
|
|
538
690
|
export const overwriteSetLocale = (fn) => {
|
|
539
|
-
setLocale =
|
|
691
|
+
setLocale = fn;
|
|
540
692
|
};
|
|
541
693
|
|
|
542
694
|
/**
|
|
@@ -563,14 +715,32 @@ export let getUrlOrigin = () => {
|
|
|
563
715
|
* Use this function in server environments to
|
|
564
716
|
* define how the URL origin is resolved.
|
|
565
717
|
*
|
|
566
|
-
* @
|
|
718
|
+
* @param {() => string} fn - The new implementation for `getUrlOrigin()`.
|
|
567
719
|
*/
|
|
568
720
|
export let overwriteGetUrlOrigin = (fn) => {
|
|
569
721
|
getUrlOrigin = fn;
|
|
570
722
|
};
|
|
571
723
|
|
|
572
724
|
/**
|
|
573
|
-
*
|
|
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.
|
|
574
744
|
*
|
|
575
745
|
* @example
|
|
576
746
|
* if (isLocale(params.locale)) {
|
|
@@ -579,36 +749,32 @@ export let overwriteGetUrlOrigin = (fn) => {
|
|
|
579
749
|
* setLocale('en');
|
|
580
750
|
* }
|
|
581
751
|
*
|
|
582
|
-
*
|
|
752
|
+
* Use `toLocale()` when you want case-insensitive matching and canonicalization.
|
|
753
|
+
*
|
|
754
|
+
* @param {unknown} locale
|
|
583
755
|
* @returns {locale is Locale}
|
|
584
756
|
*/
|
|
585
757
|
export function isLocale(locale) {
|
|
586
|
-
|
|
587
|
-
return false;
|
|
588
|
-
return !locale
|
|
589
|
-
? false
|
|
590
|
-
: locales.some((item) => item.toLowerCase() === locale.toLowerCase());
|
|
758
|
+
return !!locale && locales.some((item) => item === locale);
|
|
591
759
|
}
|
|
592
|
-
|
|
593
760
|
/**
|
|
594
|
-
* Asserts that the input
|
|
761
|
+
* Asserts that the input can be normalized to a locale.
|
|
595
762
|
*
|
|
596
|
-
* @param {
|
|
597
|
-
* @returns {Locale} The input
|
|
763
|
+
* @param {unknown} input - The input to check.
|
|
764
|
+
* @returns {Locale} The input normalized to a Locale.
|
|
598
765
|
* @throws {Error} If the input is not a locale.
|
|
599
766
|
*/
|
|
600
767
|
export function assertIsLocale(input) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const matchedLocale = locales.find((item) => item.toLowerCase() === lowerInput);
|
|
606
|
-
if (!matchedLocale) {
|
|
607
|
-
throw new Error(`Invalid locale: ${input}. Expected one of: ${locales.join(", ")}`);
|
|
608
|
-
}
|
|
609
|
-
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(", ")}`);
|
|
610
772
|
}
|
|
611
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
|
+
*/
|
|
612
778
|
/**
|
|
613
779
|
* Extracts a locale from a request.
|
|
614
780
|
*
|
|
@@ -625,12 +791,27 @@ export function assertIsLocale(input) {
|
|
|
625
791
|
* @example
|
|
626
792
|
* const locale = extractLocaleFromRequest(request);
|
|
627
793
|
*
|
|
628
|
-
* @
|
|
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}
|
|
629
809
|
*/
|
|
630
|
-
export const
|
|
810
|
+
export const extractLocaleFromRequestWithStrategies = (request, strategies, url = request.url) => {
|
|
811
|
+
const effectiveRequestUrl = resolveEffectiveRequestUrl(request, url);
|
|
631
812
|
/** @type {string|undefined} */
|
|
632
813
|
let locale;
|
|
633
|
-
for (const strat of
|
|
814
|
+
for (const strat of strategies) {
|
|
634
815
|
if (TREE_SHAKE_COOKIE_STRATEGY_USED && strat === "cookie") {
|
|
635
816
|
locale = request.headers
|
|
636
817
|
.get("cookie")
|
|
@@ -639,7 +820,7 @@ export const extractLocaleFromRequest = (request) => {
|
|
|
639
820
|
?.split("=")[1];
|
|
640
821
|
}
|
|
641
822
|
else if (TREE_SHAKE_URL_STRATEGY_USED && strat === "url") {
|
|
642
|
-
locale = extractLocaleFromUrl(
|
|
823
|
+
locale = extractLocaleFromUrl(effectiveRequestUrl);
|
|
643
824
|
}
|
|
644
825
|
else if (TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED &&
|
|
645
826
|
strat === "preferredLanguage") {
|
|
@@ -659,17 +840,24 @@ export const extractLocaleFromRequest = (request) => {
|
|
|
659
840
|
// Use extractLocaleFromRequestAsync for custom server strategies
|
|
660
841
|
continue;
|
|
661
842
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}
|
|
666
|
-
else {
|
|
667
|
-
return assertIsLocale(locale);
|
|
668
|
-
}
|
|
843
|
+
const matchedLocale = toLocale(locale);
|
|
844
|
+
if (matchedLocale) {
|
|
845
|
+
return matchedLocale;
|
|
669
846
|
}
|
|
670
847
|
}
|
|
671
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");
|
|
672
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
|
+
}
|
|
673
861
|
|
|
674
862
|
/**
|
|
675
863
|
* Asynchronously extracts a locale from a request.
|
|
@@ -698,11 +886,15 @@ export const extractLocaleFromRequest = (request) => {
|
|
|
698
886
|
*
|
|
699
887
|
* const locale = await extractLocaleFromRequestAsync(request);
|
|
700
888
|
*
|
|
701
|
-
* @
|
|
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.
|
|
702
892
|
*/
|
|
703
|
-
export const extractLocaleFromRequestAsync = async (request) => {
|
|
893
|
+
export const extractLocaleFromRequestAsync = async (request, options = {}) => {
|
|
704
894
|
/** @type {string|undefined} */
|
|
705
895
|
let locale;
|
|
896
|
+
const effectiveRequestUrl = resolveEffectiveRequestUrlFromRequestAsync(request, options.effectiveRequestUrl);
|
|
897
|
+
const strategy = getStrategyForUrl(effectiveRequestUrl);
|
|
706
898
|
// Process custom strategies first, in order
|
|
707
899
|
for (const strat of strategy) {
|
|
708
900
|
if (isCustomStrategy(strat) && customServerStrategies.has(strat)) {
|
|
@@ -712,15 +904,26 @@ export const extractLocaleFromRequestAsync = async (request) => {
|
|
|
712
904
|
locale = await handler.getLocale(request);
|
|
713
905
|
}
|
|
714
906
|
// If we got a valid locale from this custom strategy, use it
|
|
715
|
-
|
|
716
|
-
|
|
907
|
+
const matchedLocale = toLocale(locale);
|
|
908
|
+
if (matchedLocale) {
|
|
909
|
+
return matchedLocale;
|
|
717
910
|
}
|
|
718
911
|
}
|
|
719
912
|
}
|
|
720
913
|
// If no custom strategy provided a valid locale, fall back to sync version
|
|
721
|
-
|
|
722
|
-
return assertIsLocale(locale);
|
|
914
|
+
return extractLocaleFromRequestWithStrategies(request, strategy, effectiveRequestUrl);
|
|
723
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
|
+
}
|
|
724
927
|
|
|
725
928
|
/**
|
|
726
929
|
* Extracts a cookie from the document.
|
|
@@ -728,7 +931,7 @@ export const extractLocaleFromRequestAsync = async (request) => {
|
|
|
728
931
|
* Will return undefined if the document is not available or if the cookie is not set.
|
|
729
932
|
* The `document` object is not available in server-side rendering, so this function should not be called in that context.
|
|
730
933
|
*
|
|
731
|
-
* @returns {
|
|
934
|
+
* @returns {Locale | undefined}
|
|
732
935
|
*/
|
|
733
936
|
export function extractLocaleFromCookie() {
|
|
734
937
|
if (typeof document === "undefined" || !document.cookie) {
|
|
@@ -736,10 +939,7 @@ export function extractLocaleFromCookie() {
|
|
|
736
939
|
}
|
|
737
940
|
const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
|
|
738
941
|
const locale = match?.[2];
|
|
739
|
-
|
|
740
|
-
return locale;
|
|
741
|
-
}
|
|
742
|
-
return undefined;
|
|
942
|
+
return toLocale(locale);
|
|
743
943
|
}
|
|
744
944
|
|
|
745
945
|
/**
|
|
@@ -751,9 +951,8 @@ export function extractLocaleFromCookie() {
|
|
|
751
951
|
* @example
|
|
752
952
|
* const locale = extractLocaleFromHeader(request);
|
|
753
953
|
*
|
|
754
|
-
* @type {(request: Request) => Locale}
|
|
755
954
|
* @param {Request} request - The request object to extract the locale from.
|
|
756
|
-
* @returns {
|
|
955
|
+
* @returns {Locale | undefined} The negotiated preferred language.
|
|
757
956
|
*/
|
|
758
957
|
export function extractLocaleFromHeader(request) {
|
|
759
958
|
const acceptLanguageHeader = request.headers.get("accept-language");
|
|
@@ -764,20 +963,22 @@ export function extractLocaleFromHeader(request) {
|
|
|
764
963
|
.map((lang) => {
|
|
765
964
|
const [tag, q = "1"] = lang.trim().split(";q=");
|
|
766
965
|
// Get both the full tag and base language code
|
|
767
|
-
const baseTag = tag?.split("-")[0]
|
|
966
|
+
const baseTag = tag?.split("-")[0];
|
|
768
967
|
return {
|
|
769
|
-
fullTag: tag
|
|
968
|
+
fullTag: tag,
|
|
770
969
|
baseTag,
|
|
771
970
|
q: Number(q),
|
|
772
971
|
};
|
|
773
972
|
})
|
|
774
973
|
.sort((a, b) => b.q - a.q);
|
|
775
974
|
for (const lang of languages) {
|
|
776
|
-
|
|
777
|
-
|
|
975
|
+
const fullLocale = toLocale(lang.fullTag);
|
|
976
|
+
if (fullLocale) {
|
|
977
|
+
return fullLocale;
|
|
778
978
|
}
|
|
779
|
-
|
|
780
|
-
|
|
979
|
+
const baseLocale = toLocale(lang.baseTag);
|
|
980
|
+
if (baseLocale) {
|
|
981
|
+
return baseLocale;
|
|
781
982
|
}
|
|
782
983
|
}
|
|
783
984
|
return undefined;
|
|
@@ -794,23 +995,24 @@ export function extractLocaleFromHeader(request) {
|
|
|
794
995
|
* @example
|
|
795
996
|
* const locale = extractLocaleFromNavigator();
|
|
796
997
|
*
|
|
797
|
-
* @
|
|
798
|
-
* @returns {string | undefined}
|
|
998
|
+
* @returns {Locale | undefined}
|
|
799
999
|
*/
|
|
800
1000
|
export function extractLocaleFromNavigator() {
|
|
801
1001
|
if (!navigator?.languages?.length) {
|
|
802
1002
|
return undefined;
|
|
803
1003
|
}
|
|
804
1004
|
const languages = navigator.languages.map((lang) => ({
|
|
805
|
-
fullTag: lang
|
|
806
|
-
baseTag: lang.split("-")[0]
|
|
1005
|
+
fullTag: lang,
|
|
1006
|
+
baseTag: lang.split("-")[0],
|
|
807
1007
|
}));
|
|
808
1008
|
for (const lang of languages) {
|
|
809
|
-
|
|
810
|
-
|
|
1009
|
+
const fullLocale = toLocale(lang.fullTag);
|
|
1010
|
+
if (fullLocale) {
|
|
1011
|
+
return fullLocale;
|
|
811
1012
|
}
|
|
812
|
-
|
|
813
|
-
|
|
1013
|
+
const baseLocale = toLocale(lang.baseTag);
|
|
1014
|
+
if (baseLocale) {
|
|
1015
|
+
return baseLocale;
|
|
814
1016
|
}
|
|
815
1017
|
}
|
|
816
1018
|
return undefined;
|
|
@@ -829,6 +1031,10 @@ let cachedLocale;
|
|
|
829
1031
|
/**
|
|
830
1032
|
* Extracts the locale from a given URL using native URLPattern.
|
|
831
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
|
+
*
|
|
832
1038
|
* @param {URL|string} url - The full URL from which to extract the locale.
|
|
833
1039
|
* @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
|
|
834
1040
|
*/
|
|
@@ -837,6 +1043,7 @@ export function extractLocaleFromUrl(url) {
|
|
|
837
1043
|
if (cachedUrl === urlString) {
|
|
838
1044
|
return cachedLocale;
|
|
839
1045
|
}
|
|
1046
|
+
/** @type {Locale | undefined} */
|
|
840
1047
|
let result;
|
|
841
1048
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
842
1049
|
result = defaultUrlPatternExtractLocale(url);
|
|
@@ -847,11 +1054,7 @@ export function extractLocaleFromUrl(url) {
|
|
|
847
1054
|
for (const element of urlPatterns) {
|
|
848
1055
|
for (const [locale, localizedPattern] of element.localized) {
|
|
849
1056
|
const match = new URLPattern(localizedPattern, urlObj.href).exec(urlObj.href);
|
|
850
|
-
if (
|
|
851
|
-
continue;
|
|
852
|
-
}
|
|
853
|
-
// Check if the locale is valid
|
|
854
|
-
if (assertIsLocale(locale)) {
|
|
1057
|
+
if (match) {
|
|
855
1058
|
result = locale;
|
|
856
1059
|
break;
|
|
857
1060
|
}
|
|
@@ -867,20 +1070,13 @@ export function extractLocaleFromUrl(url) {
|
|
|
867
1070
|
/**
|
|
868
1071
|
* https://github.com/opral/inlang-paraglide-js/issues/381
|
|
869
1072
|
*
|
|
870
|
-
* @param {URL|string} url - The full URL from which to extract the locale.
|
|
871
|
-
* @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.
|
|
872
1075
|
*/
|
|
873
1076
|
function defaultUrlPatternExtractLocale(url) {
|
|
874
1077
|
const urlObj = new URL(url, "http://dummy.com");
|
|
875
1078
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
876
|
-
|
|
877
|
-
const potentialLocale = pathSegments[0];
|
|
878
|
-
if (isLocale(potentialLocale)) {
|
|
879
|
-
return potentialLocale;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
// everything else has to be the base locale
|
|
883
|
-
return baseLocale;
|
|
1079
|
+
return toLocale(pathSegments[0]) || baseLocale;
|
|
884
1080
|
}
|
|
885
1081
|
|
|
886
1082
|
/**
|
|
@@ -923,15 +1119,17 @@ function defaultUrlPatternExtractLocale(url) {
|
|
|
923
1119
|
* ```
|
|
924
1120
|
*
|
|
925
1121
|
* @param {string | URL} url - The URL to localize. If string, must be absolute.
|
|
926
|
-
* @param {
|
|
927
|
-
* @param {
|
|
1122
|
+
* @param {object} [options] - Options for localization
|
|
1123
|
+
* @param {Locale} [options.locale] - Target locale. If not provided, uses getLocale()
|
|
928
1124
|
* @returns {URL} The localized URL, always absolute
|
|
929
1125
|
*/
|
|
930
1126
|
export function localizeUrl(url, options) {
|
|
1127
|
+
const targetLocale = options?.locale
|
|
1128
|
+
? assertIsLocale(options?.locale)
|
|
1129
|
+
: getLocale();
|
|
931
1130
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
932
|
-
return localizeUrlDefaultPattern(url,
|
|
1131
|
+
return localizeUrlDefaultPattern(url, targetLocale);
|
|
933
1132
|
}
|
|
934
|
-
const targetLocale = options?.locale ?? getLocale();
|
|
935
1133
|
const urlObj = typeof url === "string" ? new URL(url) : url;
|
|
936
1134
|
// Iterate over URL patterns
|
|
937
1135
|
for (const element of urlPatterns) {
|
|
@@ -964,13 +1162,11 @@ export function localizeUrl(url, options) {
|
|
|
964
1162
|
* https://github.com/opral/inlang-paraglide-js/issues/381
|
|
965
1163
|
*
|
|
966
1164
|
* @param {string | URL} url
|
|
967
|
-
* @param {
|
|
968
|
-
* @param {string} [options.locale]
|
|
1165
|
+
* @param {Locale} locale
|
|
969
1166
|
* @returns {URL}
|
|
970
1167
|
*/
|
|
971
|
-
function localizeUrlDefaultPattern(url,
|
|
1168
|
+
function localizeUrlDefaultPattern(url, locale) {
|
|
972
1169
|
const urlObj = typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url);
|
|
973
|
-
const locale = options?.locale ?? getLocale();
|
|
974
1170
|
const currentLocale = extractLocaleFromUrl(urlObj);
|
|
975
1171
|
// If current locale matches target locale, no change needed
|
|
976
1172
|
if (currentLocale === locale) {
|
|
@@ -978,7 +1174,7 @@ function localizeUrlDefaultPattern(url, options) {
|
|
|
978
1174
|
}
|
|
979
1175
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
980
1176
|
// If current path starts with a locale, remove it
|
|
981
|
-
if (pathSegments.length > 0 &&
|
|
1177
|
+
if (pathSegments.length > 0 && toLocale(pathSegments[0])) {
|
|
982
1178
|
pathSegments.shift();
|
|
983
1179
|
}
|
|
984
1180
|
// For base locale, don't add prefix
|
|
@@ -1066,7 +1262,7 @@ function deLocalizeUrlDefaultPattern(url) {
|
|
|
1066
1262
|
const urlObj = typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url);
|
|
1067
1263
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
1068
1264
|
// If first segment is a locale, remove it
|
|
1069
|
-
if (pathSegments.length > 0 &&
|
|
1265
|
+
if (pathSegments.length > 0 && toLocale(pathSegments[0])) {
|
|
1070
1266
|
urlObj.pathname = "/" + pathSegments.slice(1).join("/");
|
|
1071
1267
|
}
|
|
1072
1268
|
return urlObj;
|
|
@@ -1179,7 +1375,8 @@ function fillPattern(pattern, values, origin) {
|
|
|
1179
1375
|
* Aggregates named groups from various parts of the URLPattern match result.
|
|
1180
1376
|
*
|
|
1181
1377
|
*
|
|
1182
|
-
* @
|
|
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.
|
|
1183
1380
|
*/
|
|
1184
1381
|
export function aggregateGroups(match) {
|
|
1185
1382
|
return {
|
|
@@ -1197,19 +1394,19 @@ export function aggregateGroups(match) {
|
|
|
1197
1394
|
/**
|
|
1198
1395
|
* @typedef {object} ShouldRedirectServerInput
|
|
1199
1396
|
* @property {Request} request
|
|
1200
|
-
* @property {string | URL} [
|
|
1201
|
-
* @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]
|
|
1202
1399
|
*
|
|
1203
1400
|
* @typedef {object} ShouldRedirectClientInput
|
|
1204
1401
|
* @property {undefined} [request]
|
|
1205
1402
|
* @property {string | URL} [url]
|
|
1206
|
-
* @property {
|
|
1403
|
+
* @property {Locale} [locale]
|
|
1207
1404
|
*
|
|
1208
1405
|
* @typedef {ShouldRedirectServerInput | ShouldRedirectClientInput} ShouldRedirectInput
|
|
1209
1406
|
*
|
|
1210
1407
|
* @typedef {object} ShouldRedirectResult
|
|
1211
1408
|
* @property {boolean} shouldRedirect - Indicates whether the consumer should perform a redirect.
|
|
1212
|
-
* @property {
|
|
1409
|
+
* @property {Locale} locale - Locale resolved using the configured strategies.
|
|
1213
1410
|
* @property {URL | undefined} redirectUrl - Destination URL when a redirect is required.
|
|
1214
1411
|
*/
|
|
1215
1412
|
/**
|
|
@@ -1245,15 +1442,33 @@ export function aggregateGroups(match) {
|
|
|
1245
1442
|
* return render(request, decision.locale);
|
|
1246
1443
|
* }
|
|
1247
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
|
+
*
|
|
1248
1462
|
* @param {ShouldRedirectInput} [input]
|
|
1249
1463
|
* @returns {Promise<ShouldRedirectResult>}
|
|
1250
1464
|
*/
|
|
1251
1465
|
export async function shouldRedirect(input = {}) {
|
|
1252
|
-
const
|
|
1253
|
-
|
|
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")) {
|
|
1254
1470
|
return { shouldRedirect: false, locale, redirectUrl: undefined };
|
|
1255
1471
|
}
|
|
1256
|
-
const currentUrl = resolveUrl(input);
|
|
1257
1472
|
const localizedUrl = localizeUrl(currentUrl.href, { locale });
|
|
1258
1473
|
const shouldRedirectToLocalizedUrl = normalizeUrl(localizedUrl.href) !== normalizeUrl(currentUrl.href);
|
|
1259
1474
|
return {
|
|
@@ -1266,14 +1481,21 @@ export async function shouldRedirect(input = {}) {
|
|
|
1266
1481
|
* Resolves the locale either from the provided input or by using the configured strategies.
|
|
1267
1482
|
*
|
|
1268
1483
|
* @param {ShouldRedirectInput} input
|
|
1269
|
-
* @
|
|
1484
|
+
* @param {URL} currentUrl
|
|
1485
|
+
* @returns {Promise<Locale>}
|
|
1270
1486
|
*/
|
|
1271
|
-
async function resolveLocale(input) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1487
|
+
async function resolveLocale(input, currentUrl) {
|
|
1488
|
+
const locale = toLocale(input.locale);
|
|
1489
|
+
if (locale) {
|
|
1490
|
+
return locale;
|
|
1274
1491
|
}
|
|
1275
1492
|
if (input.request) {
|
|
1276
|
-
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);
|
|
1277
1499
|
}
|
|
1278
1500
|
return getLocale();
|
|
1279
1501
|
}
|
|
@@ -1284,13 +1506,19 @@ async function resolveLocale(input) {
|
|
|
1284
1506
|
* @returns {URL}
|
|
1285
1507
|
*/
|
|
1286
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
|
+
}
|
|
1287
1515
|
if (input.request) {
|
|
1288
1516
|
return new URL(input.request.url);
|
|
1289
1517
|
}
|
|
1290
|
-
if (input.url instanceof URL) {
|
|
1518
|
+
if ("url" in input && input.url instanceof URL) {
|
|
1291
1519
|
return new URL(input.url.href);
|
|
1292
1520
|
}
|
|
1293
|
-
if (typeof input.url === "string") {
|
|
1521
|
+
if ("url" in input && typeof input.url === "string") {
|
|
1294
1522
|
return new URL(input.url, getUrlOrigin());
|
|
1295
1523
|
}
|
|
1296
1524
|
if (typeof window !== "undefined" && window?.location?.href) {
|
|
@@ -1346,8 +1574,8 @@ function normalizeUrl(url) {
|
|
|
1346
1574
|
* which provides more precise control over URL handling.
|
|
1347
1575
|
*
|
|
1348
1576
|
* @param {string} href - The href to localize (can be relative or absolute)
|
|
1349
|
-
* @param {
|
|
1350
|
-
* @param {
|
|
1577
|
+
* @param {object} [options] - Options for localization
|
|
1578
|
+
* @param {Locale} [options.locale] - Target locale. If not provided, uses `getLocale()`
|
|
1351
1579
|
* @returns {string} The localized href, relative if input was relative
|
|
1352
1580
|
*/
|
|
1353
1581
|
export function localizeHref(href, options) {
|
|
@@ -1479,6 +1707,7 @@ export function trackMessageCall(safeModuleId, locale) {
|
|
|
1479
1707
|
* The order follows each input URL with all its locale variants before moving to the next URL.
|
|
1480
1708
|
*/
|
|
1481
1709
|
export function generateStaticLocalizedUrls(urls) {
|
|
1710
|
+
/** @type {Set<URL>} */
|
|
1482
1711
|
const localizedUrls = new Set();
|
|
1483
1712
|
// For default URL pattern, we can optimize the generation
|
|
1484
1713
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
@@ -1571,7 +1800,7 @@ export const customClientStrategies = new Map();
|
|
|
1571
1800
|
/**
|
|
1572
1801
|
* Checks if the given strategy is a custom strategy.
|
|
1573
1802
|
*
|
|
1574
|
-
* @param {
|
|
1803
|
+
* @param {unknown} strategy The name of the custom strategy to validate.
|
|
1575
1804
|
* Must be a string that starts with "custom-" followed by alphanumeric characters, hyphens, or underscores.
|
|
1576
1805
|
* @returns {boolean} Returns true if it is a custom strategy, false otherwise.
|
|
1577
1806
|
*/
|
|
@@ -1583,7 +1812,7 @@ export function isCustomStrategy(strategy) {
|
|
|
1583
1812
|
*
|
|
1584
1813
|
* @see https://inlang.com/m/gerre34r/library-inlang-paraglideJs/strategy#write-your-own-strategy
|
|
1585
1814
|
*
|
|
1586
|
-
* @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.
|
|
1587
1816
|
* @param {CustomServerStrategyHandler} handler The handler for the custom strategy, which should implement
|
|
1588
1817
|
* the method getLocale.
|
|
1589
1818
|
* @returns {void}
|
|
@@ -1599,7 +1828,7 @@ export function defineCustomServerStrategy(strategy, handler) {
|
|
|
1599
1828
|
*
|
|
1600
1829
|
* @see https://inlang.com/m/gerre34r/library-inlang-paraglideJs/strategy#write-your-own-strategy
|
|
1601
1830
|
*
|
|
1602
|
-
* @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.
|
|
1603
1832
|
* @param {CustomClientStrategyHandler} handler The handler for the custom strategy, which should implement the
|
|
1604
1833
|
* methods getLocale and setLocale.
|
|
1605
1834
|
* @returns {void}
|
|
@@ -1612,26 +1841,25 @@ export function defineCustomClientStrategy(strategy, handler) {
|
|
|
1612
1841
|
}
|
|
1613
1842
|
|
|
1614
1843
|
// ------ TYPES ------
|
|
1615
|
-
|
|
1844
|
+
export {};
|
|
1616
1845
|
/**
|
|
1617
1846
|
* A locale that is available in the project.
|
|
1618
1847
|
*
|
|
1619
1848
|
* @example
|
|
1620
1849
|
* setLocale(request.locale as Locale)
|
|
1621
1850
|
*
|
|
1622
|
-
* @typedef {
|
|
1851
|
+
* @typedef {typeof locales[number]} Locale
|
|
1623
1852
|
*/
|
|
1624
|
-
|
|
1625
1853
|
/**
|
|
1626
1854
|
* A branded type representing a localized string.
|
|
1627
1855
|
*
|
|
1628
|
-
* Message functions return this type instead of
|
|
1856
|
+
* Message functions return this type instead of \`string\`, enabling TypeScript
|
|
1629
1857
|
* to distinguish translated strings from regular strings at compile time.
|
|
1630
1858
|
* This allows you to enforce that only properly localized content is used
|
|
1631
1859
|
* in your UI components.
|
|
1632
1860
|
*
|
|
1633
|
-
* Since
|
|
1634
|
-
* 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.
|
|
1635
1863
|
*
|
|
1636
1864
|
* @example
|
|
1637
1865
|
* // Enforce localized strings in your components
|
|
@@ -1663,4 +1891,100 @@ export function defineCustomClientStrategy(strategy, handler) {
|
|
|
1663
1891
|
*
|
|
1664
1892
|
* @typedef {string & { readonly __brand: 'LocalizedString' }} LocalizedString
|
|
1665
1893
|
*/
|
|
1666
|
-
|
|
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
|
+
*/
|