@zoyth/simple-site-framework 1.0.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 (166) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +572 -0
  3. package/bin/create-simple-site.js +390 -0
  4. package/bin/simple-site.js +664 -0
  5. package/dist/client.js +135 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/client.mjs +107 -0
  8. package/dist/client.mjs.map +1 -0
  9. package/dist/components/index.d.mts +3936 -0
  10. package/dist/components/index.d.ts +3936 -0
  11. package/dist/components/index.js +38265 -0
  12. package/dist/components/index.js.map +1 -0
  13. package/dist/components/index.mjs +38173 -0
  14. package/dist/components/index.mjs.map +1 -0
  15. package/dist/config/index.d.mts +298 -0
  16. package/dist/config/index.d.ts +298 -0
  17. package/dist/config/index.js +19 -0
  18. package/dist/config/index.js.map +1 -0
  19. package/dist/config/index.mjs +1 -0
  20. package/dist/config/index.mjs.map +1 -0
  21. package/dist/index.d.mts +2184 -0
  22. package/dist/index.d.ts +2184 -0
  23. package/dist/index.js +1713 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/index.mjs +1605 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/lib/i18n/index.js +665 -0
  28. package/dist/lib/i18n/index.js.map +1 -0
  29. package/dist/lib/i18n/index.mjs +621 -0
  30. package/dist/lib/i18n/index.mjs.map +1 -0
  31. package/docs/DOCUMENTATION-STRUCTURE.md +1156 -0
  32. package/docs/EXPORTS.md +125 -0
  33. package/docs/PERFORMANCE.md +757 -0
  34. package/docs/POLICY-PAGES.md +867 -0
  35. package/docs/ROADMAP.md +334 -0
  36. package/docs/SEO.md +455 -0
  37. package/docs/SITEMAP.md +708 -0
  38. package/docs/STRUCTURED-DATA.md +671 -0
  39. package/docs/accessibility/common-patterns.md +529 -0
  40. package/docs/accessibility/keyboard-navigation.md +263 -0
  41. package/docs/accessibility/overview.md +122 -0
  42. package/docs/accessibility/screen-readers.md +311 -0
  43. package/docs/accessibility/wcag-compliance.md +159 -0
  44. package/docs/api/README.md +164 -0
  45. package/docs/api/components/Accessibility.md +356 -0
  46. package/docs/api/components/Button.md +240 -0
  47. package/docs/api/components/HeroSection.md +306 -0
  48. package/docs/architecture/decisions.md +449 -0
  49. package/docs/components/AnalyticsTracker.md +58 -0
  50. package/docs/components/AnimatedCounter.md +48 -0
  51. package/docs/components/AnimatedSection.md +56 -0
  52. package/docs/components/BlogCard.md +42 -0
  53. package/docs/components/Checkbox.md +56 -0
  54. package/docs/components/CodeBlock.md +52 -0
  55. package/docs/components/ComparisonTable.md +40 -0
  56. package/docs/components/ComponentDemo.md +38 -0
  57. package/docs/components/CountdownTimer.md +51 -0
  58. package/docs/components/ExitIntentModal.md +56 -0
  59. package/docs/components/FAQAccordion.md +66 -0
  60. package/docs/components/FeaturesGrid.md +55 -0
  61. package/docs/components/FileUpload.md +54 -0
  62. package/docs/components/I18nMetaTags.md +55 -0
  63. package/docs/components/Icon.md +53 -0
  64. package/docs/components/LazySection.md +46 -0
  65. package/docs/components/LiveProof.md +53 -0
  66. package/docs/components/LoadingSpinner.md +46 -0
  67. package/docs/components/MultiStepForm.md +48 -0
  68. package/docs/components/PolicyLayout.md +55 -0
  69. package/docs/components/PricingTable.md +49 -0
  70. package/docs/components/Radio.md +59 -0
  71. package/docs/components/SEOMetaTags.md +58 -0
  72. package/docs/components/ScriptInjector.md +50 -0
  73. package/docs/components/Select.md +72 -0
  74. package/docs/components/Skeleton.md +47 -0
  75. package/docs/components/StatsSection.md +48 -0
  76. package/docs/components/StickyBar.md +62 -0
  77. package/docs/components/StructuredData.md +99 -0
  78. package/docs/components/StyleGuide.md +46 -0
  79. package/docs/components/TableOfContents.md +47 -0
  80. package/docs/components/TestimonialCarousel.md +42 -0
  81. package/docs/components/Timeline.md +51 -0
  82. package/docs/components/Toast.md +59 -0
  83. package/docs/components/TrackedLink.md +62 -0
  84. package/docs/components/TrustBadges.md +44 -0
  85. package/docs/components/conversion/MobileCTA.md +363 -0
  86. package/docs/components/forms/ContactForm.md +75 -0
  87. package/docs/components/forms/FormField.md +74 -0
  88. package/docs/components/layout/Footer.md +601 -0
  89. package/docs/components/layout/Header.md +549 -0
  90. package/docs/components/layout/LanguageSelector.md +54 -0
  91. package/docs/components/layout/LanguageSwitcher.md +24 -0
  92. package/docs/components/overview.md +447 -0
  93. package/docs/components/sections/AboutSection.md +48 -0
  94. package/docs/components/sections/CTASection.md +596 -0
  95. package/docs/components/sections/CaseStudySection.md +47 -0
  96. package/docs/components/sections/ContactSection.md +599 -0
  97. package/docs/components/sections/FeatureSection.md +44 -0
  98. package/docs/components/sections/HeroSection.md +404 -0
  99. package/docs/components/sections/LogosSection.md +47 -0
  100. package/docs/components/sections/PersonalTaxesSection.md +23 -0
  101. package/docs/components/sections/RecruitingSection.md +23 -0
  102. package/docs/components/sections/SecurePortalSection.md +23 -0
  103. package/docs/components/sections/ServicePageLayout.md +52 -0
  104. package/docs/components/sections/ServicesSection.md +49 -0
  105. package/docs/components/sections/TestimonialSection.md +44 -0
  106. package/docs/components/sections/WhyChooseUsSection.md +54 -0
  107. package/docs/components/ui/Breadcrumb.md +70 -0
  108. package/docs/components/ui/Button.md +514 -0
  109. package/docs/components/ui/Card.md +501 -0
  110. package/docs/components/ui/Input.md +54 -0
  111. package/docs/components/ui/MobileLinks.md +43 -0
  112. package/docs/components/ui/Modal.md +60 -0
  113. package/docs/components/ui/Tabs.md +62 -0
  114. package/docs/components/ui/Textarea.md +52 -0
  115. package/docs/core-concepts/configuration-driven.md +552 -0
  116. package/docs/core-concepts/overview.md +351 -0
  117. package/docs/features/accessibility/README.md +73 -0
  118. package/docs/features/accessibility/aria-support.md +177 -0
  119. package/docs/features/accessibility/color-contrast.md +155 -0
  120. package/docs/features/accessibility/focus-management.md +187 -0
  121. package/docs/features/accessibility/testing.md +196 -0
  122. package/docs/features/analytics/README.md +51 -0
  123. package/docs/features/analytics/ab-testing.md +171 -0
  124. package/docs/features/analytics/conversion-tracking.md +207 -0
  125. package/docs/features/analytics/custom-events.md +219 -0
  126. package/docs/features/analytics/privacy.md +198 -0
  127. package/docs/features/analytics/setup.md +114 -0
  128. package/docs/features/analytics/tracking-events.md +224 -0
  129. package/docs/features/i18n/README.md +51 -0
  130. package/docs/features/i18n/best-practices.md +273 -0
  131. package/docs/features/i18n/configuration.md +84 -0
  132. package/docs/features/i18n/formatting.md +133 -0
  133. package/docs/features/i18n/locale-detection.md +122 -0
  134. package/docs/features/i18n/routing.md +99 -0
  135. package/docs/features/i18n/rtl-support.md +191 -0
  136. package/docs/features/i18n/translations.md +129 -0
  137. package/docs/features/internationalization.md +595 -0
  138. package/docs/features/performance/README.md +77 -0
  139. package/docs/features/performance/bundle-size.md +134 -0
  140. package/docs/features/performance/caching.md +131 -0
  141. package/docs/features/performance/code-splitting.md +121 -0
  142. package/docs/features/performance/image-optimization.md +110 -0
  143. package/docs/features/performance/lazy-loading.md +92 -0
  144. package/docs/features/performance/monitoring.md +148 -0
  145. package/docs/features/seo/README.md +51 -0
  146. package/docs/features/seo/best-practices.md +184 -0
  147. package/docs/features/seo/canonical-urls.md +182 -0
  148. package/docs/features/seo/meta-tags.md +126 -0
  149. package/docs/features/seo/open-graph.md +166 -0
  150. package/docs/features/seo/robots-txt.md +146 -0
  151. package/docs/features/seo/sitemaps.md +162 -0
  152. package/docs/features/seo/structured-data.md +166 -0
  153. package/docs/getting-started/installation.md +292 -0
  154. package/docs/getting-started/introduction.md +195 -0
  155. package/docs/getting-started/quick-start.md +460 -0
  156. package/docs/guides/analytics-setup.md +616 -0
  157. package/docs/i18n/CONFIGURATION.md +353 -0
  158. package/docs/i18n/EXAMPLES.md +402 -0
  159. package/docs/i18n/MIGRATION.md +260 -0
  160. package/docs/i18n/SEO.md +392 -0
  161. package/docs/i18n/STATIC-GENERATION-FIX.md +71 -0
  162. package/docs/migration/changelog.md +136 -0
  163. package/docs/migration/overview.md +233 -0
  164. package/docs/recipes/adding-animations.md +475 -0
  165. package/docs/recipes/forms-with-validation.md +393 -0
  166. package/package.json +152 -0
@@ -0,0 +1,402 @@
1
+ # i18n Usage Examples
2
+
3
+ Practical examples for common i18n scenarios.
4
+
5
+ ## Table of Contents
6
+ - [Single Language Site](#single-language-site)
7
+ - [Bilingual Site](#bilingual-site-2-languages)
8
+ - [Multi-Language Site](#multi-language-site-3-languages)
9
+ - [RTL Language Support](#rtl-language-support)
10
+ - [Custom Slug Translations](#custom-slug-translations)
11
+ - [Language-Specific Content](#language-specific-content)
12
+
13
+ ## Single Language Site
14
+
15
+ For a site with no i18n overhead:
16
+
17
+ ```typescript
18
+ // src/config/i18n.ts
19
+ export const i18nConfig = {
20
+ locales: ['en'],
21
+ defaultLocale: 'en',
22
+ localePrefix: 'never',
23
+ localeDetection: false,
24
+ };
25
+ ```
26
+
27
+ **URLs:** `/about`, `/contact` (no locale prefix)
28
+
29
+ **Folder structure:**
30
+ ```
31
+ src/app/
32
+ ├── layout.tsx
33
+ ├── page.tsx
34
+ └── about/
35
+ └── page.tsx
36
+ ```
37
+
38
+ **No `[locale]` folder needed** - middleware handles everything.
39
+
40
+ ## Bilingual Site (2 Languages)
41
+
42
+ Classic bilingual setup with text toggle:
43
+
44
+ ```typescript
45
+ // src/config/i18n.ts
46
+ export const i18nConfig = {
47
+ locales: ['en', 'fr'],
48
+ defaultLocale: 'en',
49
+ localePrefix: 'as-needed',
50
+ localeDetection: true,
51
+ localeNames: {
52
+ en: 'English',
53
+ fr: 'Français',
54
+ },
55
+ };
56
+ ```
57
+
58
+ **URLs:**
59
+ - English: `/about` (default, no prefix)
60
+ - French: `/fr/about` (with prefix)
61
+
62
+ **Layout with language selector:**
63
+ ```tsx
64
+ // src/app/[locale]/layout.tsx
65
+ import { setI18nConfig, getTextDirection } from 'simple-site-framework/lib/i18n';
66
+ import { LanguageSelector, I18nMetaTags } from 'simple-site-framework';
67
+ import { i18nConfig } from '../../config/i18n';
68
+
69
+ setI18nConfig(i18nConfig);
70
+
71
+ export default async function Layout({ children, params }) {
72
+ const { locale } = await params;
73
+
74
+ return (
75
+ <html lang={locale} dir={getTextDirection(locale)}>
76
+ <head>
77
+ <I18nMetaTags
78
+ currentLocale={locale}
79
+ pathname="/about"
80
+ baseUrl="https://example.com"
81
+ />
82
+ </head>
83
+ <body>
84
+ <header>
85
+ <nav>
86
+ {/* Auto-detects text toggle for 2 languages */}
87
+ <LanguageSelector currentLocale={locale} />
88
+ </nav>
89
+ </header>
90
+ <main>{children}</main>
91
+ </body>
92
+ </html>
93
+ );
94
+ }
95
+ ```
96
+
97
+ ## Multi-Language Site (3+ Languages)
98
+
99
+ Site with multiple languages and dropdown selector:
100
+
101
+ ```typescript
102
+ // src/config/i18n.ts
103
+ export const i18nConfig = {
104
+ locales: ['en', 'fr', 'es', 'de', 'ja'],
105
+ defaultLocale: 'en',
106
+ localePrefix: 'always',
107
+ localeDetection: true,
108
+ localeNames: {
109
+ en: 'English',
110
+ fr: 'Français',
111
+ es: 'Español',
112
+ de: 'Deutsch',
113
+ ja: '日本語',
114
+ },
115
+ localeLabels: {
116
+ en: 'EN',
117
+ fr: 'FR',
118
+ es: 'ES',
119
+ de: 'DE',
120
+ ja: 'JA',
121
+ },
122
+ };
123
+ ```
124
+
125
+ **URLs:** All have prefix
126
+ - `/en/about`
127
+ - `/fr/about`
128
+ - `/es/about`
129
+ - `/de/about`
130
+ - `/ja/about`
131
+
132
+ **Layout with dropdown:**
133
+ ```tsx
134
+ // LanguageSelector auto-switches to dropdown with 3+ languages
135
+ <LanguageSelector currentLocale={locale} className="ml-4" />
136
+ ```
137
+
138
+ ## RTL Language Support
139
+
140
+ Adding Arabic and Hebrew:
141
+
142
+ ```typescript
143
+ // src/config/i18n.ts
144
+ export const i18nConfig = {
145
+ locales: ['en', 'ar', 'he'],
146
+ defaultLocale: 'en',
147
+ rtlLocales: ['ar', 'he'],
148
+ localeNames: {
149
+ en: 'English',
150
+ ar: 'العربية',
151
+ he: 'עברית',
152
+ },
153
+ };
154
+ ```
155
+
156
+ **Layout with RTL support:**
157
+ ```tsx
158
+ import { getTextDirection } from 'simple-site-framework/lib/i18n';
159
+
160
+ <html lang={locale} dir={getTextDirection(locale)}>
161
+ {/* dir="ltr" for English, dir="rtl" for Arabic/Hebrew */}
162
+ </html>
163
+ ```
164
+
165
+ **RTL-aware CSS:**
166
+ ```css
167
+ /* Use logical properties */
168
+ .container {
169
+ padding-inline-start: 1rem; /* Left in LTR, right in RTL */
170
+ margin-inline-end: 2rem; /* Right in LTR, left in RTL */
171
+ }
172
+
173
+ /* Or use dir selector */
174
+ [dir="rtl"] .icon {
175
+ transform: scaleX(-1); /* Flip icons in RTL */
176
+ }
177
+ ```
178
+
179
+ ## Custom Slug Translations
180
+
181
+ Translate URL slugs between languages:
182
+
183
+ ```typescript
184
+ // src/config/i18n.ts
185
+ export const i18nConfig = {
186
+ locales: ['en', 'fr', 'es'],
187
+ defaultLocale: 'en',
188
+ slugTranslations: {
189
+ en: {
190
+ '/products': '/produits',
191
+ '/services': '/servicios',
192
+ '/about': '/a-propos',
193
+ },
194
+ fr: {
195
+ '/produits': '/products',
196
+ '/servicios': '/services',
197
+ '/a-propos': '/about',
198
+ },
199
+ es: {
200
+ '/products': '/productos',
201
+ '/services': '/servicios',
202
+ '/about': '/acerca-de',
203
+ },
204
+ },
205
+ };
206
+ ```
207
+
208
+ **URLs:**
209
+ - English: `/products`
210
+ - French: `/fr/produits`
211
+ - Spanish: `/es/productos`
212
+
213
+ **Language selector handles translation automatically.**
214
+
215
+ ## Language-Specific Content
216
+
217
+ Using localized strings in components:
218
+
219
+ ```tsx
220
+ // Component with localized content
221
+ import { getLocalizedString } from 'simple-site-framework/lib/content';
222
+
223
+ interface Props {
224
+ locale: string;
225
+ }
226
+
227
+ export function PricingSection({ locale }: Props) {
228
+ const content = {
229
+ heading: {
230
+ en: 'Pricing Plans',
231
+ fr: 'Plans tarifaires',
232
+ es: 'Planes de precios',
233
+ },
234
+ description: {
235
+ en: 'Choose the plan that fits your needs',
236
+ fr: 'Choisissez le plan qui vous convient',
237
+ es: 'Elige el plan que se adapte a tus necesidades',
238
+ },
239
+ };
240
+
241
+ return (
242
+ <section>
243
+ <h2>{getLocalizedString(content.heading, locale)}</h2>
244
+ <p>{getLocalizedString(content.description, locale)}</p>
245
+ </section>
246
+ );
247
+ }
248
+ ```
249
+
250
+ ## Formatters
251
+
252
+ Using locale-aware formatters:
253
+
254
+ ```tsx
255
+ import {
256
+ formatDate,
257
+ formatNumber,
258
+ formatCurrency,
259
+ formatRelativeTime,
260
+ } from 'simple-site-framework/lib/i18n';
261
+
262
+ export function ProductCard({ locale, product }) {
263
+ return (
264
+ <div>
265
+ <h3>{product.name}</h3>
266
+
267
+ {/* Format currency */}
268
+ <p className="price">
269
+ {formatCurrency(product.price, locale, 'USD')}
270
+ {/* en: "$29.99" | fr: "29,99 $US" */}
271
+ </p>
272
+
273
+ {/* Format date */}
274
+ <time>
275
+ {formatDate(product.releaseDate, locale, { dateStyle: 'long' })}
276
+ {/* en: "January 15, 2026" | fr: "15 janvier 2026" */}
277
+ </time>
278
+
279
+ {/* Format relative time */}
280
+ <span>
281
+ {formatRelativeTime(-2, 'day', locale)}
282
+ {/* en: "2 days ago" | fr: "il y a 2 jours" */}
283
+ </span>
284
+
285
+ {/* Format number */}
286
+ <p>
287
+ {formatNumber(product.views, locale)} views
288
+ {/* en: "1,234,567" | fr: "1 234 567" */}
289
+ </p>
290
+ </div>
291
+ );
292
+ }
293
+ ```
294
+
295
+ ## Middleware Configuration
296
+
297
+ ### Basic Middleware
298
+
299
+ ```typescript
300
+ // src/middleware.ts
301
+ import { createI18nMiddleware } from 'simple-site-framework/lib/i18n';
302
+ import { i18nConfig } from './src/config/i18n';
303
+
304
+ export default createI18nMiddleware(i18nConfig);
305
+
306
+ export const config = {
307
+ matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
308
+ };
309
+ ```
310
+
311
+ ### Exclude Additional Routes
312
+
313
+ ```typescript
314
+ export const config = {
315
+ matcher: [
316
+ '/((?!api|_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)',
317
+ ],
318
+ };
319
+ ```
320
+
321
+ ### Custom Middleware Logic
322
+
323
+ ```typescript
324
+ import { createI18nMiddleware } from 'simple-site-framework/lib/i18n';
325
+ import { NextRequest } from 'next/server';
326
+ import { i18nConfig } from './src/config/i18n';
327
+
328
+ const i18nMiddleware = createI18nMiddleware(i18nConfig);
329
+
330
+ export default function middleware(request: NextRequest) {
331
+ // Run i18n middleware first
332
+ const response = i18nMiddleware(request);
333
+
334
+ // Add custom logic
335
+ response.headers.set('X-Custom-Header', 'value');
336
+
337
+ return response;
338
+ }
339
+
340
+ export const config = {
341
+ matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
342
+ };
343
+ ```
344
+
345
+ ## Static Generation
346
+
347
+ Generate static pages for all locales:
348
+
349
+ ```tsx
350
+ // src/app/[locale]/blog/[slug]/page.tsx
351
+ import { i18nConfig } from '../../../config/i18n';
352
+
353
+ export async function generateStaticParams() {
354
+ const posts = await getPosts();
355
+
356
+ return i18nConfig.locales.flatMap((locale) =>
357
+ posts.map((post) => ({
358
+ locale,
359
+ slug: post.slug,
360
+ }))
361
+ );
362
+ }
363
+ ```
364
+
365
+ ## Utilities
366
+
367
+ ### Check Locale Support
368
+
369
+ ```tsx
370
+ import { validateLocale } from 'simple-site-framework/lib/i18n';
371
+
372
+ if (validateLocale(userLocale)) {
373
+ // Use user's locale
374
+ } else {
375
+ // Fall back to default
376
+ }
377
+ ```
378
+
379
+ ### Get Alternate Locales
380
+
381
+ ```tsx
382
+ import { getAlternateLocales } from 'simple-site-framework/lib/i18n';
383
+
384
+ const alternates = getAlternateLocales('en');
385
+ // ['fr', 'es', 'de'] (all except 'en')
386
+ ```
387
+
388
+ ### Match Locale Variants
389
+
390
+ ```tsx
391
+ import { matchLocale } from 'simple-site-framework/lib/i18n';
392
+
393
+ matchLocale('en-US'); // 'en' (if 'en' is supported)
394
+ matchLocale('fr-CA'); // 'fr' (if 'fr' is supported)
395
+ matchLocale('de-DE'); // null (if 'de' not supported)
396
+ ```
397
+
398
+ ## See Also
399
+
400
+ - [Configuration Reference](./CONFIGURATION.md)
401
+ - [Migration Guide](./MIGRATION.md)
402
+ - [SEO Guide](./SEO.md)
@@ -0,0 +1,260 @@
1
+ # i18n Migration Guide
2
+
3
+ This guide helps you migrate from the hardcoded bilingual (fr/en) system to the new flexible i18n configuration.
4
+
5
+ ## Overview
6
+
7
+ **Old System (pre-v0.2.0):**
8
+ - Hardcoded support for French and English only
9
+ - Locale routing always required `[locale]` folder
10
+ - No configuration needed (but inflexible)
11
+
12
+ **New System (v0.2.0+):**
13
+ - Support for any number of languages
14
+ - Flexible locale prefix modes
15
+ - Project-specific configuration
16
+ - Middleware for automatic routing
17
+
18
+ ## Breaking Changes
19
+
20
+ 1. **Configuration Required**: Projects must call `setI18nConfig()` before using i18n features
21
+ 2. **No Hardcoded Locales**: Import from your config, not from framework
22
+ 3. **LanguageSelector**: Replaces `LanguageSwitcher` (which is now deprecated)
23
+
24
+ ## Migration Steps
25
+
26
+ ### Step 1: Create i18n Configuration
27
+
28
+ Create `/src/config/i18n.ts` in your project:
29
+
30
+ ```typescript
31
+ import type { I18nConfig } from 'simple-site-framework/lib/i18n';
32
+
33
+ export const i18nConfig: I18nConfig = {
34
+ // Supported locales
35
+ locales: ['fr', 'en'],
36
+
37
+ // Default locale
38
+ defaultLocale: 'fr',
39
+
40
+ // Locale prefix mode (matches old behavior)
41
+ localePrefix: 'always',
42
+
43
+ // Enable browser language detection
44
+ localeDetection: true,
45
+
46
+ // Display names for language selector
47
+ localeNames: {
48
+ fr: 'Français',
49
+ en: 'English',
50
+ },
51
+
52
+ // Short labels for compact display
53
+ localeLabels: {
54
+ fr: 'FR',
55
+ en: 'EN',
56
+ },
57
+ };
58
+ ```
59
+
60
+ **To match old behavior exactly**, use `localePrefix: 'always'`.
61
+
62
+ ### Step 2: Create Middleware
63
+
64
+ Create `/src/middleware.ts` in your project:
65
+
66
+ ```typescript
67
+ import { createI18nMiddleware } from 'simple-site-framework/lib/i18n';
68
+ import { i18nConfig } from './src/config/i18n';
69
+
70
+ export default createI18nMiddleware(i18nConfig);
71
+
72
+ export const config = {
73
+ // Exclude API routes, static assets, etc.
74
+ matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
75
+ };
76
+ ```
77
+
78
+ ### Step 3: Initialize Config in Layout
79
+
80
+ Update `/src/app/[locale]/layout.tsx`:
81
+
82
+ ```typescript
83
+ import { setI18nConfig } from 'simple-site-framework/lib/i18n';
84
+ import { i18nConfig } from '../../config/i18n';
85
+
86
+ // Initialize config at the top level
87
+ setI18nConfig(i18nConfig);
88
+
89
+ export async function generateStaticParams() {
90
+ return i18nConfig.locales.map((locale) => ({ locale }));
91
+ }
92
+
93
+ export default async function LocaleLayout({
94
+ children,
95
+ params,
96
+ }: {
97
+ children: React.ReactNode;
98
+ params: Promise<{ locale: string }>;
99
+ }) {
100
+ const { locale } = (await params) as { locale: string };
101
+
102
+ return (
103
+ <html lang={locale}>
104
+ <body>{children}</body>
105
+ </html>
106
+ );
107
+ }
108
+ ```
109
+
110
+ ### Step 4: Update Language Switcher (Optional)
111
+
112
+ Replace `LanguageSwitcher` with `LanguageSelector`:
113
+
114
+ **Before:**
115
+ ```typescript
116
+ import { LanguageSwitcher } from 'simple-site-framework/components/layout/LanguageSwitcher';
117
+
118
+ <LanguageSwitcher currentLocale={locale} />
119
+ ```
120
+
121
+ **After:**
122
+ ```typescript
123
+ import { LanguageSelector } from 'simple-site-framework/components/layout/LanguageSelector';
124
+
125
+ <LanguageSelector currentLocale={locale} />
126
+ ```
127
+
128
+ **Note:** `LanguageSwitcher` still works (it's a wrapper), but it's deprecated and will be removed in v1.0.0.
129
+
130
+ ### Step 5: Add SEO Meta Tags (Optional but Recommended)
131
+
132
+ Add `I18nMetaTags` to your layout or pages:
133
+
134
+ ```typescript
135
+ import { I18nMetaTags } from 'simple-site-framework';
136
+
137
+ export default function Layout({ children, params }) {
138
+ return (
139
+ <html>
140
+ <head>
141
+ <I18nMetaTags
142
+ currentLocale={params.locale}
143
+ pathname="/about"
144
+ baseUrl="https://yoursite.com"
145
+ />
146
+ </head>
147
+ <body>{children}</body>
148
+ </html>
149
+ );
150
+ }
151
+ ```
152
+
153
+ ### Step 6: Test Your Changes
154
+
155
+ 1. **Run build**: `npm run build`
156
+ 2. **Test language switching**: Click language selector
157
+ 3. **Test direct URLs**: Navigate to `/fr/about`, `/en/about`
158
+ 4. **Test browser detection**: Clear cookies, visit `/`
159
+ 5. **Check SEO tags**: View page source for hreflang tags
160
+
161
+ ## Common Issues
162
+
163
+ ### Issue: "i18n configuration not initialized"
164
+
165
+ **Cause**: Forgot to call `setI18nConfig()` in layout
166
+
167
+ **Fix**: Add this at the top of your layout file:
168
+ ```typescript
169
+ import { setI18nConfig } from 'simple-site-framework/lib/i18n';
170
+ import { i18nConfig } from '../../config/i18n';
171
+
172
+ setI18nConfig(i18nConfig);
173
+ ```
174
+
175
+ ### Issue: Routes not working
176
+
177
+ **Cause**: Middleware not created or incorrect matcher
178
+
179
+ **Fix**: Ensure `/src/middleware.ts` exists and exports the middleware with correct matcher.
180
+
181
+ ### Issue: Language selector not appearing
182
+
183
+ **Cause**: Component not imported or config not initialized
184
+
185
+ **Fix**: Import `LanguageSelector` and ensure config is initialized before rendering.
186
+
187
+ ## Upgrading to Better Prefix Modes
188
+
189
+ Once migrated, consider switching to `localePrefix: 'as-needed'` for better UX:
190
+
191
+ ```typescript
192
+ export const i18nConfig: I18nConfig = {
193
+ locales: ['fr', 'en'],
194
+ defaultLocale: 'fr',
195
+ localePrefix: 'as-needed', // Changed from 'always'
196
+ // ... rest of config
197
+ };
198
+ ```
199
+
200
+ **With 'as-needed':**
201
+ - French (default): `/about` (no prefix)
202
+ - English: `/en/about` (with prefix)
203
+
204
+ **Benefits:**
205
+ - Cleaner URLs for default language
206
+ - Better SEO (canonical URLs simpler)
207
+ - Matches user expectations for primary market
208
+
209
+ ## Adding More Languages
210
+
211
+ To add more languages after migration:
212
+
213
+ ```typescript
214
+ export const i18nConfig: I18nConfig = {
215
+ locales: ['fr', 'en', 'es', 'de'], // Added Spanish and German
216
+ defaultLocale: 'fr',
217
+ localePrefix: 'as-needed',
218
+ localeNames: {
219
+ fr: 'Français',
220
+ en: 'English',
221
+ es: 'Español', // Add display names
222
+ de: 'Deutsch',
223
+ },
224
+ localeLabels: {
225
+ fr: 'FR',
226
+ en: 'EN',
227
+ es: 'ES', // Add labels
228
+ de: 'DE',
229
+ },
230
+ };
231
+ ```
232
+
233
+ The `LanguageSelector` automatically switches to dropdown mode with 3+ languages.
234
+
235
+ ## RTL Language Support
236
+
237
+ To add RTL languages (Arabic, Hebrew, etc.):
238
+
239
+ ```typescript
240
+ export const i18nConfig: I18nConfig = {
241
+ locales: ['en', 'ar', 'he'],
242
+ defaultLocale: 'en',
243
+ rtlLocales: ['ar', 'he'], // Specify RTL locales
244
+ // ... rest of config
245
+ };
246
+ ```
247
+
248
+ Update your layout to use text direction:
249
+
250
+ ```typescript
251
+ import { getTextDirection } from 'simple-site-framework/lib/i18n';
252
+
253
+ <html lang={locale} dir={getTextDirection(locale)}>
254
+ ```
255
+
256
+ ## Need Help?
257
+
258
+ - Check [CONFIGURATION.md](./CONFIGURATION.md) for complete config reference
259
+ - Check [EXAMPLES.md](./EXAMPLES.md) for usage examples
260
+ - Open an issue on GitHub: https://github.com/zoyth/simple-site-framework/issues