@asafarim/shared-i18n 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +266 -350
  2. package/demo/README.md +119 -148
  3. package/demo/index.html +12 -1
  4. package/demo/node_modules/.bin/kill-port +17 -0
  5. package/demo/node_modules/.bin/tsc +5 -9
  6. package/demo/node_modules/.bin/tsserver +5 -9
  7. package/demo/node_modules/.bin/vite +5 -9
  8. package/demo/package.json +7 -4
  9. package/demo/public/404.html +24 -0
  10. package/demo/public/favicon.svg +4 -4
  11. package/demo/public/logo.svg +24 -24
  12. package/demo/src/App.tsx +178 -129
  13. package/demo/src/components/CountryLanguageSelectorsPage.tsx +240 -0
  14. package/demo/src/components/GetStartedSection.tsx +56 -56
  15. package/demo/src/components/KeyTable.tsx +29 -29
  16. package/demo/src/components/LanguageBar.tsx +145 -103
  17. package/demo/src/components/LanguageSwitcherDemo.module.css +114 -114
  18. package/demo/src/components/LanguageSwitchersPage.tsx +245 -0
  19. package/demo/src/components/Logo.tsx +6 -6
  20. package/demo/src/components/OverviewSection.tsx +58 -43
  21. package/demo/src/components/Panel.tsx +15 -15
  22. package/demo/src/components/RoutingLabPage.tsx +147 -0
  23. package/demo/src/components/StatusCard.tsx +109 -109
  24. package/demo/src/data/countries.ts +48 -0
  25. package/demo/src/i18n/localeAdapter.ts +91 -0
  26. package/demo/src/i18n/localeRouting.ts +77 -0
  27. package/demo/src/index.css +1075 -644
  28. package/demo/src/locales/de/demo.json +202 -84
  29. package/demo/src/locales/en/demo.json +201 -85
  30. package/demo/src/locales/fr/demo.json +203 -85
  31. package/demo/src/locales/it/demo.json +202 -84
  32. package/demo/src/locales/lb/demo.json +201 -0
  33. package/demo/src/locales/nl/demo.json +203 -85
  34. package/demo/src/main.tsx +32 -29
  35. package/demo/tsconfig.json +18 -18
  36. package/demo/tsconfig.node.json +10 -10
  37. package/demo/tsconfig.tsbuildinfo +1 -1
  38. package/demo/vite-env.d.ts +7 -7
  39. package/demo/vite.config.d.ts +2 -2
  40. package/demo/vite.config.js +10 -10
  41. package/dist/components/LanguageSwitcher.module.css +303 -303
  42. package/dist/country-language-selector.css +431 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +2 -0
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/package.json +8 -5
  48. package/demo/dist/Icon Dropdown_Limited Languages.png +0 -0
  49. package/demo/dist/Select Dropdown_Text Only.png +0 -0
  50. package/demo/dist/assets/favicon-BZYZvBLo.svg +0 -4
  51. package/demo/dist/assets/index-BdjqKw_N.css +0 -1
  52. package/demo/dist/assets/index-C1Tq1uEr.js +0 -191
  53. package/demo/dist/favicon.svg +0 -4
  54. package/demo/dist/index.html +0 -27
  55. package/demo/dist/logo.svg +0 -24
  56. package/demo/node_modules/.bin/browserslist +0 -21
  57. package/demo/node_modules/.bin/browserslist.CMD +0 -12
  58. package/demo/node_modules/.bin/browserslist.ps1 +0 -41
  59. package/demo/node_modules/.bin/tsc.CMD +0 -12
  60. package/demo/node_modules/.bin/tsc.ps1 +0 -41
  61. package/demo/node_modules/.bin/tsserver.CMD +0 -12
  62. package/demo/node_modules/.bin/tsserver.ps1 +0 -41
  63. package/demo/node_modules/.bin/vite.CMD +0 -12
  64. package/demo/node_modules/.bin/vite.ps1 +0 -41
  65. package/demo/node_modules/.vite/deps/@asafarim_country-language-selector.js +0 -848
  66. package/demo/node_modules/.vite/deps/@asafarim_country-language-selector.js.map +0 -7
  67. package/demo/node_modules/.vite/deps/_metadata.json +0 -76
  68. package/demo/node_modules/.vite/deps/chunk-5WRI5ZAA.js +0 -30
  69. package/demo/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +0 -7
  70. package/demo/node_modules/.vite/deps/chunk-B3AHR5EX.js +0 -1004
  71. package/demo/node_modules/.vite/deps/chunk-B3AHR5EX.js.map +0 -7
  72. package/demo/node_modules/.vite/deps/chunk-E6BG6WAU.js +0 -292
  73. package/demo/node_modules/.vite/deps/chunk-E6BG6WAU.js.map +0 -7
  74. package/demo/node_modules/.vite/deps/chunk-MVARZQEG.js +0 -280
  75. package/demo/node_modules/.vite/deps/chunk-MVARZQEG.js.map +0 -7
  76. package/demo/node_modules/.vite/deps/i18next-browser-languagedetector.js +0 -400
  77. package/demo/node_modules/.vite/deps/i18next-browser-languagedetector.js.map +0 -7
  78. package/demo/node_modules/.vite/deps/i18next.js +0 -2392
  79. package/demo/node_modules/.vite/deps/i18next.js.map +0 -7
  80. package/demo/node_modules/.vite/deps/package.json +0 -3
  81. package/demo/node_modules/.vite/deps/react-dom.js +0 -6
  82. package/demo/node_modules/.vite/deps/react-dom.js.map +0 -7
  83. package/demo/node_modules/.vite/deps/react-dom_client.js +0 -20217
  84. package/demo/node_modules/.vite/deps/react-dom_client.js.map +0 -7
  85. package/demo/node_modules/.vite/deps/react-i18next.js +0 -869
  86. package/demo/node_modules/.vite/deps/react-i18next.js.map +0 -7
  87. package/demo/node_modules/.vite/deps/react.js +0 -5
  88. package/demo/node_modules/.vite/deps/react.js.map +0 -7
  89. package/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +0 -278
  90. package/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +0 -7
  91. package/demo/node_modules/.vite/deps/react_jsx-runtime.js +0 -6
  92. package/demo/node_modules/.vite/deps/react_jsx-runtime.js.map +0 -7
  93. package/demo/src/components/CountryLanguageDemo.tsx +0 -140
  94. package/demo/src/components/LanguageSwitcherDemo.tsx +0 -256
package/demo/README.md CHANGED
@@ -1,148 +1,119 @@
1
- # @asafarim/shared-i18n Demo
2
-
3
- A comprehensive interactive demo application showcasing the features of [@asafarim/shared-i18n](../README.md) and its integration with [@asafarim/country-language-selector](https://www.npmjs.com/package/@asafarim/country-language-selector).
4
-
5
- ## Live Demo
6
-
7
- View the demo online at: [https://alisafari-it.github.io/shared-i18n/](https://alisafari-it.github.io/shared-i18n/)
8
-
9
- ## Local Development
10
-
11
- ### Prerequisites
12
-
13
- - Node.js 18+
14
- - pnpm 10+
15
-
16
- ### Setup
17
-
18
- ```bash
19
- # From the root directory
20
- pnpm install
21
-
22
- # Build the shared-i18n package
23
- pnpm run build
24
-
25
- # Navigate to demo and start dev server
26
- cd demo
27
- pnpm run dev
28
- ```
29
-
30
- The demo will be available at `http://localhost:5173/shared-i18n/`
31
-
32
- ### Build
33
-
34
- ```bash
35
- pnpm run build
36
- ```
37
-
38
- Output files are generated in `dist/`
39
-
40
- ## Demo Features
41
-
42
- ### Tab 1: Overview
43
-
44
- Highlights the key features and use cases of shared-i18n:
45
- - Multi-language support with cookie persistence
46
- - Built-in language detection and fallback
47
- - TypeScript support with full type safety
48
- - Seamless integration with react-i18next
49
-
50
- ### Tab 2: Get Started
51
-
52
- Step-by-step guide to integrate shared-i18n into your React application:
53
- 1. Install the package
54
- 2. Initialize i18n in your app
55
- 3. Use the `useLanguage` hook
56
- 4. Translate with `useTranslation`
57
- 5. Leverage cookie persistence
58
- 6. Optional backend synchronization
59
-
60
- Includes code examples and pro tips for each step.
61
-
62
- ### Tab 3: Demo
63
-
64
- Live examples of the `LanguageSwitcher` component:
65
- - **Buttons Variant** — Individual language buttons
66
- - **Select Dropdown** — Native HTML dropdown
67
- - **Icon Dropdown** — Compact flag emoji selector
68
- - **Toggle Button** — For exactly 2 languages
69
- - **Limited Languages** — Filter languages per component
70
- - **Translations Panel** — View actual translations from common and identity-portal namespaces
71
- - **Interpolation & Trans Component** — Dynamic string interpolation examples
72
-
73
- ### Tab 4: Country Selector
74
-
75
- Live examples of the `CountryLanguageSelector` component:
76
- - **Default Selector** — Standard country/language picker with compact mode
77
- - **Full Trigger Variant** — Display full country and language names
78
- - **Custom Trigger** — Implement your own button styling and layout
79
-
80
- ### Header Features
81
-
82
- - **Country/Language Selector** — In the header, select from Belgium, Switzerland, and Canada
83
- - **Language Support** English, Dutch, French, German, Italian (6+ languages total)
84
- - **Dark/Light Theme Toggle** — Accessible theme switching
85
- - **Links** GitHub and NPM package links
86
-
87
- ## Supported Languages
88
-
89
- The demo includes translations for:
90
- - 🇬🇧 English (en)
91
- - 🇳🇱 Dutch (nl)
92
- - 🇫🇷 French (fr)
93
- - 🇩🇪 German (de)
94
- - 🇮🇹 Italian (it)
95
-
96
- Language selection persists to localStorage automatically.
97
-
98
- ## Project Structure
99
-
100
- ```
101
- demo/
102
- ├── src/
103
- │ ├── components/
104
- │ │ ├── LanguageSwitcherDemo.tsx # Shared-i18n examples
105
- │ │ ├── CountryLanguageDemo.tsx # Country selector examples
106
- │ │ ├── LanguageBar.tsx # Header with country selector
107
- │ │ ├── OverviewSection.tsx # Overview tab
108
- │ │ ├── GetStartedSection.tsx # Get started tab
109
- │ │ ├── Panel.tsx # Reusable panel wrapper
110
- │ │ ├── KeyTable.tsx # Translations table
111
- │ │ └── StatusCard.tsx # Language sync status
112
- │ ├── locales/
113
- │ │ ├── en/demo.json
114
- │ │ ├── nl/demo.json
115
- │ │ ├── fr/demo.json
116
- │ │ ├── de/demo.json
117
- │ │ └── it/demo.json
118
- │ ├── App.tsx # Main app with tabs
119
- │ ├── main.tsx # Entry point
120
- │ └── index.css # Global styles
121
- ├── package.json
122
- └── vite.config.ts
123
- ```
124
-
125
- ## Key Technologies
126
-
127
- - **React 19** — UI library
128
- - **TypeScript** — Type safety
129
- - **Vite** — Build tool and dev server
130
- - **i18next** — Translation engine
131
- - **react-i18next** — React bindings for i18next
132
- - **ASafariM Design Tokens** — Design system styling
133
-
134
- ## Related Packages
135
-
136
- - [@asafarim/shared-i18n](../README.md) — Core i18n package
137
- - [@asafarim/country-language-selector](https://www.npmjs.com/package/@asafarim/country-language-selector) — Country/language selector component
138
- - [@asafarim/design-tokens](https://www.npmjs.com/package/@asafarim/design-tokens) — Design system
139
-
140
- ## License
141
-
142
- MIT
143
-
144
- ## Support
145
-
146
- For issues or questions about the shared-i18n package, see the [main README](../README.md).
147
-
148
- For issues specific to the country-language-selector, see its [documentation](https://alisafari-it.github.io/country-language-switch/).
1
+ # @asafarim/shared-i18n Demo
2
+
3
+ Interactive demo for [@asafarim/shared-i18n](../README.md). Showcases **both** `LanguageSwitcher` and `CountryLanguageSelector` imported from a single package, with Benelux + UK locale-aware URL routing.
4
+
5
+ Live: [https://alisafari-it.github.io/shared-i18n/](https://alisafari-it.github.io/shared-i18n/)
6
+
7
+ ## Local Development
8
+
9
+ ```bash
10
+ # From workspace root — build the package first
11
+ pnpm install
12
+ pnpm run build # builds @asafarim/shared-i18n (including CSS copy)
13
+
14
+ # Start the demo dev server
15
+ cd demo
16
+ pnpm run dev # http://localhost:5173/shared-i18n/
17
+ ```
18
+
19
+ ## Demo Pages
20
+
21
+ ### Overview (`/be-en/overview`)
22
+ - Hero with live locale / URL preview
23
+ - Two-column feature comparison between `LanguageSwitcher` and `CountryLanguageSelector`
24
+ - Routing contract explanation
25
+
26
+ ### Get Started (`/be-en/get-started`)
27
+ - Step-by-step guide: install → CSS import → `initI18n` → add both selectors
28
+ - Code snippets for `resolveLocaleFromLanguage` adapter pattern
29
+ - Pro tips
30
+
31
+ ### Language Switchers (`/be-en/language-switchers`)
32
+ All six `LanguageSwitcher` variants with live `resolveLocaleFromLanguage` wiring:
33
+ - Buttons, select, icon-dropdown (all / limited languages)
34
+ - Icon-dropdown with labels
35
+ - Toggle button (2 languages)
36
+ - **Comparison table** and country-awareness explanation
37
+ - Inline notice when language falls back to a different country
38
+
39
+ ### Country Language Selectors (`/be-en/country-language-selectors`)
40
+ All `CountryLanguageSelector` variants controlled by the same locale:
41
+ - Image flags / emoji flags × compact / full / flag-only triggers
42
+ - Custom `renderTrigger` render prop example
43
+ - Popover `align="start"` variant
44
+ - Live status bar (country, language, slug, URL)
45
+
46
+ ### Routing Lab (`/be-en/routing-lab`)
47
+ Side-by-side demo:
48
+ - Left: `LanguageSwitcher` + `resolveLocaleFromLanguage` adapter with fallback notices
49
+ - Right: `CountryLanguageSelector` direct full-locale output
50
+ - Scripted scenario cards that apply predefined transitions
51
+
52
+ ## Countries Covered
53
+
54
+ | Code | Country | Languages |
55
+ |------|---------|-----------|
56
+ | BE | Belgium | en, nl, fr, de |
57
+ | NL | Netherlands | nl, en |
58
+ | LU | Luxembourg | lb, fr, de, en |
59
+ | GB | United Kingdom | en |
60
+
61
+ ## URL Structure
62
+
63
+ ```
64
+ /shared-i18n/<country-lower>-<language-lower>/<page>
65
+
66
+ Examples:
67
+ /shared-i18n/be-en/overview
68
+ /shared-i18n/nl-nl/language-switchers
69
+ /shared-i18n/lu-fr/country-language-selectors
70
+ /shared-i18n/gb-en/routing-lab
71
+ ```
72
+
73
+ Changing locale preserves the active page; changing page preserves the active locale. Invalid slugs fall back to `be-en/overview`.
74
+
75
+ ## Architecture
76
+
77
+ ```
78
+ demo/src/
79
+ ├── App.tsx # URL-driven router, locale ↔ i18n sync
80
+ ├── main.tsx # initI18n + CSS import
81
+ ├── index.css # Premium app-shell design
82
+ ├── data/
83
+ │ └── countries.ts # Benelux + UK country list (Country[])
84
+ ├── i18n/
85
+ │ ├── localeRouting.ts # DemoPage type, slug helpers, parsePathname
86
+ │ └── localeAdapter.ts # resolveLocaleFromLanguage helper
87
+ ├── components/
88
+ │ ├── LanguageBar.tsx # Navbar: two CLS controls, theme toggle
89
+ │ ├── OverviewSection.tsx # Overview feature cards
90
+ │ ├── GetStartedSection.tsx # Accordion steps
91
+ │ ├── LanguageSwitchersPage.tsx # All LanguageSwitcher variants + comparison table
92
+ │ ├── CountryLanguageSelectorsPage.tsx # All CLS variants
93
+ │ ├── RoutingLabPage.tsx # Side-by-side LS vs CLS routing demo
94
+ │ ├── KeyTable.tsx # Translation key inspector
95
+ │ ├── StatusCard.tsx # i18n live status
96
+ │ └── Logo.tsx # Brand logo
97
+ └── locales/
98
+ ├── en/demo.json
99
+ ├── nl/demo.json
100
+ ├── fr/demo.json
101
+ ├── de/demo.json
102
+ └── it/demo.json
103
+ ```
104
+
105
+ ## Key Technologies
106
+
107
+ - **React 19** + **TypeScript**
108
+ - **Vite 6** build tool and dev server
109
+ - **i18next** + **react-i18next** — translation engine
110
+ - **@asafarim/shared-i18n** LanguageSwitcher, CountryLanguageSelector, all hooks
111
+ - **@asafarim/design-tokens** Design system
112
+
113
+ ## GitHub Pages Deployment
114
+
115
+ The demo uses a `public/404.html` + `index.html` script pattern to handle SPA deep links on GitHub Pages. See those files for the implementation.
116
+
117
+ ## License
118
+
119
+ MIT
package/demo/index.html CHANGED
@@ -2,9 +2,20 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
- <link rel="icon" type="image/svg+xml" href="./public/favicon.svg" />
5
+ <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Shared i18n demo</title>
8
+ <script>
9
+ // SPA GitHub Pages fallback decoder. Pairs with public/404.html.
10
+ (function (l) {
11
+ if (l.search[1] === '/') {
12
+ var decoded = l.search.slice(1).split('&').map(function (s) {
13
+ return s.replace(/~and~/g, '&');
14
+ }).join('?');
15
+ window.history.replaceState(null, '', l.pathname.slice(0, -1) + decoded + l.hash);
16
+ }
17
+ }(window.location));
18
+ </script>
8
19
  </head>
9
20
  <body>
10
21
  <div id="root"></div>
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/kill-port@2.0.1/node_modules/kill-port/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/kill-port@2.0.1/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/kill-port@2.0.1/node_modules/kill-port/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/kill-port@2.0.1/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../kill-port/cli.js" "$@"
15
+ else
16
+ exec node "$basedir/../kill-port/cli.js" "$@"
17
+ fi
@@ -2,20 +2,16 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsc" "$@"
14
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
19
15
  else
20
- exec node "$basedir/../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsc" "$@"
16
+ exec node "$basedir/../typescript/bin/tsc" "$@"
21
17
  fi
@@ -2,20 +2,16 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/typescript@5.8.3/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsserver" "$@"
14
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
19
15
  else
20
- exec node "$basedir/../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/tsserver" "$@"
16
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
21
17
  fi
@@ -2,20 +2,16 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/bin/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/bin/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/bin/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules:/mnt/c/repos/my-tools/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/bin/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules:/home/runner/work/shared-i18n/shared-i18n/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
- exec "$basedir/node" "$basedir/../../../node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/bin/vite.js" "$@"
14
+ exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
19
15
  else
20
- exec node "$basedir/../../../node_modules/.pnpm/vite@6.4.1_@types+node@24.10.4/node_modules/vite/bin/vite.js" "$@"
16
+ exec node "$basedir/../vite/bin/vite.js" "$@"
21
17
  fi
package/demo/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "shared-i18n-demo",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
7
7
  "build": "tsc -b && vite build",
8
- "preview": "vite preview"
8
+ "preview": "vite preview",
9
+ "predev": "kill-port 5173",
10
+ "postdev": "echo 'Demo running at http://localhost:5173/shared-i18n/'"
9
11
  },
10
12
  "dependencies": {
11
- "@asafarim/country-language-selector": "^0.2.3",
13
+ "@asafarim/country-language-selector": "^0.4.1",
12
14
  "@asafarim/design-tokens": "^0.5.0",
13
15
  "@asafarim/shared-i18n": "workspace:*",
14
16
  "react": "^19.0.0",
@@ -19,7 +21,8 @@
19
21
  "@types/react-dom": "^19.0.0",
20
22
  "@vitejs/plugin-react": "^4.3.0",
21
23
  "typescript": "~5.8.3",
22
- "vite": "^6.0.0"
24
+ "vite": "^6.0.0",
25
+ "kill-port": "^2.0.1"
23
26
  },
24
27
  "publishConfig": {
25
28
  "access": "public"
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Shared i18n demo</title>
6
+ <script>
7
+ // SPA GitHub Pages fallback (rafgraph/spa-github-pages).
8
+ // Single-page apps for GitHub Pages — MIT license.
9
+ // Rewrites a deep URL into a single query string and redirects to the
10
+ // SPA index, which decodes it back into history.
11
+ var pathSegmentsToKeep = 1; // keep the `/shared-i18n` base path
12
+
13
+ var l = window.location;
14
+ l.replace(
15
+ l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
16
+ l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') + '/?/' +
17
+ l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
18
+ (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
19
+ l.hash
20
+ );
21
+ </script>
22
+ </head>
23
+ <body></body>
24
+ </html>
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
- <rect width="100" height="100" fill="#4F46E5"/>
3
- <text x="50" y="65" font-size="60" font-weight="bold" text-anchor="middle" fill="white">i18n</text>
4
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <rect width="100" height="100" fill="#4F46E5"/>
3
+ <text x="50" y="65" font-size="60" font-weight="bold" text-anchor="middle" fill="white">i18n</text>
4
+ </svg>
@@ -1,24 +1,24 @@
1
- <svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <defs>
3
- <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
- <stop offset="0%" stop-color="#3A5AFE" />
5
- <stop offset="100%" stop-color="#14B8A6" />
6
- </linearGradient>
7
- <linearGradient id="accent" x1="0%" y1="0%" x2="0%" y2="100%">
8
- <stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.9" />
9
- <stop offset="100%" stop-color="#FFFFFF" stop-opacity="0.2" />
10
- </linearGradient>
11
- <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%" color-interpolation-filters="sRGB">
12
- <feDropShadow dx="0" dy="8" stdDeviation="12" flood-color="#0B1220" flood-opacity="0.28" />
13
- </filter>
14
- </defs>
15
- <rect width="180" height="180" rx="32" fill="url(#bg)" filter="url(#shadow)" />
16
- <g transform="translate(45 45)">
17
- <path d="M45 0C20.147 0 0 20.147 0 45C0 69.853 20.147 90 45 90C69.853 90 90 69.853 90 45C90 20.147 69.853 0 45 0ZM45 72C29.088 72 15.75 58.662 15.75 42.75C15.75 26.838 29.088 13.5 45 13.5C60.912 13.5 74.25 26.838 74.25 42.75C74.25 58.662 60.912 72 45 72Z" fill="white" opacity="0.2" />
18
- <path d="M24 27H66C70.971 27 75 31.029 75 36V54C75 58.971 70.971 63 66 63H24C19.029 63 15 58.971 15 54V36C15 31.029 19.029 27 24 27Z" fill="url(#accent)" />
19
- <path d="M36 54V45C36 40.029 40.029 36 45 36C49.971 36 54 40.029 54 45V54" stroke="#0B1220" stroke-width="4" stroke-linecap="round" />
20
- <circle cx="45" cy="21" r="6" fill="white" />
21
- <path d="M33 69H57" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.7" />
22
- <path d="M27 15H63" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.4" />
23
- </g>
24
- </svg>
1
+ <svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#3A5AFE" />
5
+ <stop offset="100%" stop-color="#14B8A6" />
6
+ </linearGradient>
7
+ <linearGradient id="accent" x1="0%" y1="0%" x2="0%" y2="100%">
8
+ <stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.9" />
9
+ <stop offset="100%" stop-color="#FFFFFF" stop-opacity="0.2" />
10
+ </linearGradient>
11
+ <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%" color-interpolation-filters="sRGB">
12
+ <feDropShadow dx="0" dy="8" stdDeviation="12" flood-color="#0B1220" flood-opacity="0.28" />
13
+ </filter>
14
+ </defs>
15
+ <rect width="180" height="180" rx="32" fill="url(#bg)" filter="url(#shadow)" />
16
+ <g transform="translate(45 45)">
17
+ <path d="M45 0C20.147 0 0 20.147 0 45C0 69.853 20.147 90 45 90C69.853 90 90 69.853 90 45C90 20.147 69.853 0 45 0ZM45 72C29.088 72 15.75 58.662 15.75 42.75C15.75 26.838 29.088 13.5 45 13.5C60.912 13.5 74.25 26.838 74.25 42.75C74.25 58.662 60.912 72 45 72Z" fill="white" opacity="0.2" />
18
+ <path d="M24 27H66C70.971 27 75 31.029 75 36V54C75 58.971 70.971 63 66 63H24C19.029 63 15 58.971 15 54V36C15 31.029 19.029 27 24 27Z" fill="url(#accent)" />
19
+ <path d="M36 54V45C36 40.029 40.029 36 45 36C49.971 36 54 40.029 54 45V54" stroke="#0B1220" stroke-width="4" stroke-linecap="round" />
20
+ <circle cx="45" cy="21" r="6" fill="white" />
21
+ <path d="M33 69H57" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.7" />
22
+ <path d="M27 15H63" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.4" />
23
+ </g>
24
+ </svg>