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.
Files changed (497) hide show
  1. package/dist/COMPONENT_API.md +2 -0
  2. package/dist/components/accordion/Accordion.d.ts +24 -0
  3. package/dist/components/accordion/Accordion.js +4 -0
  4. package/dist/components/accordion/components/Accordion.svelte +2 -8
  5. package/dist/components/accordion/components/AccordionContent.svelte +5 -12
  6. package/dist/components/accordion/components/AccordionItem.svelte +3 -9
  7. package/dist/components/accordion/components/AccordionTrigger.svelte +5 -15
  8. package/dist/components/ai/ChatBubble.svelte +35 -0
  9. package/dist/components/ai/ChatBubble.svelte.d.ts +12 -0
  10. package/dist/components/ai/PromptInput.svelte +58 -0
  11. package/dist/components/ai/PromptInput.svelte.d.ts +13 -0
  12. package/dist/components/ai/StreamText.svelte +41 -0
  13. package/dist/components/ai/StreamText.svelte.d.ts +11 -0
  14. package/dist/components/ai/SuggestionChips.svelte +34 -0
  15. package/dist/components/ai/SuggestionChips.svelte.d.ts +10 -0
  16. package/dist/components/ai/ThinkingLoader.svelte +34 -0
  17. package/dist/components/ai/ThinkingLoader.svelte.d.ts +11 -0
  18. package/dist/components/ai/index.d.ts +5 -0
  19. package/dist/components/ai/index.js +5 -0
  20. package/dist/components/alert/Alert.svelte +47 -0
  21. package/dist/components/alert/Alert.svelte.d.ts +15 -0
  22. package/dist/components/alert/index.d.ts +1 -0
  23. package/dist/components/alert/index.js +1 -0
  24. package/dist/components/avatar/Avatar.svelte +9 -25
  25. package/dist/components/badge/Badge.d.ts +52 -0
  26. package/dist/components/badge/Badge.js +22 -0
  27. package/dist/components/badge/Badge.svelte +22 -0
  28. package/dist/components/badge/Badge.svelte.d.ts +4 -0
  29. package/dist/components/badge/index.d.ts +2 -0
  30. package/dist/components/badge/index.js +1 -0
  31. package/dist/components/brand-logo/BrandLogo.svelte +12 -10
  32. package/dist/components/button/Button.d.ts +2 -2
  33. package/dist/components/button/Button.js +12 -12
  34. package/dist/components/button/Button.svelte +7 -34
  35. package/dist/components/card/Card.d.ts +68 -0
  36. package/dist/components/card/Card.js +28 -0
  37. package/dist/components/card/Card.svelte +33 -0
  38. package/dist/components/card/Card.svelte.d.ts +4 -0
  39. package/dist/components/card/index.d.ts +2 -0
  40. package/dist/components/card/index.js +1 -0
  41. package/dist/components/checkbox/Checkbox.d.ts +25 -4
  42. package/dist/components/checkbox/Checkbox.js +4 -0
  43. package/dist/components/checkbox/Checkbox.svelte +13 -16
  44. package/dist/components/checkbox/Checkbox.svelte.d.ts +2 -2
  45. package/dist/components/combobox/Combobox.d.ts +45 -9
  46. package/dist/components/combobox/Combobox.js +5 -7
  47. package/dist/components/combobox/Combobox.svelte +226 -8
  48. package/dist/components/combobox/Combobox.svelte.d.ts +2 -2
  49. package/dist/components/combobox/index.d.ts +1 -1
  50. package/dist/components/command/components/command-empty.svelte +3 -8
  51. package/dist/components/command/components/command-group.svelte +3 -13
  52. package/dist/components/command/components/command-input.svelte +5 -13
  53. package/dist/components/command/components/command-item.svelte +3 -9
  54. package/dist/components/command/components/command-link-item.svelte +3 -8
  55. package/dist/components/command/components/command-list.svelte +3 -8
  56. package/dist/components/command/components/command-separator.svelte +3 -8
  57. package/dist/components/command/components/command-shortcut.svelte +2 -10
  58. package/dist/components/command/components/command.svelte +29 -42
  59. package/dist/components/date-range-picker/DateRangePicker.svelte +490 -0
  60. package/dist/components/date-range-picker/DateRangePicker.svelte.d.ts +4 -0
  61. package/dist/components/date-range-picker/DateRangePicker.types.d.ts +38 -0
  62. package/dist/components/date-range-picker/DateRangePicker.types.js +1 -0
  63. package/dist/components/date-range-picker/index.d.ts +2 -0
  64. package/dist/components/date-range-picker/index.js +1 -0
  65. package/dist/components/dialog/Dialog.d.ts +43 -121
  66. package/dist/components/dialog/Dialog.js +1 -39
  67. package/dist/components/dialog/Dialog.svelte +103 -113
  68. package/dist/components/dialog/Dialog.svelte.d.ts +1 -2
  69. package/dist/components/dialog/dialog.scss +21 -24
  70. package/dist/components/drawer/Drawer.svelte +63 -0
  71. package/dist/components/drawer/Drawer.svelte.d.ts +16 -0
  72. package/dist/components/drawer/index.d.ts +1 -0
  73. package/dist/components/drawer/index.js +1 -0
  74. package/dist/components/dropdown-menu/DropdownMenu.d.ts +51 -24
  75. package/dist/components/dropdown-menu/DropdownMenu.js +1 -15
  76. package/dist/components/dropdown-menu/components/DropdownMenu.svelte +36 -34
  77. package/dist/components/dropdown-menu/components/DropdownMenu.svelte.d.ts +1 -1
  78. package/dist/components/dropdown-menu/components/DropdownMenuGroup.svelte +8 -12
  79. package/dist/components/dropdown-menu/components/DropdownMenuGroup.svelte.d.ts +2 -4
  80. package/dist/components/dropdown-menu/components/DropdownMenuHeader.svelte +11 -12
  81. package/dist/components/dropdown-menu/components/DropdownMenuHeader.svelte.d.ts +2 -4
  82. package/dist/components/dropdown-menu/components/DropdownMenuItem.svelte +27 -30
  83. package/dist/components/dropdown-menu/components/DropdownMenuItem.svelte.d.ts +1 -1
  84. package/dist/components/dropdown-menu/components/DropdownMenuSeparator.svelte +9 -11
  85. package/dist/components/dropdown-menu/components/DropdownMenuSeparator.svelte.d.ts +2 -4
  86. package/dist/components/fonts/TeraFontMono.svelte +4 -4
  87. package/dist/components/fonts/TeraFontMono.svelte.d.ts +1 -0
  88. package/dist/components/fonts/TeraFontSansSerif.svelte +4 -4
  89. package/dist/components/fonts/TeraFontSansSerif.svelte.d.ts +1 -1
  90. package/dist/components/header/Header.svelte +6 -9
  91. package/dist/components/header/header.scss +1 -1
  92. package/dist/components/icons/IconArrowBigRightFilled.svelte +3 -7
  93. package/dist/components/icons/IconBook.svelte +3 -6
  94. package/dist/components/icons/IconBookmarkPlus.svelte +3 -6
  95. package/dist/components/icons/IconCalculator.svelte +3 -6
  96. package/dist/components/icons/IconCheck.svelte +3 -6
  97. package/dist/components/icons/IconChevronDown.svelte +3 -6
  98. package/dist/components/icons/IconCoin.svelte +3 -6
  99. package/dist/components/icons/IconCoinConvert.svelte +2 -5
  100. package/dist/components/icons/IconCopy.svelte +3 -6
  101. package/dist/components/icons/IconCopyCheckFilled.svelte +3 -6
  102. package/dist/components/icons/IconHamburger.svelte +3 -6
  103. package/dist/components/icons/IconLanguage.svelte +3 -6
  104. package/dist/components/icons/IconLoader2.svelte +3 -6
  105. package/dist/components/icons/IconLogout.svelte +3 -6
  106. package/dist/components/icons/IconMoon.svelte +3 -6
  107. package/dist/components/icons/IconPointFilled.svelte +3 -6
  108. package/dist/components/icons/IconSearch.svelte +3 -6
  109. package/dist/components/icons/IconSettings.svelte +3 -6
  110. package/dist/components/icons/IconSun.svelte +3 -6
  111. package/dist/components/icons/IconSwitchHorizontal.svelte +3 -6
  112. package/dist/components/icons/IconSwitchVertical.svelte +3 -6
  113. package/dist/components/icons/IconTransform.svelte +3 -6
  114. package/dist/components/icons/IconX.svelte +3 -6
  115. package/dist/components/input/Input.d.ts +2 -2
  116. package/dist/components/input/Input.js +10 -10
  117. package/dist/components/input/Input.svelte +10 -26
  118. package/dist/components/label/Label.d.ts +2 -2
  119. package/dist/components/label/Label.js +2 -2
  120. package/dist/components/label/Label.svelte +4 -12
  121. package/dist/components/language-picker-button/LanguagePickerButton.svelte +23 -42
  122. package/dist/components/light-dark-toggle/LightDarkToggle.svelte +21 -26
  123. package/dist/components/marketing/FeatureCard.svelte +37 -0
  124. package/dist/components/marketing/FeatureCard.svelte.d.ts +13 -0
  125. package/dist/components/marketing/PricingCard.svelte +48 -0
  126. package/dist/components/marketing/PricingCard.svelte.d.ts +15 -0
  127. package/dist/components/marketing/StatBlock.svelte +14 -0
  128. package/dist/components/marketing/StatBlock.svelte.d.ts +10 -0
  129. package/dist/components/marketing/TestimonialCard.svelte +24 -0
  130. package/dist/components/marketing/TestimonialCard.svelte.d.ts +12 -0
  131. package/dist/components/marketing/index.d.ts +4 -0
  132. package/dist/components/marketing/index.js +4 -0
  133. package/dist/components/popover/Popover.d.ts +32 -13
  134. package/dist/components/popover/Popover.js +1 -7
  135. package/dist/components/popover/Popover.svelte +40 -158
  136. package/dist/components/popover/Popover.svelte.d.ts +2 -2
  137. package/dist/components/popover-responsive/PopoverResponsive.d.ts +18 -7
  138. package/dist/components/popover-responsive/PopoverResponsive.js +1 -7
  139. package/dist/components/popover-responsive/PopoverResponsive.svelte +25 -87
  140. package/dist/components/popover-responsive/PopoverResponsive.svelte.d.ts +2 -11
  141. package/dist/components/select/Select.d.ts +60 -23
  142. package/dist/components/select/Select.js +14 -35
  143. package/dist/components/select/Select.svelte +157 -28
  144. package/dist/components/select/Select.svelte.d.ts +2 -3
  145. package/dist/components/select/index.d.ts +1 -1
  146. package/dist/components/side-navigation/SideNavigation.svelte +73 -96
  147. package/dist/components/side-navigation/SideNavigationItem.svelte +2 -2
  148. package/dist/components/side-navigation/SideNavigationLayout.svelte +3 -5
  149. package/dist/components/side-navigation/sidenav.scss +17 -13
  150. package/dist/components/skeleton/Skeleton.svelte +48 -0
  151. package/dist/components/skeleton/Skeleton.svelte.d.ts +12 -0
  152. package/dist/components/skeleton/index.d.ts +1 -0
  153. package/dist/components/skeleton/index.js +1 -0
  154. package/dist/components/slider/Slider.d.ts +25 -15
  155. package/dist/components/slider/Slider.js +1 -7
  156. package/dist/components/slider/Slider.svelte +38 -164
  157. package/dist/components/slider/Slider.svelte.d.ts +1 -1
  158. package/dist/components/spinner/Spinner.svelte +39 -0
  159. package/dist/components/spinner/Spinner.svelte.d.ts +10 -0
  160. package/dist/components/spinner/index.d.ts +1 -0
  161. package/dist/components/spinner/index.js +1 -0
  162. package/dist/components/star-rating/StarRating.svelte +33 -49
  163. package/dist/components/switch/Switch.d.ts +19 -4
  164. package/dist/components/switch/Switch.js +4 -0
  165. package/dist/components/switch/Switch.svelte +13 -17
  166. package/dist/components/switch/Switch.svelte.d.ts +2 -2
  167. package/dist/components/table/Table.svelte +68 -0
  168. package/dist/components/table/Table.svelte.d.ts +40 -0
  169. package/dist/components/table/index.d.ts +1 -0
  170. package/dist/components/table/index.js +1 -0
  171. package/dist/components/tabs/Tabs.svelte.d.ts +45 -16
  172. package/dist/components/tabs/Tabs.svelte.js +8 -18
  173. package/dist/components/tabs/components/Tabs.svelte +27 -33
  174. package/dist/components/tabs/components/Tabs.svelte.d.ts +1 -1
  175. package/dist/components/tabs/components/TabsContent.svelte +13 -36
  176. package/dist/components/tabs/components/TabsContent.svelte.d.ts +2 -5
  177. package/dist/components/tabs/components/TabsItem.svelte +43 -32
  178. package/dist/components/tabs/components/TabsItem.svelte.d.ts +2 -5
  179. package/dist/components/tabs/components/TabsList.svelte +90 -58
  180. package/dist/components/tabs/components/TabsList.svelte.d.ts +2 -4
  181. package/dist/components/tera-ui-context/TeraUiContext.svelte +13 -26
  182. package/dist/components/text-area/TextArea.d.ts +2 -2
  183. package/dist/components/text-area/TextArea.js +9 -9
  184. package/dist/components/text-area/TextArea.svelte +41 -65
  185. package/dist/components/toast/ToastContainer.svelte +50 -0
  186. package/dist/components/toast/ToastContainer.svelte.d.ts +18 -0
  187. package/dist/components/toast/index.d.ts +3 -0
  188. package/dist/components/toast/index.js +2 -0
  189. package/dist/components/toast/toast.svelte.d.ts +22 -0
  190. package/dist/components/toast/toast.svelte.js +18 -0
  191. package/dist/components/tooltip/Tooltip.d.ts +23 -0
  192. package/dist/components/tooltip/Tooltip.js +1 -0
  193. package/dist/components/tooltip/Tooltip.svelte +30 -0
  194. package/dist/components/tooltip/Tooltip.svelte.d.ts +4 -0
  195. package/dist/components/tooltip/index.d.ts +2 -0
  196. package/dist/components/tooltip/index.js +1 -0
  197. package/dist/components/user-avatar-with-menu/UserAvatarWithMenu.svelte +48 -69
  198. package/dist/index.d.ts +19 -2
  199. package/dist/index.js +12 -0
  200. package/dist/llms/accordion.md +90 -0
  201. package/dist/llms/ai.md +110 -0
  202. package/dist/llms/alert.md +29 -0
  203. package/dist/llms/avatar.md +34 -0
  204. package/dist/llms/badge.md +31 -0
  205. package/dist/llms/brand-logo.md +30 -0
  206. package/dist/llms/button.md +37 -0
  207. package/dist/llms/card.md +32 -0
  208. package/dist/llms/checkbox.md +35 -0
  209. package/dist/llms/colors.md +161 -0
  210. package/dist/llms/combobox.md +40 -0
  211. package/dist/llms/command.md +7 -0
  212. package/dist/llms/date-range-picker.md +36 -0
  213. package/dist/llms/dialog.md +45 -0
  214. package/dist/llms/drawer.md +30 -0
  215. package/dist/llms/dropdown-menu.md +112 -0
  216. package/dist/llms/fonts.md +7 -0
  217. package/dist/llms/header.md +26 -0
  218. package/dist/llms/icons.md +43 -0
  219. package/dist/llms/index.md +65 -0
  220. package/dist/llms/input.md +37 -0
  221. package/dist/llms/label.md +30 -0
  222. package/dist/llms/language-picker-button.md +30 -0
  223. package/dist/llms/light-dark-toggle.md +26 -0
  224. package/dist/llms/marketing.md +95 -0
  225. package/dist/llms/popover-responsive.md +32 -0
  226. package/dist/llms/popover.md +40 -0
  227. package/dist/llms/select.md +44 -0
  228. package/dist/llms/side-navigation.md +30 -0
  229. package/dist/llms/skeleton.md +28 -0
  230. package/dist/llms/slider.md +36 -0
  231. package/dist/llms/spinner.md +25 -0
  232. package/dist/llms/star-rating.md +31 -0
  233. package/dist/llms/switch.md +33 -0
  234. package/dist/llms/table.md +30 -0
  235. package/dist/llms/tabs.md +92 -0
  236. package/dist/llms/tera-ui-context.md +30 -0
  237. package/dist/llms/text-area.md +39 -0
  238. package/dist/llms/toast.md +7 -0
  239. package/dist/llms/tooltip.md +32 -0
  240. package/dist/llms/user-avatar-with-menu.md +28 -0
  241. package/dist/paraglide/README.md +71 -2
  242. package/dist/paraglide/messages/_index.d.ts +7 -21
  243. package/dist/paraglide/messages/_index.js +7 -485
  244. package/dist/paraglide/messages/text_account_settings.d.ts +16 -0
  245. package/dist/paraglide/messages/text_account_settings.js +234 -0
  246. package/dist/paraglide/messages/text_calces_documentation.d.ts +16 -0
  247. package/dist/paraglide/messages/text_calces_documentation.js +234 -0
  248. package/dist/paraglide/messages/text_calces_scientific_calculator.d.ts +16 -0
  249. package/dist/paraglide/messages/text_calces_scientific_calculator.js +234 -0
  250. package/dist/paraglide/messages/text_currency_converter.d.ts +16 -0
  251. package/dist/paraglide/messages/text_currency_converter.js +234 -0
  252. package/dist/paraglide/messages/text_logout.d.ts +16 -0
  253. package/dist/paraglide/messages/text_logout.js +234 -0
  254. package/dist/paraglide/messages/text_select_language.d.ts +16 -0
  255. package/dist/paraglide/messages/text_select_language.js +234 -0
  256. package/dist/paraglide/messages/text_unit_converter.d.ts +16 -0
  257. package/dist/paraglide/messages/text_unit_converter.js +234 -0
  258. package/dist/paraglide/registry.d.ts +13 -0
  259. package/dist/paraglide/registry.js +15 -0
  260. package/dist/paraglide/runtime.d.ts +242 -125
  261. package/dist/paraglide/runtime.js +467 -143
  262. package/dist/paraglide/server.d.ts +13 -20
  263. package/dist/paraglide/server.js +92 -40
  264. package/dist/stories/ComponentOverview.stories.svelte +533 -0
  265. package/dist/stories/ComponentOverview.stories.svelte.d.ts +6 -0
  266. package/dist/tera-i18n/dev-tools/translator/gpt-translator-i18n-message.js +130 -9
  267. package/dist/tera-i18n/dev-tools/translator/package-lock.json +14 -224
  268. package/dist/tera-i18n/dev-tools/translator/package.json +1 -1
  269. package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-calculator.md +34 -0
  270. package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-cv-maker.md +149 -0
  271. package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-system.txt +1 -1
  272. package/dist/tera-i18n/projects/common/all-language-data.js +70 -13
  273. package/dist/tera-i18n/projects/cv-maker/messages/ar-AE.json +94 -0
  274. package/dist/tera-i18n/projects/cv-maker/messages/ar-EG.json +94 -0
  275. package/dist/tera-i18n/projects/cv-maker/messages/ar-IQ.json +94 -0
  276. package/dist/tera-i18n/projects/cv-maker/messages/ar-SA.json +94 -0
  277. package/dist/tera-i18n/projects/cv-maker/messages/ar-SD.json +94 -0
  278. package/dist/tera-i18n/projects/cv-maker/messages/ar-YE.json +94 -0
  279. package/dist/tera-i18n/projects/cv-maker/messages/ar.json +58 -15
  280. package/dist/tera-i18n/projects/cv-maker/messages/bg.json +57 -14
  281. package/dist/tera-i18n/projects/cv-maker/messages/bn.json +65 -22
  282. package/dist/tera-i18n/projects/cv-maker/messages/ca.json +54 -11
  283. package/dist/tera-i18n/projects/cv-maker/messages/cs.json +59 -16
  284. package/dist/tera-i18n/projects/cv-maker/messages/da.json +51 -8
  285. package/dist/tera-i18n/projects/cv-maker/messages/de.json +58 -15
  286. package/dist/tera-i18n/projects/cv-maker/messages/el.json +71 -28
  287. package/dist/tera-i18n/projects/cv-maker/messages/en-AE.json +94 -0
  288. package/dist/tera-i18n/projects/cv-maker/messages/en-AU.json +94 -0
  289. package/dist/tera-i18n/projects/cv-maker/messages/en-CA.json +51 -8
  290. package/dist/tera-i18n/projects/cv-maker/messages/en-GB.json +50 -7
  291. package/dist/tera-i18n/projects/cv-maker/messages/en-ID.json +94 -0
  292. package/dist/tera-i18n/projects/cv-maker/messages/en-IN.json +54 -11
  293. package/dist/tera-i18n/projects/cv-maker/messages/en-NZ.json +94 -0
  294. package/dist/tera-i18n/projects/cv-maker/messages/en-PH.json +94 -0
  295. package/dist/tera-i18n/projects/cv-maker/messages/en-PK.json +58 -15
  296. package/dist/tera-i18n/projects/cv-maker/messages/en-SA.json +94 -0
  297. package/dist/tera-i18n/projects/cv-maker/messages/en-US.json +51 -8
  298. package/dist/tera-i18n/projects/cv-maker/messages/en-ZA.json +52 -9
  299. package/dist/tera-i18n/projects/cv-maker/messages/en.json +45 -16
  300. package/dist/tera-i18n/projects/cv-maker/messages/es-419.json +94 -0
  301. package/dist/tera-i18n/projects/cv-maker/messages/es-AR.json +94 -0
  302. package/dist/tera-i18n/projects/cv-maker/messages/es-ES.json +94 -0
  303. package/dist/tera-i18n/projects/cv-maker/messages/es-MX.json +94 -0
  304. package/dist/tera-i18n/projects/cv-maker/messages/es.json +53 -10
  305. package/dist/tera-i18n/projects/cv-maker/messages/fi.json +52 -9
  306. package/dist/tera-i18n/projects/cv-maker/messages/fr-MA.json +94 -0
  307. package/dist/tera-i18n/projects/cv-maker/messages/fr.json +54 -11
  308. package/dist/tera-i18n/projects/cv-maker/messages/he.json +55 -12
  309. package/dist/tera-i18n/projects/cv-maker/messages/hi.json +59 -16
  310. package/dist/tera-i18n/projects/cv-maker/messages/hr.json +94 -0
  311. package/dist/tera-i18n/projects/cv-maker/messages/hu.json +63 -20
  312. package/dist/tera-i18n/projects/cv-maker/messages/id.json +60 -17
  313. package/dist/tera-i18n/projects/cv-maker/messages/it.json +53 -10
  314. package/dist/tera-i18n/projects/cv-maker/messages/ja.json +62 -19
  315. package/dist/tera-i18n/projects/cv-maker/messages/ko.json +61 -18
  316. package/dist/tera-i18n/projects/cv-maker/messages/lt.json +61 -18
  317. package/dist/tera-i18n/projects/cv-maker/messages/lv.json +61 -18
  318. package/dist/tera-i18n/projects/cv-maker/messages/ms-MY.json +60 -17
  319. package/dist/tera-i18n/projects/cv-maker/messages/ms.json +61 -18
  320. package/dist/tera-i18n/projects/cv-maker/messages/nl.json +53 -10
  321. package/dist/tera-i18n/projects/cv-maker/messages/no.json +54 -11
  322. package/dist/tera-i18n/projects/cv-maker/messages/pl.json +59 -16
  323. package/dist/tera-i18n/projects/cv-maker/messages/pt-BR.json +58 -15
  324. package/dist/tera-i18n/projects/cv-maker/messages/pt-PT.json +59 -16
  325. package/dist/tera-i18n/projects/cv-maker/messages/pt.json +66 -23
  326. package/dist/tera-i18n/projects/cv-maker/messages/ro.json +52 -9
  327. package/dist/tera-i18n/projects/cv-maker/messages/ru.json +57 -14
  328. package/dist/tera-i18n/projects/cv-maker/messages/sk.json +62 -19
  329. package/dist/tera-i18n/projects/cv-maker/messages/sl.json +57 -14
  330. package/dist/tera-i18n/projects/cv-maker/messages/sq.json +59 -16
  331. package/dist/tera-i18n/projects/cv-maker/messages/sr.json +91 -48
  332. package/dist/tera-i18n/projects/cv-maker/messages/sv.json +56 -13
  333. package/dist/tera-i18n/projects/cv-maker/messages/sw.json +62 -19
  334. package/dist/tera-i18n/projects/cv-maker/messages/ta.json +72 -29
  335. package/dist/tera-i18n/projects/cv-maker/messages/te.json +75 -32
  336. package/dist/tera-i18n/projects/cv-maker/messages/th.json +62 -19
  337. package/dist/tera-i18n/projects/cv-maker/messages/tl.json +77 -34
  338. package/dist/tera-i18n/projects/cv-maker/messages/tr.json +63 -20
  339. package/dist/tera-i18n/projects/cv-maker/messages/uk.json +63 -20
  340. package/dist/tera-i18n/projects/cv-maker/messages/vi.json +64 -21
  341. package/dist/tera-i18n/projects/cv-maker/messages/zh-CN.json +63 -20
  342. package/dist/tera-i18n/projects/cv-maker/messages/zh-TW.json +58 -15
  343. package/dist/tera-i18n/projects/cv-maker/messages/zh.json +94 -0
  344. package/dist/tera-i18n/projects/cv-maker/project.inlang/settings.json +82 -68
  345. package/dist/tera-i18n/projects/cv-maker/supported-language.js +36 -9
  346. package/dist/tera-i18n/projects/mathda/messages/en.json +4 -0
  347. package/dist/tera-i18n/projects/mathda/messages/vi.json +4 -0
  348. package/dist/tera-i18n/projects/mathda/project.inlang/settings.json +15 -0
  349. package/dist/tera-i18n/projects/mathda/supported-language.d.ts +1 -0
  350. package/dist/tera-i18n/projects/mathda/supported-language.js +4 -0
  351. package/dist/tera-i18n/projects/tera-calculator/messages/bg.json +149 -72
  352. package/dist/tera-i18n/projects/tera-calculator/messages/bn.json +149 -72
  353. package/dist/tera-i18n/projects/tera-calculator/messages/ca.json +139 -62
  354. package/dist/tera-i18n/projects/tera-calculator/messages/cs.json +132 -55
  355. package/dist/tera-i18n/projects/tera-calculator/messages/da.json +132 -55
  356. package/dist/tera-i18n/projects/tera-calculator/messages/de.json +181 -104
  357. package/dist/tera-i18n/projects/tera-calculator/messages/el.json +145 -68
  358. package/dist/tera-i18n/projects/tera-calculator/messages/en-IN.json +183 -0
  359. package/dist/tera-i18n/projects/tera-calculator/messages/en-PH.json +183 -0
  360. package/dist/tera-i18n/projects/tera-calculator/messages/en-US.json +183 -0
  361. package/dist/tera-i18n/projects/tera-calculator/messages/en.json +187 -104
  362. package/dist/tera-i18n/projects/tera-calculator/messages/es.json +181 -104
  363. package/dist/tera-i18n/projects/tera-calculator/messages/fi.json +137 -60
  364. package/dist/tera-i18n/projects/tera-calculator/messages/fr.json +180 -103
  365. package/dist/tera-i18n/projects/tera-calculator/messages/hi.json +136 -59
  366. package/dist/tera-i18n/projects/tera-calculator/messages/hu.json +141 -64
  367. package/dist/tera-i18n/projects/tera-calculator/messages/id.json +132 -55
  368. package/dist/tera-i18n/projects/tera-calculator/messages/it.json +180 -103
  369. package/dist/tera-i18n/projects/tera-calculator/messages/ja.json +136 -59
  370. package/dist/tera-i18n/projects/tera-calculator/messages/ko.json +133 -56
  371. package/dist/tera-i18n/projects/tera-calculator/messages/lt.json +140 -63
  372. package/dist/tera-i18n/projects/tera-calculator/messages/lv.json +141 -64
  373. package/dist/tera-i18n/projects/tera-calculator/messages/ms.json +139 -62
  374. package/dist/tera-i18n/projects/tera-calculator/messages/nl.json +145 -68
  375. package/dist/tera-i18n/projects/tera-calculator/messages/no.json +131 -54
  376. package/dist/tera-i18n/projects/tera-calculator/messages/pl.json +134 -57
  377. package/dist/tera-i18n/projects/tera-calculator/messages/pt.json +180 -103
  378. package/dist/tera-i18n/projects/tera-calculator/messages/ro.json +136 -59
  379. package/dist/tera-i18n/projects/tera-calculator/messages/ru.json +180 -103
  380. package/dist/tera-i18n/projects/tera-calculator/messages/sk.json +135 -58
  381. package/dist/tera-i18n/projects/tera-calculator/messages/sl.json +139 -62
  382. package/dist/tera-i18n/projects/tera-calculator/messages/sq.json +148 -71
  383. package/dist/tera-i18n/projects/tera-calculator/messages/sr.json +141 -64
  384. package/dist/tera-i18n/projects/tera-calculator/messages/sv.json +134 -57
  385. package/dist/tera-i18n/projects/tera-calculator/messages/sw.json +152 -75
  386. package/dist/tera-i18n/projects/tera-calculator/messages/ta.json +159 -82
  387. package/dist/tera-i18n/projects/tera-calculator/messages/te.json +165 -88
  388. package/dist/tera-i18n/projects/tera-calculator/messages/th.json +136 -59
  389. package/dist/tera-i18n/projects/tera-calculator/messages/tl.json +146 -69
  390. package/dist/tera-i18n/projects/tera-calculator/messages/tr.json +135 -58
  391. package/dist/tera-i18n/projects/tera-calculator/messages/uk.json +142 -65
  392. package/dist/tera-i18n/projects/tera-calculator/messages/vi.json +181 -104
  393. package/dist/tera-i18n/projects/tera-calculator/messages/zh-CN.json +129 -52
  394. package/dist/tera-i18n/projects/tera-calculator/messages/zh-TW.json +135 -58
  395. package/dist/tera-i18n/projects/tera-calculator/project.inlang/settings.json +51 -53
  396. package/dist/tera-i18n/projects/tera-calculator/supported-language.js +6 -3
  397. package/dist/themes/tera-ui-base.css +242 -77
  398. package/dist/themes/theme-ai.css +100 -0
  399. package/dist/themes/theme-marketing.css +91 -0
  400. package/dist/themes/theme-professional.css +41 -0
  401. package/package.json +36 -29
  402. package/dist/paraglide/messages/ar.d.ts +0 -9
  403. package/dist/paraglide/messages/ar.js +0 -31
  404. package/dist/paraglide/messages/bg.d.ts +0 -9
  405. package/dist/paraglide/messages/bg.js +0 -31
  406. package/dist/paraglide/messages/bn.d.ts +0 -9
  407. package/dist/paraglide/messages/bn.js +0 -31
  408. package/dist/paraglide/messages/ca.d.ts +0 -9
  409. package/dist/paraglide/messages/ca.js +0 -31
  410. package/dist/paraglide/messages/cs.d.ts +0 -9
  411. package/dist/paraglide/messages/cs.js +0 -31
  412. package/dist/paraglide/messages/da.d.ts +0 -9
  413. package/dist/paraglide/messages/da.js +0 -31
  414. package/dist/paraglide/messages/de.d.ts +0 -9
  415. package/dist/paraglide/messages/de.js +0 -31
  416. package/dist/paraglide/messages/el.d.ts +0 -9
  417. package/dist/paraglide/messages/el.js +0 -31
  418. package/dist/paraglide/messages/en.d.ts +0 -9
  419. package/dist/paraglide/messages/en.js +0 -31
  420. package/dist/paraglide/messages/es.d.ts +0 -9
  421. package/dist/paraglide/messages/es.js +0 -31
  422. package/dist/paraglide/messages/fi.d.ts +0 -9
  423. package/dist/paraglide/messages/fi.js +0 -31
  424. package/dist/paraglide/messages/fr.d.ts +0 -9
  425. package/dist/paraglide/messages/fr.js +0 -31
  426. package/dist/paraglide/messages/he.d.ts +0 -9
  427. package/dist/paraglide/messages/he.js +0 -31
  428. package/dist/paraglide/messages/hi.d.ts +0 -9
  429. package/dist/paraglide/messages/hi.js +0 -31
  430. package/dist/paraglide/messages/hu.d.ts +0 -9
  431. package/dist/paraglide/messages/hu.js +0 -31
  432. package/dist/paraglide/messages/id.d.ts +0 -9
  433. package/dist/paraglide/messages/id.js +0 -31
  434. package/dist/paraglide/messages/it.d.ts +0 -9
  435. package/dist/paraglide/messages/it.js +0 -31
  436. package/dist/paraglide/messages/ja.d.ts +0 -9
  437. package/dist/paraglide/messages/ja.js +0 -31
  438. package/dist/paraglide/messages/ko.d.ts +0 -9
  439. package/dist/paraglide/messages/ko.js +0 -31
  440. package/dist/paraglide/messages/lt.d.ts +0 -9
  441. package/dist/paraglide/messages/lt.js +0 -31
  442. package/dist/paraglide/messages/lv.d.ts +0 -9
  443. package/dist/paraglide/messages/lv.js +0 -31
  444. package/dist/paraglide/messages/ms.d.ts +0 -9
  445. package/dist/paraglide/messages/ms.js +0 -31
  446. package/dist/paraglide/messages/nl.d.ts +0 -9
  447. package/dist/paraglide/messages/nl.js +0 -31
  448. package/dist/paraglide/messages/no.d.ts +0 -9
  449. package/dist/paraglide/messages/no.js +0 -31
  450. package/dist/paraglide/messages/pl.d.ts +0 -9
  451. package/dist/paraglide/messages/pl.js +0 -31
  452. package/dist/paraglide/messages/pt.d.ts +0 -9
  453. package/dist/paraglide/messages/pt.js +0 -31
  454. package/dist/paraglide/messages/ro.d.ts +0 -9
  455. package/dist/paraglide/messages/ro.js +0 -31
  456. package/dist/paraglide/messages/ru.d.ts +0 -9
  457. package/dist/paraglide/messages/ru.js +0 -31
  458. package/dist/paraglide/messages/sk.d.ts +0 -9
  459. package/dist/paraglide/messages/sk.js +0 -31
  460. package/dist/paraglide/messages/sl.d.ts +0 -9
  461. package/dist/paraglide/messages/sl.js +0 -31
  462. package/dist/paraglide/messages/sq.d.ts +0 -9
  463. package/dist/paraglide/messages/sq.js +0 -31
  464. package/dist/paraglide/messages/sr.d.ts +0 -9
  465. package/dist/paraglide/messages/sr.js +0 -31
  466. package/dist/paraglide/messages/sv.d.ts +0 -9
  467. package/dist/paraglide/messages/sv.js +0 -31
  468. package/dist/paraglide/messages/sw.d.ts +0 -9
  469. package/dist/paraglide/messages/sw.js +0 -31
  470. package/dist/paraglide/messages/ta.d.ts +0 -9
  471. package/dist/paraglide/messages/ta.js +0 -31
  472. package/dist/paraglide/messages/te.d.ts +0 -9
  473. package/dist/paraglide/messages/te.js +0 -31
  474. package/dist/paraglide/messages/th.d.ts +0 -9
  475. package/dist/paraglide/messages/th.js +0 -31
  476. package/dist/paraglide/messages/tl.d.ts +0 -9
  477. package/dist/paraglide/messages/tl.js +0 -31
  478. package/dist/paraglide/messages/tr.d.ts +0 -9
  479. package/dist/paraglide/messages/tr.js +0 -31
  480. package/dist/paraglide/messages/uk.d.ts +0 -9
  481. package/dist/paraglide/messages/uk.js +0 -31
  482. package/dist/paraglide/messages/vi.d.ts +0 -9
  483. package/dist/paraglide/messages/vi.js +0 -31
  484. package/dist/paraglide/messages/zh-CN.d.ts +0 -9
  485. package/dist/paraglide/messages/zh-CN.js +0 -31
  486. package/dist/paraglide/messages/zh-TW.d.ts +0 -9
  487. package/dist/paraglide/messages/zh-TW.js +0 -31
  488. package/dist/tera-i18n/dev-tools/translator/prompt/i18n-message-translate-prompt-cv-maker.txt +0 -21
  489. package/dist/tera-i18n/projects/cv-maker/project.inlang/project_id +0 -1
  490. package/dist/tera-i18n/projects/tera-calculator/messages/ar.json +0 -106
  491. package/dist/tera-i18n/projects/tera-calculator/messages/he.json +0 -106
  492. package/dist/tera-i18n/projects/tera-calculator/project.inlang/project_id +0 -1
  493. package/dist/tera-i18n/projects/tera-system-ui/project.inlang/.meta.json +0 -3
  494. package/dist/tera-i18n/projects/tera-system-ui/project.inlang/README.md +0 -103
  495. package/dist/tera-i18n/projects/tera-system-ui/project.inlang/project_id +0 -1
  496. package/dist/themes/tw-preset.cjs +0 -160
  497. 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", "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"]);
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 \`overwriteGetLocale()\` and \`defineSetLocale()\`.
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
- * @type {() => Locale}
370
+ * @returns {Locale} The current locale.
301
371
  */
302
372
  export let getLocale = () => {
303
373
  if (experimentalStaticLocale !== undefined) {
304
- return assertIsLocale(experimentalStaticLocale);
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
- for (const strat of strategy) {
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 window !== "undefined") {
327
- locale = extractLocaleFromUrl(window.location.href);
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
- locale = result;
462
+ if (result !== undefined) {
463
+ return assertIsLocale(result);
464
+ }
354
465
  }
355
466
  }
356
- // check if match, else continue loop
357
- if (locale !== undefined) {
358
- const asserted = assertIsLocale(locale);
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
- throw new Error("No locale found. Read the docs https://inlang.com/m/gerre34r/library-inlang-paraglideJs/errors#no-locale-found");
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
- * @type {(fn: () => Locale) => void}
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<any>>} */
592
+ /** @type {Array<Promise<void>>} */
445
593
  const customSetLocalePromises = [];
446
594
  /** @type {string | undefined} */
447
595
  let newLocation = undefined;
448
- for (const strat of strategy) {
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 \`setLocale()\` function.
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 = /** @type {SetLocaleFn} */ (fn);
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
- * @type {(fn: () => string) => void}
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
- * Check if something is an available locale.
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
- * @param {any} locale
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
- if (typeof locale !== "string")
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 is a locale.
761
+ * Asserts that the input can be normalized to a locale.
595
762
  *
596
- * @param {any} input - The input to check.
597
- * @returns {Locale} The input if it is a locale.
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
- if (typeof input !== "string") {
602
- throw new Error(`Invalid locale: ${input}. Expected a string.`);
603
- }
604
- const lowerInput = input.toLowerCase();
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
- * @type {(request: Request) => Locale}
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 extractLocaleFromRequest = (request) => {
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 strategy) {
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(request.url);
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
- if (locale !== undefined) {
663
- if (!isLocale(locale)) {
664
- locale = undefined;
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
- * @type {(request: Request) => Promise<Locale>}
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
- if (locale !== undefined && isLocale(locale)) {
716
- return assertIsLocale(locale);
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
- locale = extractLocaleFromRequest(request);
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 {string | undefined}
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
- if (isLocale(locale)) {
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 {string|undefined} The negotiated preferred language.
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]?.toLowerCase();
966
+ const baseTag = tag?.split("-")[0];
768
967
  return {
769
- fullTag: tag?.toLowerCase(),
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
- if (isLocale(lang.fullTag)) {
777
- return lang.fullTag;
975
+ const fullLocale = toLocale(lang.fullTag);
976
+ if (fullLocale) {
977
+ return fullLocale;
778
978
  }
779
- else if (isLocale(lang.baseTag)) {
780
- return lang.baseTag;
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
- * @type {() => Locale | undefined}
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.toLowerCase(),
806
- baseTag: lang.split("-")[0]?.toLowerCase(),
1005
+ fullTag: lang,
1006
+ baseTag: lang.split("-")[0],
807
1007
  }));
808
1008
  for (const lang of languages) {
809
- if (isLocale(lang.fullTag)) {
810
- return lang.fullTag;
1009
+ const fullLocale = toLocale(lang.fullTag);
1010
+ if (fullLocale) {
1011
+ return fullLocale;
811
1012
  }
812
- else if (isLocale(lang.baseTag)) {
813
- return lang.baseTag;
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 (!match) {
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
- if (pathSegments.length > 0) {
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 {Object} [options] - Options for localization
927
- * @param {string} [options.locale] - Target locale. If not provided, uses getLocale()
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, options);
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 {Object} [options]
968
- * @param {string} [options.locale]
1165
+ * @param {Locale} locale
969
1166
  * @returns {URL}
970
1167
  */
971
- function localizeUrlDefaultPattern(url, options) {
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 && isLocale(pathSegments[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 && isLocale(pathSegments[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
- * @type {(match: any) => Record<string, string | null | undefined>}
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} [url]
1201
- * @property {ReturnType<typeof assertIsLocale>} [locale]
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 {ReturnType<typeof assertIsLocale>} [locale]
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 {ReturnType<typeof assertIsLocale>} locale - Locale resolved using the configured strategies.
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 locale = /** @type {ReturnType<typeof assertIsLocale>} */ (await resolveLocale(input));
1253
- if (!strategy.includes("url")) {
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
- * @returns {Promise<ReturnType<typeof assertIsLocale>>}
1484
+ * @param {URL} currentUrl
1485
+ * @returns {Promise<Locale>}
1270
1486
  */
1271
- async function resolveLocale(input) {
1272
- if (input.locale) {
1273
- return assertIsLocale(input.locale);
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 {Object} [options] - Options for localization
1350
- * @param {string} [options.locale] - Target locale. If not provided, uses `getLocale()`
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 {any} strategy The name of the custom strategy to validate.
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 {any} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
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 {any} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
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 {(typeof locales)[number]} Locale
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 `string`, enabling TypeScript
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 `LocalizedString` is a branded subtype of `string`, it remains fully
1634
- * backward compatible—you can pass it anywhere a `string` is expected.
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
+ */