@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
@@ -0,0 +1,201 @@
1
+ {
2
+ "title": "Shared i18n Demo",
3
+ "subtitle": "Eng liicht React i18next Wrapper mat Cookie-Persistenz.",
4
+ "cta": "Sprooch wiesselen",
5
+ "overview": {
6
+ "heading": "Iwwersiicht",
7
+ "description": "@asafarim/shared-i18n schéckt souwuel e LanguageSwitcher (nëmme Sprooch) wéi och e CountryLanguageSelector (Land + Sprooch) aus enger eenzeger Installatioun.",
8
+ "features": {
9
+ "title": "LanguageSwitcher",
10
+ "items": [
11
+ "Ännert i18n Iwwersetzungssprooch (en, nl, fr, de …)",
12
+ "Dräi Varianten: Knäppercher, Select Dropdown, Icon-Dropdown",
13
+ "Cookie-baséiert Persistenz an automatesch Browsererkennung",
14
+ "Benotzt resolveLocaleFromLanguage Adapter fir URL-sächer Routing",
15
+ "Bescht fir Apps wou Land / Markt net wichteg ass"
16
+ ]
17
+ },
18
+ "selectors": {
19
+ "title": "CountryLanguageSelector",
20
+ "items": [
21
+ "Droe souwuel Land WÉI Sprooch: { country: 'BE', language: 'en' }",
22
+ "Kann be-en vun nl-en, lu-en, gb-en ënnerscheeden",
23
+ "Bild Fändelen (flagcdn.com) oder Emoji Fändelen",
24
+ "Kompakt, voll, nëmmen-Fändel, an individuell Trigger-Varianten",
25
+ "Bescht fir lokaléiert URLs wéi /be-en/get-started"
26
+ ]
27
+ },
28
+ "useCases": {
29
+ "title": "Perfekt Fir",
30
+ "items": [
31
+ "Locale-bewosst URL Routing (Benelux, EU, global)",
32
+ "Enterprise Plattformen mat Land + Sprooch Preferenzen",
33
+ "Apps déi be-en vun gb-en ënnerscheede mussen",
34
+ "Identitéits- an Authentifikatiounssystemer mat per-Locale Inhalt",
35
+ "SaaS Applikatiounen déi international Mäert bedéngen"
36
+ ]
37
+ }
38
+ },
39
+ "getStarted": {
40
+ "heading": "Ufangen",
41
+ "intro": "Alles wat Dir braucht — LanguageSwitcher a CountryLanguageSelector — kënnt aus engem Package.",
42
+ "steps": [
43
+ {
44
+ "title": "1. Installéieren",
45
+ "description": "Ee Package gëtt Iech souwuel den nëmme-Sprooch Wiesseler wéi och den Land+Sprooch Selektor.",
46
+ "code": "pnpm add @asafarim/shared-i18n\n# oder: npm i @asafarim/shared-i18n"
47
+ },
48
+ {
49
+ "title": "2. Den Selector Stylesheet importéieren",
50
+ "description": "Setzt de CountryLanguageSelector CSS an Ärem Entry Point.",
51
+ "code": "// main.tsx\nimport '@asafarim/shared-i18n/country-language-selector.css';"
52
+ },
53
+ {
54
+ "title": "3. i18n initialiséieren",
55
+ "description": "Rufft initI18n beim App-Start mat Ären Iwwersetzungsressourcen op.",
56
+ "code": "import { initI18n } from '@asafarim/shared-i18n';\n\ninitI18n({\n defaultLanguage: 'en',\n defaultNS: 'common',\n ns: ['common', 'app'],\n resources: {\n en: { app: enApp },\n lb: { app: lbApp }\n }\n});"
57
+ },
58
+ {
59
+ "title": "4. CountryLanguageSelector dobäisetzen",
60
+ "description": "Importéiert vun @asafarim/shared-i18n — kee separat Package néideg.",
61
+ "code": "import {\n CountryLanguageSelector,\n type Country,\n type Locale,\n} from '@asafarim/shared-i18n';\n\n<CountryLanguageSelector\n countries={countries}\n value={locale}\n onChange={(locale) => {\n i18n.changeLanguage(locale.language);\n navigate(`/${locale.country.toLowerCase()}-${locale.language}/`);\n }}\n triggerVariant=\"compact\"\n flagMode=\"image\"\n/>"
62
+ },
63
+ {
64
+ "title": "5. LanguageSwitcher dobäisetzen",
65
+ "description": "Fir nëmme-Iwwersetzung Apps. Verdraht duerch resolveLocaleFromLanguage wann Dir och Locale URLs hutt.",
66
+ "code": "import { LanguageSwitcher } from '@asafarim/shared-i18n';\n\n<LanguageSwitcher\n variant=\"buttons\"\n onChanged={(lang) => {\n // map Sprooch → voll Locale fir URL-sächer Routing:\n const { locale } = resolveLocaleFromLanguage(currentLocale, lang, countries);\n navigate(locale);\n }}\n/>"
67
+ },
68
+ {
69
+ "title": "6. GitHub Pages SPA Fallback (optional)",
70
+ "description": "Fir statist Hosting op GitHub Pages, setzt eng 404.html Redirect Strategie.",
71
+ "code": "// public/404.html — leitet Deep Links duerch Query String ëm\n// index.html — decodéiert se zeréck duerch history.replaceState\n// Kuckt den Demo Source fir déi vollstänneg Implementatioun."
72
+ }
73
+ ],
74
+ "tips": {
75
+ "title": "Pro Tipps",
76
+ "items": [
77
+ "Benotzt CountryLanguageSelector wann Är App locale-bewosst URLs huet",
78
+ "Benotzt LanguageSwitcher + resolveLocaleFromLanguage als liichtgewiichteg Adapter Schicht",
79
+ "Béid Komponenten sinn kontrolléiert — gitt value={locale} an onChange fir synchron ze bleiwen",
80
+ "i18next späichert nëmme Sprooch; d'URL späichert Land + Sprooch",
81
+ "Setzt VITE_IDENTITY_API_URL fir Sprooch-Preferenz Synchronisatioun"
82
+ ]
83
+ }
84
+ },
85
+ "routingContract": {
86
+ "heading": "Routing Kontrakt",
87
+ "description": "D'URL ass d'Quell vun der Wourecht fir souwuel Locale wéi och aktiv Säit.",
88
+ "items": [
89
+ "{base} leitet ëm op {target}",
90
+ "{pattern} steiert d'UI",
91
+ "CountryLanguageSelector Ännerung → voll Locale Update",
92
+ "LanguageSwitcher Ännerung → Sprooch opgeléist duerch resolveLocaleFromLanguage",
93
+ "Ongülteg Slug → {defaultSlug}; ongülteg Säit → {defaultPage}"
94
+ ]
95
+ },
96
+ "languageSwitchers": {
97
+ "heading": "Sproochwiesseler",
98
+ "intro": "LanguageSwitcher ass nëmme-Sprooch — et weess net a wéi engem Land de Benotzer ass. All Variante hei ënnen ass duerch resolveLocaleFromLanguage verdraht sodatt d'Auswiel vun enger Sprooch nach ëmmer eng gülteg Locale URL produzéiert.",
99
+ "distinction": {
100
+ "title": "Warum LanguageSwitcher CountryLanguageSelector net ersetze kann",
101
+ "p1": "Déi véier Locale Slugs droen déiselwecht Sprooch (Englesch) mee verschidde Länner. LanguageSwitcher kann se net ënnerscheeden:",
102
+ "p2": "CountryLanguageSelector dréit souwuel Land wéi Sprooch, also kann et déi véier all duerstellen an ënnerscheeden.",
103
+ "link": "Kuckt den Country Language Selectors Tab dofir."
104
+ },
105
+ "comparison": {
106
+ "title": "Verglach",
107
+ "capability": "Fäegkeet",
108
+ "ls": "LanguageSwitcher",
109
+ "cls": "CountryLanguageSelector",
110
+ "yes": "Jo",
111
+ "no": "Nee",
112
+ "needsAdapter": "Nee — braucht Adapter",
113
+ "optional": "Optional",
114
+ "yesVia": "Jo, via locale.language",
115
+ "changesLang": "Ännert i18n Sprooch",
116
+ "knowsCountry": "Kennt Land",
117
+ "representsBeEn": "Kann be-en duerstellen",
118
+ "distinguishes": "Kann be-en vun gb-en ënnerscheeden",
119
+ "bestUrls": "Bescht fir lokaléiert URLs",
120
+ "bestTransOnly": "Bescht fir nëmme-Iwwersetzung Apps"
121
+ },
122
+ "variants": [
123
+ { "title": "Knäppercher Variante", "desc": "Individuell Knäppercher fir all Sprooch. Feuert onChanged mat engem Sproochcode." },
124
+ { "title": "Select dropdown — nëmmen Text", "desc": "Native <select> mat Sproochnimm. Keen Emoji." },
125
+ { "title": "Icon dropdown — all Sproochen", "desc": "Kompakt Fändel-Emoji Dropdown deen all ënnerstëtzt Sprooche weist." },
126
+ { "title": "Icon dropdown — ageschränkt Sproochen", "desc": "Agegrenzt op nëmme Englesch an Hollännesch. Nëtzlech fir den Demo Lännerumfang ze passen." },
127
+ { "title": "Icon dropdown — mat Labelen", "desc": "Dasselwecht mee weist Sproochnimm niewent dem Fändel-Emoji." },
128
+ { "title": "Toggle Knäppchen (2 Sproochen)", "desc": "Wann genee 2 Sproochen giwwer an isToggler=true, renderert een eenzelen Toggle Knäppchen." }
129
+ ],
130
+ "note": "Dës Kontroll ännert nëmmen d'Sprooch. D'Demo mapped déi ausgewielt Sprooch zeréck op eng voll Locale duerch resolveLocaleFromLanguage sodatt d'URL gülteg bleift.",
131
+ "preview": "Virschau",
132
+ "code": "Code"
133
+ },
134
+ "routingLab": {
135
+ "heading": "Routing Lab",
136
+ "intro": "Säit-an-Säit Verglach vu wéi LanguageSwitcher a CountryLanguageSelector sech verhalen beim Änneren vun der Locale. D'URL gëtt live aktualiséiert.",
137
+ "currentLocale": "Aktuell Locale",
138
+ "slug": "Slug",
139
+ "urlPath": "URL Pfad",
140
+ "langOnly": {
141
+ "title": "Nëmme-Sprooch Aktioun",
142
+ "desc": "LanguageSwitcher feuert ee Sproochcode of. D'Demo benotzt resolveLocaleFromLanguage fir en op eng gülteg voll Locale ze mappen. Wann d'aktuell Land d'Sprooch net ënnerstëtzt, gëtt eng Fallback Noriicht gewisen.",
143
+ "resolved": "Opgeléist Locale:"
144
+ },
145
+ "countryLang": {
146
+ "title": "Land-Sprooch Aktioun",
147
+ "desc": "CountryLanguageSelector feuert direkt ee vollstännegt { country, language } Objet of — keen Adapter néideg. D'URL huet ëmmer dat richteg Land + Sprooch.",
148
+ "resolved": "Opgeléist Locale:"
149
+ },
150
+ "scenarios": {
151
+ "title": "Skriptéiert Szenarien",
152
+ "desc": "Klickt op eng Rei fir d'Szenario unzewenden a kuckt wéi d'URL an d'Locale Chip aktualiséiert ginn.",
153
+ "expected": "Erwartet:"
154
+ }
155
+ },
156
+ "status": {
157
+ "heading": "Live Status",
158
+ "cookie": "Cookie",
159
+ "backend": "Backend",
160
+ "simulate": "Backend Synchronisatioun simuléieren",
161
+ "resultOk": "Backend Synchronisatioun gelongen",
162
+ "resultFail": "Backend Synchronisatioun feelgeschlagen"
163
+ },
164
+ "nav": {
165
+ "overview": "Iwwersiicht",
166
+ "getStarted": "Ufangen",
167
+ "languageSwitchers": "Sproochwiesseler",
168
+ "countrySelectors": "Land Selektoren",
169
+ "routingLab": "Routing Lab",
170
+ "tagline": "Benelux + UK Locale Routing Demo"
171
+ },
172
+ "footer": {
173
+ "activeRoute": "Aktiv Route",
174
+ "builtWith": "Gebaut mat"
175
+ },
176
+ "hero": {
177
+ "getStarted": "Ufangen",
178
+ "trySelector": "Selector probéieren",
179
+ "liveRoutePreview": "Live Route Virschau"
180
+ },
181
+ "countryLanguageSelectors": {
182
+ "heading": "Land Sprooch Selektoren",
183
+ "intro": "CountryLanguageSelector dréit souwuel Land wéi Sprooch, wat et zur richteger Wiel fir locale-bewosst URLs mécht. All Varianten hei ënnen deelen déiselwecht kontrolléiert Locale — dat Änneren vun engem aktualiséiert d'URL an béid Navbar-Selektoren.",
184
+ "country": "Land",
185
+ "language": "Sprooch",
186
+ "slug": "Slug",
187
+ "url": "URL",
188
+ "preview": "Virschau",
189
+ "code": "Code",
190
+ "variants": [
191
+ { "title": "Bild Fändelen · kompakten Trigger", "desc": "Benotzt SVG Fändelen vu flagcdn.com — funktionéiert op Windows wou Emoji Fändelen als ISO Codes ugewise ginn." },
192
+ { "title": "Deaktivéierte Zoustand", "desc": "Den Selector kann während dem Lueden oder wann de Benotzer keng Erlabnes huet fir d'Locale ze änneren, deaktivéiert ginn." },
193
+ { "title": "Vollstänneg Nimm · Bild Fändelen", "desc": "Weist déi vollstänneg Land- a Sprooch nimm — nëtzlech wann de Plaz net limitéiert ass." },
194
+ { "title": "Nëmme-Fändel Trigger", "desc": "Nëmme d'Fändel gëtt am Trigger gewisen — ideal fir ganz kompakt Navbars." },
195
+ { "title": "Individuellen Trigger via renderTrigger", "desc": "Voll Kontroll iwwer den Trigger Knäppchen via d'renderTrigger render prop. Benotzt eng inline Fändel Bild sou datt et op Windows fonctionnéiert." },
196
+ { "title": "Popover alignéiert op Start", "desc": "Alignéiert d'Dropdown Popover op déi lénk Kante vum Trigger via align='start'." }
197
+ ],
198
+ "open": "Opmaachen",
199
+ "close": "Zoumaachen"
200
+ }
201
+ }
@@ -1,85 +1,203 @@
1
- {
2
- "title": "Shared i18n demo",
3
- "subtitle": "Een lichtgewicht React i18next wrapper met cookie persistentie.",
4
- "cta": "Taal wisselen",
5
- "overview": {
6
- "heading": "Overzicht",
7
- "description": "@asafarim/shared-i18n is een production-grade internationalisatie (i18n) pakket voor React-applicaties.",
8
- "features": {
9
- "title": "Belangrijkste Functies",
10
- "items": [
11
- "Ondersteuning voor meerdere talen met cookie persistentie",
12
- "Ingebouwde taaldetectie en fallback",
13
- "TypeScript-ondersteuning met volledige type veiligheid",
14
- "Vooraf geconfigureerde common en identity-portal naamruimten",
15
- "Naadloze integratie met react-i18next",
16
- "Synchronisatie van taalvoorkeur met backend",
17
- "SSR-veilige hulpprogramma's voor server-side rendering"
18
- ]
19
- },
20
- "useCases": {
21
- "title": "Ideaal Voor",
22
- "items": [
23
- "Globale applicaties die ondersteuning voor meerdere talen vereisen",
24
- "Enterprise-platforms met taalvoorkeuren van gebruikers",
25
- "Identiteits- en verificatiesystemen",
26
- "Content management systemen met lokalisatie",
27
- "SaaS-applicaties die internationale gebruikers bedienen"
28
- ]
29
- }
30
- },
31
- "getStarted": {
32
- "heading": "Aan de Slag",
33
- "intro": "Leer hoe je @asafarim/shared-i18n in minuten in je React-applicatie integreert.",
34
- "steps": [
35
- {
36
- "title": "1. Installeer het Pakket",
37
- "description": "Voeg het pakket toe aan je projectafhankelijkheden.",
38
- "code": "pnpm add @asafarim/shared-i18n"
39
- },
40
- {
41
- "title": "2. Initialiseer i18n in Je App",
42
- "description": "Roep initI18n aan bij het opstarten van de applicatie om taalinstellingen te configureren.",
43
- "code": "import { initI18n } from '@asafarim/shared-i18n';\n\ninitI18n({\n defaultNS: 'common',\n ns: ['common', 'identityPortal'],\n resources: { /* je vertalingen */ }\n});"
44
- },
45
- {
46
- "title": "3. Gebruik de useLanguage Hook",
47
- "description": "Krijg toegang tot taalwisseling en huidige taaltoestand in je componenten.",
48
- "code": "const { changeLanguage, isChanging } = useLanguage();\n\n<button onClick={() => changeLanguage('en')}>\n Naar Engels\n</button>"
49
- },
50
- {
51
- "title": "4. Vertaal met useTranslation",
52
- "description": "Gebruik de useTranslation hook om toegang te krijgen tot vertaalde strings.",
53
- "code": "const { t } = useTranslation('common');\n\n<h1>{t('welcome')}</h1>"
54
- },
55
- {
56
- "title": "5. Maak Gebruik van Cookie Persistentie",
57
- "description": "Taalvoorkeuren van gebruikers worden automatisch opgeslagen en hersteld.",
58
- "code": "// Automatisch opgeslagen via cookies\n// Geen extra setup vereist!"
59
- },
60
- {
61
- "title": "6. Synchroniseer met Backend (Optioneel)",
62
- "description": "Werk taalvoorkeuren van gebruikers bij op je backend.",
63
- "code": "import { updateUserLanguagePreference } from '@asafarim/shared-i18n';\n\nawait updateUserLanguagePreference('nl');"
64
- }
65
- ],
66
- "tips": {
67
- "title": "Pro Tips",
68
- "items": [
69
- "Gebruik naamruimten om vertalingen per functie in te delen",
70
- "Maak gebruik van de Trans-component voor complexe vertalingen met variabelen",
71
- "Stel VITE_IDENTITY_API_URL in voor backend-synchronisatie",
72
- "Controleer browsertaldetectie met getInitialLanguage()",
73
- "Combineer met design tokens voor consistent thema's in alle talen"
74
- ]
75
- }
76
- },
77
- "status": {
78
- "heading": "Live status",
79
- "cookie": "Cookie",
80
- "backend": "Backend",
81
- "simulate": "Backend synchronisatie simuleren",
82
- "resultOk": "Backend synchronisatie geslaagd",
83
- "resultFail": "Backend synchronisatie mislukt"
84
- }
85
- }
1
+ {
2
+ "title": "Shared i18n demo",
3
+ "subtitle": "Een lichtgewicht React i18next wrapper met cookie persistentie.",
4
+ "cta": "Taal wisselen",
5
+ "overview": {
6
+ "heading": "Overzicht",
7
+ "description": "@asafarim/shared-i18n is een production-grade internationalisatie (i18n) pakket voor React-applicaties.",
8
+ "features": {
9
+ "title": "Belangrijkste Functies",
10
+ "items": [
11
+ "Ondersteuning voor meerdere talen met cookie persistentie",
12
+ "Ingebouwde taaldetectie en fallback",
13
+ "TypeScript-ondersteuning met volledige type veiligheid",
14
+ "Vooraf geconfigureerde common en identity-portal naamruimten",
15
+ "Naadloze integratie met react-i18next",
16
+ "Synchronisatie van taalvoorkeur met backend",
17
+ "SSR-veilige hulpprogramma's voor server-side rendering"
18
+ ]
19
+ },
20
+ "selectors": {
21
+ "title": "CountryLanguageSelector",
22
+ "items": [
23
+ "Bevat zowel land ALS taal: { country: 'BE', language: 'en' }",
24
+ "Kan be-en onderscheiden van nl-en, lu-en, gb-en",
25
+ "Afbeeldingvlaggen (flagcdn.com) of emoji-vlaggen",
26
+ "Compacte, volledige, alleen-vlag en aangepaste trigger-varianten",
27
+ "Beste voor gelocaliseerde URLs zoals /be-en/get-started"
28
+ ]
29
+ },
30
+ "useCases": {
31
+ "title": "Ideaal Voor",
32
+ "items": [
33
+ "Globale applicaties die ondersteuning voor meerdere talen vereisen",
34
+ "Enterprise-platforms met taalvoorkeuren van gebruikers",
35
+ "Identiteits- en verificatiesystemen",
36
+ "Content management systemen met lokalisatie",
37
+ "SaaS-applicaties die internationale gebruikers bedienen"
38
+ ]
39
+ }
40
+ },
41
+ "getStarted": {
42
+ "heading": "Aan de Slag",
43
+ "intro": "Leer hoe je @asafarim/shared-i18n in minuten in je React-applicatie integreert.",
44
+ "steps": [
45
+ {
46
+ "title": "1. Installeer het Pakket",
47
+ "description": "Voeg het pakket toe aan je projectafhankelijkheden.",
48
+ "code": "pnpm add @asafarim/shared-i18n"
49
+ },
50
+ {
51
+ "title": "2. Initialiseer i18n in Je App",
52
+ "description": "Roep initI18n aan bij het opstarten van de applicatie om taalinstellingen te configureren.",
53
+ "code": "import { initI18n } from '@asafarim/shared-i18n';\n\ninitI18n({\n defaultNS: 'common',\n ns: ['common', 'identityPortal'],\n resources: { /* je vertalingen */ }\n});"
54
+ },
55
+ {
56
+ "title": "3. Gebruik de useLanguage Hook",
57
+ "description": "Krijg toegang tot taalwisseling en huidige taaltoestand in je componenten.",
58
+ "code": "const { changeLanguage, isChanging } = useLanguage();\n\n<button onClick={() => changeLanguage('en')}>\n Naar Engels\n</button>"
59
+ },
60
+ {
61
+ "title": "4. Vertaal met useTranslation",
62
+ "description": "Gebruik de useTranslation hook om toegang te krijgen tot vertaalde strings.",
63
+ "code": "const { t } = useTranslation('common');\n\n<h1>{t('welcome')}</h1>"
64
+ },
65
+ {
66
+ "title": "5. Maak Gebruik van Cookie Persistentie",
67
+ "description": "Taalvoorkeuren van gebruikers worden automatisch opgeslagen en hersteld.",
68
+ "code": "// Automatisch opgeslagen via cookies\n// Geen extra setup vereist!"
69
+ },
70
+ {
71
+ "title": "6. Synchroniseer met Backend (Optioneel)",
72
+ "description": "Werk taalvoorkeuren van gebruikers bij op je backend.",
73
+ "code": "import { updateUserLanguagePreference } from '@asafarim/shared-i18n';\n\nawait updateUserLanguagePreference('nl');"
74
+ }
75
+ ],
76
+ "tips": {
77
+ "title": "Pro Tips",
78
+ "items": [
79
+ "Gebruik naamruimten om vertalingen per functie in te delen",
80
+ "Maak gebruik van de Trans-component voor complexe vertalingen met variabelen",
81
+ "Stel VITE_IDENTITY_API_URL in voor backend-synchronisatie",
82
+ "Controleer browsertaldetectie met getInitialLanguage()",
83
+ "Combineer met design tokens voor consistent thema's in alle talen"
84
+ ]
85
+ }
86
+ },
87
+ "routingContract": {
88
+ "heading": "Routing contract",
89
+ "description": "De URL is de bron van waarheid voor zowel locale als actieve pagina.",
90
+ "items": [
91
+ "{base} redirect naar {target}",
92
+ "{pattern} stuurt de UI aan",
93
+ "CountryLanguageSelector wijziging → volledige locale update",
94
+ "LanguageSwitcher wijziging → taal opgelost via resolveLocaleFromLanguage",
95
+ "Ongeldige slug → {defaultSlug}; ongeldige pagina → {defaultPage}"
96
+ ]
97
+ },
98
+ "languageSwitchers": {
99
+ "heading": "Taalwisselaars",
100
+ "intro": "LanguageSwitcher is alleen-taal — het weet niet in welk land de gebruiker zich bevindt. Elke variant hieronder is aangesloten via resolveLocaleFromLanguage zodat het selecteren van een taal nog steeds een geldige locale-URL oplevert.",
101
+ "distinction": {
102
+ "title": "Waarom LanguageSwitcher CountryLanguageSelector niet kan vervangen",
103
+ "p1": "Al deze vier locale-slugs dragen dezelfde taal (Engels) maar verschillende landen. LanguageSwitcher kan ze niet onderscheiden:",
104
+ "p2": "CountryLanguageSelector draagt zowel land als taal, dus het kan alle vier vertegenwoordigen en onderscheiden.",
105
+ "link": "Zie het Country Language Selectors tabblad daarvoor."
106
+ },
107
+ "comparison": {
108
+ "title": "Vergelijking",
109
+ "capability": "Mogelijkheid",
110
+ "ls": "LanguageSwitcher",
111
+ "cls": "CountryLanguageSelector",
112
+ "yes": "Ja",
113
+ "no": "Nee",
114
+ "needsAdapter": "Nee — heeft adapter nodig",
115
+ "optional": "Optioneel",
116
+ "yesVia": "Ja, via locale.language",
117
+ "changesLang": "Wijzigt i18n taal",
118
+ "knowsCountry": "Kent land",
119
+ "representsBeEn": "Kan be-en vertegenwoordigen",
120
+ "distinguishes": "Kan be-en van gb-en onderscheiden",
121
+ "bestUrls": "Beste voor gelocaliseerde URLs",
122
+ "bestTransOnly": "Beste voor alleen-vertaling apps"
123
+ },
124
+ "variants": [
125
+ { "title": "Knoppen variant", "desc": "Individuele knoppen voor elke taal. Vuurt onChanged met een taalcode." },
126
+ { "title": "Select dropdown — alleen tekst", "desc": "Native <select> met taalnamen. Geen emoji." },
127
+ { "title": "Icon dropdown — alle talen", "desc": "Compacte vlag-emoji dropdown met alle ondersteunde talen." },
128
+ { "title": "Icon dropdown — beperkte talen", "desc": "Beperkt tot alleen Engels en Nederlands. Handig om de demo-landscope te matchen." },
129
+ { "title": "Icon dropdown — met labels", "desc": "Zelfde als boven maar toont taalnamen naast de vlag-emoji." },
130
+ { "title": "Toggle knop (2 talen)", "desc": "Wanneer exact 2 talen worden meegegeven en isToggler=true, rendert een enkele toggle knop." }
131
+ ],
132
+ "note": "Deze regelaar wijzigt alleen taal. De demo mapped de geselecteerde taal terug naar een volledige locale via resolveLocaleFromLanguage zodat de URL geldig blijft.",
133
+ "preview": "Voorbeeld",
134
+ "code": "Code"
135
+ },
136
+ "routingLab": {
137
+ "heading": "Routing Lab",
138
+ "intro": "Vergelijking naast elkaar van hoe LanguageSwitcher en CountryLanguageSelector zich gedragen bij het wijzigen van locale. De URL wordt live bijgewerkt.",
139
+ "currentLocale": "Huidige locale",
140
+ "slug": "Slug",
141
+ "urlPath": "URL pad",
142
+ "langOnly": {
143
+ "title": "Alleen-taal actie",
144
+ "desc": "LanguageSwitcher vuurt een taalcode af. De demo gebruikt resolveLocaleFromLanguage om deze te mappen naar een geldige volledige locale. Als het huidige land de taal niet ondersteunt, wordt een fallback melding getoond.",
145
+ "resolved": "Opgeloste locale:"
146
+ },
147
+ "countryLang": {
148
+ "title": "Land-taal actie",
149
+ "desc": "CountryLanguageSelector vuurt direct een volledig { country, language } object af — geen adapter nodig. De URL heeft altijd het juiste land + taal.",
150
+ "resolved": "Opgeloste locale:"
151
+ },
152
+ "scenarios": {
153
+ "title": "Gescripte scenario's",
154
+ "desc": "Klik op een rij om het scenario toe te passen en zie hoe de URL en locale chip worden bijgewerkt.",
155
+ "expected": "Verwacht:"
156
+ }
157
+ },
158
+ "status": {
159
+ "heading": "Live status",
160
+ "cookie": "Cookie",
161
+ "backend": "Backend",
162
+ "simulate": "Backend synchronisatie simuleren",
163
+ "resultOk": "Backend synchronisatie geslaagd",
164
+ "resultFail": "Backend synchronisatie mislukt"
165
+ },
166
+ "nav": {
167
+ "overview": "Overzicht",
168
+ "getStarted": "Aan de slag",
169
+ "languageSwitchers": "Taalwisselaars",
170
+ "countrySelectors": "Land Selectors",
171
+ "routingLab": "Routing Lab",
172
+ "tagline": "Benelux + UK locale routing demo"
173
+ },
174
+ "footer": {
175
+ "activeRoute": "Actieve route",
176
+ "builtWith": "Gebouwd met"
177
+ },
178
+ "hero": {
179
+ "getStarted": "Aan de slag",
180
+ "trySelector": "Probeer de selector",
181
+ "liveRoutePreview": "Live route voorbeeld"
182
+ },
183
+ "countryLanguageSelectors": {
184
+ "heading": "Land Taal Selectors",
185
+ "intro": "CountryLanguageSelector draagt zowel land als taal, waardoor het de juiste keuze is voor locale-bewuste URLs. Alle varianten hieronder delen dezelfde gecontroleerde locale — het wijzigen van één update de URL en beide navbar selectors.",
186
+ "country": "Land",
187
+ "language": "Taal",
188
+ "slug": "Slug",
189
+ "url": "URL",
190
+ "preview": "Voorbeeld",
191
+ "code": "Code",
192
+ "variants": [
193
+ { "title": "Afbeelding vlaggen · compacte trigger", "desc": "Gebruikt SVG vlaggen van flagcdn.com — werkt op Windows waar emoji vlaggen als ISO codes worden weergegeven." },
194
+ { "title": "Uitgeschakelde staat", "desc": "De selector kan worden uitgeschakeld tijdens het laden of wanneer de gebruiker geen toestemming heeft om de locale te wijzigen." },
195
+ { "title": "Volledige namen · afbeelding vlaggen", "desc": "Toont de volledige land- en taalnamen — handig wanneer ruimte niet beperkt is." },
196
+ { "title": "Alleen-vlag trigger", "desc": "Alleen de vlag wordt in de trigger getoond — ideaal voor zeer compacte navbars." },
197
+ { "title": "Aangepaste trigger via renderTrigger", "desc": "Volledige controle over de trigger knop via de renderTrigger render prop. Gebruikt een inline vlag afbeelding zodat het op Windows werkt." },
198
+ { "title": "Popover uitgelijnd naar start", "desc": "Lijn de dropdown popover uit met de linkerrand van de trigger via align='start'." }
199
+ ],
200
+ "open": "Openen",
201
+ "close": "Sluiten"
202
+ }
203
+ }
package/demo/src/main.tsx CHANGED
@@ -1,29 +1,32 @@
1
- import React from 'react'
2
- import ReactDOM from 'react-dom/client'
3
- import { initI18n } from '@asafarim/shared-i18n'
4
- import '@asafarim/country-language-selector/styles.css'
5
- import App from './App'
6
- import './index.css'
7
- import enDemo from './locales/en/demo.json'
8
- import nlDemo from './locales/nl/demo.json'
9
- import frDemo from './locales/fr/demo.json'
10
- import itDemo from './locales/it/demo.json'
11
- import deDemo from './locales/de/demo.json'
12
-
13
- initI18n({
14
- defaultNS: 'common',
15
- ns: ['common', 'demo'],
16
- resources: {
17
- en: { demo: enDemo },
18
- nl: { demo: nlDemo },
19
- fr: { demo: frDemo },
20
- it: { demo: itDemo },
21
- de: { demo: deDemo }
22
- }
23
- })
24
-
25
- ReactDOM.createRoot(document.getElementById('root')!).render(
26
- <React.StrictMode>
27
- <App />
28
- </React.StrictMode>,
29
- )
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import { initI18n } from '@asafarim/shared-i18n'
4
+ import '@asafarim/shared-i18n/country-language-selector.css'
5
+ import App from './App'
6
+ import './index.css'
7
+ import enDemo from './locales/en/demo.json'
8
+ import nlDemo from './locales/nl/demo.json'
9
+ import frDemo from './locales/fr/demo.json'
10
+ import itDemo from './locales/it/demo.json'
11
+ import deDemo from './locales/de/demo.json'
12
+ import lbDemo from './locales/lb/demo.json'
13
+
14
+ initI18n({
15
+ defaultLanguage: 'en',
16
+ defaultNS: 'common',
17
+ ns: ['common', 'demo'],
18
+ resources: {
19
+ en: { demo: enDemo },
20
+ nl: { demo: nlDemo },
21
+ fr: { demo: frDemo },
22
+ it: { demo: itDemo },
23
+ de: { demo: deDemo },
24
+ lb: { demo: lbDemo }
25
+ }
26
+ })
27
+
28
+ ReactDOM.createRoot(document.getElementById('root')!).render(
29
+ <React.StrictMode>
30
+ <App />
31
+ </React.StrictMode>,
32
+ )
@@ -1,18 +1,18 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "useDefineForClassFields": true,
5
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
- "module": "ESNext",
7
- "skipLibCheck": true,
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "resolveJsonModule": true,
11
- "moduleResolution": "bundler",
12
- "allowImportingTsExtensions": true,
13
- "noEmit": true,
14
- "jsx": "react-jsx"
15
- },
16
- "include": ["src", "../src/types", "./vite-env.d.ts"],
17
- "references": [{ "path": "./tsconfig.node.json" }, { "path": "../tsconfig.json" }]
18
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "resolveJsonModule": true,
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "noEmit": true,
14
+ "jsx": "react-jsx"
15
+ },
16
+ "include": ["src", "../src/types", "./vite-env.d.ts"],
17
+ "references": [{ "path": "./tsconfig.node.json" }, { "path": "../tsconfig.json" }]
18
+ }
@@ -1,10 +1,10 @@
1
- {
2
- "compilerOptions": {
3
- "composite": true,
4
- "skipLibCheck": true,
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "allowSyntheticDefaultImports": true
8
- },
9
- "include": ["vite.config.ts"]
10
- }
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true
8
+ },
9
+ "include": ["vite.config.ts"]
10
+ }
@@ -1 +1 @@
1
- {"root":["./src/app.tsx","./src/main.tsx","./src/components/countrylanguagedemo.tsx","./src/components/getstartedsection.tsx","./src/components/keytable.tsx","./src/components/languagebar.tsx","./src/components/languageswitcherdemo.tsx","./src/components/logo.tsx","./src/components/overviewsection.tsx","./src/components/panel.tsx","./src/components/statuscard.tsx","../src/types/css.d.ts","./vite-env.d.ts"],"version":"5.8.3"}
1
+ {"root":["./src/app.tsx","./src/main.tsx","./src/components/countrylanguageselectorspage.tsx","./src/components/getstartedsection.tsx","./src/components/keytable.tsx","./src/components/languagebar.tsx","./src/components/languageswitcherspage.tsx","./src/components/logo.tsx","./src/components/overviewsection.tsx","./src/components/panel.tsx","./src/components/routinglabpage.tsx","./src/components/statuscard.tsx","./src/data/countries.ts","./src/i18n/localeadapter.ts","./src/i18n/localerouting.ts","../src/types/css.d.ts","./vite-env.d.ts"],"version":"5.8.3"}