@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 @@
1
+ {"version":3,"sources":["../../../src/lib/i18n/config.ts","../../../src/lib/i18n/index.ts","../../../src/lib/i18n/locale-cookie.ts","../../../src/lib/i18n/slug-translations.ts","../../../src/lib/i18n/formatters.ts","../../../src/lib/i18n/middleware.ts","../../../src/lib/i18n/utils.ts"],"sourcesContent":["// ABOUTME: Dynamic i18n configuration system for flexible multi-language support\n// ABOUTME: Projects must call setI18nConfig() to initialize their locale configuration\n\nimport type { I18nConfig, LocalePrefix } from './types';\n\n/**\n * Global i18n configuration state\n * Initialized by calling setI18nConfig()\n */\nlet globalI18nConfig: I18nConfig | null = null;\n\n/**\n * Initialize the i18n configuration\n * Must be called before using any i18n features\n *\n * @param config - Complete i18n configuration\n *\n * @example\n * ```typescript\n * import { setI18nConfig } from 'simple-site-framework/lib/i18n';\n * import { i18nConfig } from './config/i18n';\n *\n * setI18nConfig(i18nConfig);\n * ```\n */\nexport function setI18nConfig(config: I18nConfig): void {\n // Validate configuration\n if (!config.locales || config.locales.length === 0) {\n throw new Error('i18n config must define at least one locale');\n }\n\n if (!config.defaultLocale) {\n throw new Error('i18n config must define a default locale');\n }\n\n if (!config.locales.includes(config.defaultLocale)) {\n throw new Error(\n `Default locale \"${config.defaultLocale}\" must be included in locales array: [${config.locales.join(', ')}]`\n );\n }\n\n // Set defaults for optional fields\n const configWithDefaults: I18nConfig = {\n ...config,\n localePrefix: config.localePrefix || 'as-needed',\n localeDetection: config.localeDetection !== false, // Default to true\n localeNames: config.localeNames || {},\n localeLabels: config.localeLabels || {},\n rtlLocales: config.rtlLocales || [],\n localeCookie: {\n name: config.localeCookie?.name || 'NEXT_LOCALE',\n maxAge: config.localeCookie?.maxAge || 365 * 24 * 60 * 60, // 1 year\n sameSite: config.localeCookie?.sameSite || 'lax',\n },\n slugTranslations: config.slugTranslations || {},\n };\n\n globalI18nConfig = configWithDefaults;\n}\n\n/**\n * Get the current i18n configuration\n * Returns legacy default config if not initialized (for build compatibility)\n *\n * @deprecated Calling without initialization - will throw in v1.0.0\n */\nexport function getI18nConfig(): I18nConfig {\n if (!globalI18nConfig) {\n // During static generation, config may not be initialized yet\n // Return legacy defaults to allow build to complete\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '⚠️ i18n configuration not initialized. Using legacy defaults.\\n' +\n 'Call setI18nConfig() in your layout before using i18n features.\\n' +\n 'See docs/i18n/MIGRATION.md for setup instructions.'\n );\n }\n\n // Return legacy hardcoded config for backward compatibility\n return {\n locales: ['fr', 'en'],\n defaultLocale: 'fr',\n localePrefix: 'as-needed',\n localeDetection: true,\n localeNames: { fr: 'Français', en: 'English' },\n localeLabels: { fr: 'FR', en: 'EN' },\n rtlLocales: [],\n localeCookie: {\n name: 'NEXT_LOCALE',\n maxAge: 365 * 24 * 60 * 60,\n sameSite: 'lax',\n },\n slugTranslations: {},\n };\n }\n\n return globalI18nConfig;\n}\n\n/**\n * Check if i18n config has been initialized\n */\nexport function isI18nConfigInitialized(): boolean {\n return globalI18nConfig !== null;\n}\n\n/**\n * Reset i18n configuration (for testing only)\n * @internal\n */\nexport function __resetI18nConfig__(): void {\n globalI18nConfig = null;\n}\n\n/**\n * Get supported locales array\n */\nexport function getLocales(): readonly string[] {\n return getI18nConfig().locales;\n}\n\n/**\n * Get default locale\n */\nexport function getDefaultLocale(): string {\n return getI18nConfig().defaultLocale;\n}\n\n/**\n * Get locale prefix mode\n */\nexport function getLocalePrefix(): LocalePrefix {\n return getI18nConfig().localePrefix || 'as-needed';\n}\n\n/**\n * Get locale names mapping\n */\nexport function getLocaleNames(): Record<string, string> {\n return getI18nConfig().localeNames || {};\n}\n\n/**\n * Get locale labels mapping\n */\nexport function getLocaleLabels(): Record<string, string> {\n return getI18nConfig().localeLabels || {};\n}\n\n/**\n * Get RTL locales array\n */\nexport function getRtlLocales(): readonly string[] {\n return getI18nConfig().rtlLocales || [];\n}\n\n/**\n * Check if locale detection is enabled\n */\nexport function isLocaleDetectionEnabled(): boolean {\n return getI18nConfig().localeDetection !== false;\n}\n\n/**\n * Get locale cookie configuration\n */\nexport function getLocaleCookieConfig() {\n const config = getI18nConfig();\n return {\n name: config.localeCookie?.name || 'NEXT_LOCALE',\n maxAge: config.localeCookie?.maxAge || 365 * 24 * 60 * 60,\n sameSite: config.localeCookie?.sameSite || 'lax',\n };\n}\n\n/**\n * Check if a locale is supported\n */\nexport function isSupportedLocale(locale: string): boolean {\n return getLocales().includes(locale);\n}\n\n/**\n * Get full locale name for display\n */\nexport function getLocaleName(locale: string): string {\n const names = getLocaleNames();\n return names[locale] || locale;\n}\n\n/**\n * Get short locale label for compact display\n */\nexport function getLocaleLabel(locale: string): string {\n const labels = getLocaleLabels();\n return labels[locale] || locale.toUpperCase();\n}\n\n// ====================================\n// Legacy exports for backward compatibility\n// These will be removed in a future major version\n// ====================================\n\n/**\n * @deprecated Use getLocales() instead. This export will be removed in v1.0.0\n */\nexport const locales = ['fr', 'en'] as const;\n\n/**\n * @deprecated Import from config schemas instead\n */\nexport type Locale = 'fr' | 'en';\n\n/**\n * @deprecated Use getDefaultLocale() instead. This export will be removed in v1.0.0\n */\nexport const defaultLocale: Locale = 'fr';\n\n/**\n * @deprecated Use getLocaleNames() instead. This export will be removed in v1.0.0\n */\nexport const localeNames: Record<Locale, string> = {\n fr: 'Français',\n en: 'English',\n};\n\n/**\n * @deprecated Use getLocaleLabels() instead. This export will be removed in v1.0.0\n */\nexport const localeLabels: Record<Locale, string> = {\n fr: 'FR',\n en: 'EN',\n};\n","// ABOUTME: i18n configuration export\n// ABOUTME: Export i18n types and configuration\n\n// Core types\nexport type {\n I18nConfig,\n LocalePrefix,\n LocaleCookieConfig,\n LanguagePreference,\n ValidLocale,\n SlugTranslations,\n} from './types';\n\n// Configuration management\nexport {\n setI18nConfig,\n getI18nConfig,\n isI18nConfigInitialized,\n getLocales,\n getDefaultLocale,\n getLocalePrefix,\n getLocaleNames,\n getLocaleLabels,\n getRtlLocales,\n isLocaleDetectionEnabled,\n getLocaleCookieConfig,\n isSupportedLocale,\n getLocaleName,\n getLocaleLabel,\n} from './config';\n\n// Legacy exports (deprecated, will be removed in v1.0.0)\nexport { locales, defaultLocale } from './config';\nexport type { Locale } from './config';\n\n// Cookie management\nexport { getLocaleFromCookie, setLocaleCookie, LOCALE_COOKIE_NAME } from './locale-cookie';\n\n// Slug translations\nexport { translateSlug, defaultSlugTranslations } from './slug-translations';\n\n// Locale-aware formatters\nexport {\n formatDate,\n formatNumber,\n formatCurrency,\n formatRelativeTime,\n formatDateRange,\n formatList,\n formatFileSize,\n getRelativeTime,\n} from './formatters';\n\n// Middleware for routing\nexport { createI18nMiddleware } from './middleware';\n\n// Utilities\nexport {\n isRtlLocale,\n getTextDirection,\n validateLocale,\n getAlternateLocales,\n normalizeLocale,\n matchLocale,\n getLocaleAutonym,\n formatLocaleDisplay,\n} from './utils';\n","// ABOUTME: Utilities for persisting user locale preference via cookies\n// ABOUTME: Allows remembering language choice across sessions\n\nimport { getLocaleCookieConfig, isSupportedLocale } from './config';\n\nexport const LOCALE_COOKIE_NAME = 'NEXT_LOCALE';\n\n/**\n * Get locale from cookie\n * Returns null if cookie not found or locale not supported\n */\nexport function getLocaleFromCookie(): string | null {\n if (typeof document === 'undefined') return null;\n\n // Safe: only runs in browser, but check config anyway for build safety\n try {\n const cookieConfig = getLocaleCookieConfig();\n const cookieName = cookieConfig.name;\n\n const cookie = document.cookie\n .split('; ')\n .find((row) => row.startsWith(`${cookieName}=`));\n\n if (!cookie) return null;\n\n const value = cookie.split('=')[1];\n\n // Validate that locale is supported\n if (isSupportedLocale(value)) {\n return value;\n }\n\n return null;\n } catch (error) {\n // Config not initialized - return null\n if (process.env.NODE_ENV !== 'production') {\n console.warn('getLocaleFromCookie: i18n config not initialized');\n }\n return null;\n }\n}\n\n/**\n * Set locale cookie\n * Uses configuration from i18n config\n */\nexport function setLocaleCookie(locale: string) {\n if (typeof document === 'undefined') return;\n\n try {\n // Validate locale is supported before setting\n if (!isSupportedLocale(locale)) {\n console.warn(`Attempted to set unsupported locale: ${locale}`);\n return;\n }\n\n const cookieConfig = getLocaleCookieConfig();\n\n document.cookie = `${cookieConfig.name}=${locale}; max-age=${cookieConfig.maxAge}; path=/; SameSite=${cookieConfig.sameSite}`;\n } catch (error) {\n // Config not initialized - fail silently\n if (process.env.NODE_ENV !== 'production') {\n console.warn('setLocaleCookie: i18n config not initialized');\n }\n }\n}\n","// ABOUTME: Slug translation mappings for bilingual routing\n// ABOUTME: Maps French slugs to English equivalents and vice versa\n\nimport type { SlugTranslations } from './types';\n\n// Re-export for backward compatibility\nexport type { SlugTranslations };\n\n// Default slug translations - can be overridden by apps\nexport const defaultSlugTranslations: SlugTranslations = {\n fr: {\n '/marketing-par-courriel': '/email-marketing',\n '/courriels-transactionnels': '/transactional-emails',\n '/forfaits': '/pricing',\n '/nous-contacter': '/contact',\n '/a-propos': '/about',\n '/politique-de-confidentialite': '/privacy-policy',\n '/conditions-dutilisation': '/terms-of-service',\n '/politique-anti-pourriel': '/anti-spam-policy',\n },\n en: {\n '/email-marketing': '/marketing-par-courriel',\n '/transactional-emails': '/courriels-transactionnels',\n '/pricing': '/forfaits',\n '/contact': '/nous-contacter',\n '/about': '/a-propos',\n '/privacy-policy': '/politique-de-confidentialite',\n '/terms-of-service': '/conditions-dutilisation',\n '/anti-spam-policy': '/politique-anti-pourriel',\n },\n};\n\n/**\n * Translates a path from one locale to another\n *\n * Merges translations in this priority order:\n * 1. Custom translations passed as parameter (highest priority)\n * 2. Translations from i18n config (if configured)\n * 3. Default translations (lowest priority)\n *\n * @param path - The current path (without locale prefix)\n * @param fromLocale - The current locale\n * @param toLocale - The target locale\n * @param customTranslations - Optional custom translations to merge with defaults\n * @returns The translated path\n *\n * @example\n * ```typescript\n * // With config translations\n * translateSlug('/about', 'en', 'fr')\n * // Returns: '/a-propos' (from config or defaults)\n *\n * // With custom override\n * translateSlug('/about', 'en', 'fr', {\n * en: { '/about': '/notre-equipe' }\n * })\n * // Returns: '/notre-equipe' (custom override)\n *\n * // Nested paths\n * translateSlug('/about/team', 'en', 'fr')\n * // Returns: '/a-propos/team' (translates base, keeps rest)\n * ```\n */\nexport function translateSlug(\n path: string,\n fromLocale: string,\n toLocale: string,\n customTranslations?: SlugTranslations\n): string {\n // Try to get config translations (may not be initialized)\n let configTranslations: SlugTranslations = {};\n try {\n const { getI18nConfig } = require('./config');\n const config = getI18nConfig();\n configTranslations = config.slugTranslations || {};\n } catch {\n // Config not initialized, use empty\n }\n\n // Merge translations: custom > config > defaults\n const translations = mergeTranslations(\n defaultSlugTranslations,\n configTranslations,\n customTranslations || {}\n );\n\n // Get the translation map for the source locale\n const translationMap = translations[fromLocale];\n\n if (!translationMap) {\n return path; // No translations for this locale, return original\n }\n\n // Check if we have a direct translation\n if (translationMap[path]) {\n return translationMap[path];\n }\n\n // Check for nested paths (e.g., /marketing-par-courriel/feature)\n for (const [fromSlug, toSlug] of Object.entries(translationMap)) {\n if (path.startsWith(fromSlug + '/')) {\n // Replace the base slug and keep the rest of the path\n return path.replace(fromSlug, toSlug);\n }\n }\n\n // No translation found, return original path\n return path;\n}\n\n/**\n * Merge multiple slug translation objects\n * Later objects take precedence over earlier ones\n */\nfunction mergeTranslations(...translations: SlugTranslations[]): SlugTranslations {\n const merged: SlugTranslations = {};\n\n for (const trans of translations) {\n for (const [locale, slugs] of Object.entries(trans)) {\n if (!merged[locale]) {\n merged[locale] = {};\n }\n Object.assign(merged[locale], slugs);\n }\n }\n\n return merged;\n}\n","// ABOUTME: Locale-aware formatting utilities using native Intl API\n// ABOUTME: Date, number, currency, and relative time formatters for internationalization\n\n/**\n * Format a date according to locale\n *\n * @param date - Date to format\n * @param locale - Locale code (e.g., 'en', 'fr', 'es')\n * @param options - Intl.DateTimeFormat options\n *\n * @example\n * ```typescript\n * formatDate(new Date('2026-02-01'), 'fr', { dateStyle: 'long' })\n * // \"1 février 2026\"\n *\n * formatDate(new Date('2026-02-01'), 'en', { dateStyle: 'long' })\n * // \"February 1, 2026\"\n *\n * formatDate(new Date(), 'fr', {\n * weekday: 'long',\n * year: 'numeric',\n * month: 'long',\n * day: 'numeric'\n * })\n * // \"samedi 1 février 2026\"\n * ```\n */\nexport function formatDate(\n date: Date,\n locale: string,\n options?: Intl.DateTimeFormatOptions\n): string {\n return new Intl.DateTimeFormat(locale, options).format(date);\n}\n\n/**\n * Format a number according to locale\n *\n * @param value - Number to format\n * @param locale - Locale code\n * @param options - Intl.NumberFormat options\n *\n * @example\n * ```typescript\n * formatNumber(1234567.89, 'en')\n * // \"1,234,567.89\"\n *\n * formatNumber(1234567.89, 'fr')\n * // \"1 234 567,89\"\n *\n * formatNumber(0.42, 'en', { style: 'percent' })\n * // \"42%\"\n *\n * formatNumber(1234, 'en', { minimumFractionDigits: 2 })\n * // \"1,234.00\"\n * ```\n */\nexport function formatNumber(\n value: number,\n locale: string,\n options?: Intl.NumberFormatOptions\n): string {\n return new Intl.NumberFormat(locale, options).format(value);\n}\n\n/**\n * Format a currency amount according to locale\n *\n * @param amount - Amount to format\n * @param locale - Locale code\n * @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR', 'CAD')\n * @param options - Additional Intl.NumberFormat options\n *\n * @example\n * ```typescript\n * formatCurrency(1299.99, 'en', 'USD')\n * // \"$1,299.99\"\n *\n * formatCurrency(1299.99, 'fr', 'EUR')\n * // \"1 299,99 €\"\n *\n * formatCurrency(1299.99, 'fr-CA', 'CAD')\n * // \"1 299,99 $\"\n *\n * formatCurrency(1299.99, 'ja', 'JPY')\n * // \"¥1,300\"\n *\n * formatCurrency(0.99, 'en', 'USD', { currencyDisplay: 'name' })\n * // \"0.99 US dollars\"\n * ```\n */\nexport function formatCurrency(\n amount: number,\n locale: string,\n currency: string,\n options?: Intl.NumberFormatOptions\n): string {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n ...options,\n }).format(amount);\n}\n\n/**\n * Format relative time (e.g., \"2 hours ago\", \"in 3 days\")\n *\n * @param value - Numeric value (negative for past, positive for future)\n * @param unit - Time unit\n * @param locale - Locale code\n * @param options - Intl.RelativeTimeFormat options\n *\n * @example\n * ```typescript\n * formatRelativeTime(-2, 'hour', 'en')\n * // \"2 hours ago\"\n *\n * formatRelativeTime(-2, 'hour', 'fr')\n * // \"il y a 2 heures\"\n *\n * formatRelativeTime(3, 'day', 'en')\n * // \"in 3 days\"\n *\n * formatRelativeTime(-1, 'week', 'es')\n * // \"hace 1 semana\"\n *\n * formatRelativeTime(-5, 'minute', 'en', { numeric: 'auto' })\n * // \"5 minutes ago\"\n * ```\n */\nexport function formatRelativeTime(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n locale: string,\n options?: Intl.RelativeTimeFormatOptions\n): string {\n return new Intl.RelativeTimeFormat(locale, options).format(value, unit);\n}\n\n/**\n * Format a date range according to locale\n * Note: formatRange requires newer TypeScript/Node versions\n *\n * @param startDate - Start date\n * @param endDate - End date\n * @param locale - Locale code\n * @param options - Intl.DateTimeFormat options\n *\n * @example\n * ```typescript\n * formatDateRange(\n * new Date('2026-02-01'),\n * new Date('2026-02-15'),\n * 'en',\n * { month: 'long', day: 'numeric' }\n * )\n * // \"February 1 – 15\"\n * ```\n */\nexport function formatDateRange(\n startDate: Date,\n endDate: Date,\n locale: string,\n options?: Intl.DateTimeFormatOptions\n): string {\n const formatter = new Intl.DateTimeFormat(locale, options);\n // Use formatRange if available, otherwise format separately\n if ('formatRange' in formatter) {\n return (formatter as any).formatRange(startDate, endDate);\n }\n return `${formatter.format(startDate)} – ${formatter.format(endDate)}`;\n}\n\n/**\n * Format a list of items according to locale\n * Falls back to simple comma-separated list if Intl.ListFormat not available\n *\n * @param items - Array of items to format\n * @param locale - Locale code\n *\n * @example\n * ```typescript\n * formatList(['apples', 'oranges', 'bananas'], 'en')\n * // \"apples, oranges, and bananas\"\n *\n * formatList(['pommes', 'oranges', 'bananes'], 'fr')\n * // \"pommes, oranges et bananes\"\n * ```\n */\nexport function formatList(\n items: string[],\n locale: string\n): string {\n // Check if Intl.ListFormat is available\n if (typeof Intl !== 'undefined' && 'ListFormat' in Intl) {\n return new (Intl as any).ListFormat(locale).format(items);\n }\n\n // Fallback for older environments\n if (items.length === 0) return '';\n if (items.length === 1) return items[0];\n if (items.length === 2) {\n const connector = locale === 'fr' ? ' et ' : ' and ';\n return items.join(connector);\n }\n\n const last = items[items.length - 1];\n const rest = items.slice(0, -1);\n const connector = locale === 'fr' ? ' et ' : ', and ';\n return rest.join(', ') + connector + last;\n}\n\n/**\n * Format file size in bytes to human-readable format\n * Not using Intl, but useful for internationalized apps\n *\n * @param bytes - File size in bytes\n * @param locale - Locale code\n * @param decimals - Number of decimal places @default 2\n *\n * @example\n * ```typescript\n * formatFileSize(1024, 'en')\n * // \"1.00 KB\"\n *\n * formatFileSize(1048576, 'fr')\n * // \"1,00 Mo\"\n *\n * formatFileSize(1073741824, 'en', 1)\n * // \"1.0 GB\"\n * ```\n */\nexport function formatFileSize(\n bytes: number,\n locale: string,\n decimals: number = 2\n): string {\n if (bytes === 0) return '0 B';\n\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const value = bytes / Math.pow(k, i);\n\n return `${formatNumber(value, locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n })} ${sizes[i]}`;\n}\n\n/**\n * Get relative time from a date (auto-selects best unit)\n *\n * @param date - Date to compare against now\n * @param locale - Locale code\n * @param options - Intl.RelativeTimeFormat options\n *\n * @example\n * ```typescript\n * // If date is 2 hours ago\n * getRelativeTime(pastDate, 'en')\n * // \"2 hours ago\"\n *\n * // If date is 3 days from now\n * getRelativeTime(futureDate, 'en')\n * // \"in 3 days\"\n *\n * // If date is 45 seconds ago\n * getRelativeTime(recentDate, 'fr')\n * // \"il y a 45 secondes\"\n * ```\n */\nexport function getRelativeTime(\n date: Date,\n locale: string,\n options?: Intl.RelativeTimeFormatOptions\n): string {\n const now = new Date();\n const diffMs = date.getTime() - now.getTime();\n const diffSecs = Math.round(diffMs / 1000);\n const diffMins = Math.round(diffSecs / 60);\n const diffHours = Math.round(diffMins / 60);\n const diffDays = Math.round(diffHours / 24);\n const diffWeeks = Math.round(diffDays / 7);\n const diffMonths = Math.round(diffDays / 30);\n const diffYears = Math.round(diffDays / 365);\n\n if (Math.abs(diffSecs) < 60) {\n return formatRelativeTime(diffSecs, 'second', locale, options);\n } else if (Math.abs(diffMins) < 60) {\n return formatRelativeTime(diffMins, 'minute', locale, options);\n } else if (Math.abs(diffHours) < 24) {\n return formatRelativeTime(diffHours, 'hour', locale, options);\n } else if (Math.abs(diffDays) < 7) {\n return formatRelativeTime(diffDays, 'day', locale, options);\n } else if (Math.abs(diffWeeks) < 4) {\n return formatRelativeTime(diffWeeks, 'week', locale, options);\n } else if (Math.abs(diffMonths) < 12) {\n return formatRelativeTime(diffMonths, 'month', locale, options);\n } else {\n return formatRelativeTime(diffYears, 'year', locale, options);\n }\n}\n","// ABOUTME: Middleware factory for automatic locale detection and routing\n// ABOUTME: Handles URL rewriting, redirects, and cookie persistence based on prefix mode\n\nimport { NextRequest, NextResponse } from 'next/server';\nimport type { I18nConfig } from './types';\n\n/**\n * Create Next.js middleware for i18n routing\n *\n * @param config - i18n configuration\n * @returns Middleware function\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { createI18nMiddleware } from 'simple-site-framework/lib/i18n';\n * import { i18nConfig } from './src/config/i18n';\n *\n * export default createI18nMiddleware(i18nConfig);\n *\n * export const config = {\n * matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],\n * };\n * ```\n */\nexport function createI18nMiddleware(config: I18nConfig) {\n return function middleware(request: NextRequest): NextResponse {\n const { pathname } = request.nextUrl;\n\n // 1. Extract locale from URL pathname\n const pathnameLocale = getLocaleFromPathname(pathname, config);\n\n // 2. If locale found in URL, validate it\n if (pathnameLocale) {\n if (!config.locales.includes(pathnameLocale)) {\n // Invalid locale in URL, redirect to default\n return redirectToLocale(request, config.defaultLocale, pathname, config);\n }\n\n // Valid locale in URL, set cookie and continue\n const response = NextResponse.next();\n setLocaleCookie(response, pathnameLocale, config);\n return response;\n }\n\n // 3. No locale in URL, detect from browser/cookie\n const detectedLocale = detectLocale(request, config);\n\n // 4. Handle based on prefix mode\n const prefixMode = config.localePrefix || 'as-needed';\n\n if (prefixMode === 'always') {\n // Always redirect to add locale prefix\n return redirectToLocale(request, detectedLocale, pathname, config);\n } else if (prefixMode === 'as-needed') {\n // Only redirect if detected locale is NOT the default\n if (detectedLocale !== config.defaultLocale) {\n return redirectToLocale(request, detectedLocale, pathname, config);\n }\n // Default locale, continue without redirect but set cookie\n const response = NextResponse.next();\n setLocaleCookie(response, config.defaultLocale, config);\n return response;\n } else {\n // 'never' mode: no redirects, just set cookie\n const response = NextResponse.next();\n setLocaleCookie(response, detectedLocale, config);\n return response;\n }\n };\n}\n\n/**\n * Extract locale from URL pathname\n * Returns null if no locale found\n */\nfunction getLocaleFromPathname(pathname: string, config: I18nConfig): string | null {\n const segments = pathname.split('/').filter(Boolean);\n\n if (segments.length === 0) {\n return null;\n }\n\n const firstSegment = segments[0];\n\n // Check if first segment matches a supported locale\n if (config.locales.includes(firstSegment)) {\n return firstSegment;\n }\n\n return null;\n}\n\n/**\n * Detect locale from cookie and Accept-Language header\n * Falls back to default locale\n */\nfunction detectLocale(request: NextRequest, config: I18nConfig): string {\n // 1. Check cookie first (user's explicit preference)\n const cookieName = config.localeCookie?.name || 'NEXT_LOCALE';\n const cookieLocale = request.cookies.get(cookieName)?.value;\n\n if (cookieLocale && config.locales.includes(cookieLocale)) {\n return cookieLocale;\n }\n\n // 2. Check Accept-Language header (browser preference)\n if (config.localeDetection !== false) {\n const acceptLanguage = request.headers.get('accept-language');\n const browserLocale = negotiateLanguage(acceptLanguage, config.locales);\n\n if (browserLocale) {\n return browserLocale;\n }\n }\n\n // 3. Fall back to default locale\n return config.defaultLocale;\n}\n\n/**\n * Negotiate language from Accept-Language header\n * Returns best match from supported locales, or null if no match\n *\n * @example\n * Accept-Language: fr-CA,fr;q=0.9,en;q=0.8\n * Supported: ['en', 'fr', 'es']\n * Result: 'fr' (highest quality match)\n */\nfunction negotiateLanguage(\n acceptLanguage: string | null,\n supportedLocales: readonly string[]\n): string | null {\n if (!acceptLanguage) {\n return null;\n }\n\n // Parse Accept-Language header into preferences\n const preferences = parseAcceptLanguage(acceptLanguage);\n\n // Find best match\n for (const pref of preferences) {\n // Exact match (e.g., 'en' matches 'en')\n if (supportedLocales.includes(pref.locale)) {\n return pref.locale;\n }\n\n // Language family match (e.g., 'en-US' matches 'en')\n const languageCode = pref.locale.split('-')[0];\n if (supportedLocales.includes(languageCode)) {\n return languageCode;\n }\n\n // Check if any supported locale starts with this language\n const match = supportedLocales.find(\n (locale) => locale.startsWith(languageCode + '-') || locale === languageCode\n );\n if (match) {\n return match;\n }\n }\n\n return null;\n}\n\n/**\n * Parse Accept-Language header into sorted preferences\n * Returns array sorted by quality value (highest first)\n */\ninterface LanguagePreference {\n locale: string;\n quality: number;\n}\n\nfunction parseAcceptLanguage(header: string): LanguagePreference[] {\n const preferences: LanguagePreference[] = [];\n\n // Split by comma and parse each preference\n const parts = header.split(',').map((p) => p.trim());\n\n for (const part of parts) {\n const [locale, ...rest] = part.split(';').map((p) => p.trim());\n\n // Extract quality value (default to 1.0)\n let quality = 1.0;\n const qParam = rest.find((p) => p.startsWith('q='));\n if (qParam) {\n const qValue = parseFloat(qParam.substring(2));\n if (!isNaN(qValue)) {\n quality = qValue;\n }\n }\n\n preferences.push({\n locale: locale.toLowerCase(),\n quality,\n });\n }\n\n // Sort by quality (highest first)\n preferences.sort((a, b) => b.quality - a.quality);\n\n return preferences;\n}\n\n/**\n * Redirect to URL with locale prefix\n */\nfunction redirectToLocale(\n request: NextRequest,\n locale: string,\n pathname: string,\n config: I18nConfig\n): NextResponse {\n const url = request.nextUrl.clone();\n\n // Remove any existing locale prefix\n const pathWithoutLocale = removeLocalePrefix(pathname, config);\n\n // Build new pathname with locale\n url.pathname = `/${locale}${pathWithoutLocale}`;\n\n const response = NextResponse.redirect(url);\n setLocaleCookie(response, locale, config);\n\n return response;\n}\n\n/**\n * Remove locale prefix from pathname if present\n */\nfunction removeLocalePrefix(pathname: string, config: I18nConfig): string {\n const segments = pathname.split('/').filter(Boolean);\n\n if (segments.length === 0) {\n return '/';\n }\n\n const firstSegment = segments[0];\n\n if (config.locales.includes(firstSegment)) {\n // Remove locale segment\n const remaining = segments.slice(1);\n return remaining.length > 0 ? `/${remaining.join('/')}` : '/';\n }\n\n return pathname;\n}\n\n/**\n * Set locale cookie on response\n */\nfunction setLocaleCookie(\n response: NextResponse,\n locale: string,\n config: I18nConfig\n): void {\n const cookieConfig = config.localeCookie || {};\n\n response.cookies.set({\n name: cookieConfig.name || 'NEXT_LOCALE',\n value: locale,\n maxAge: cookieConfig.maxAge || 365 * 24 * 60 * 60, // 1 year\n path: '/',\n sameSite: cookieConfig.sameSite || 'lax',\n });\n}\n","// ABOUTME: i18n utility functions for locale management and text direction\n// ABOUTME: RTL support, validation, and enhanced localized string handling\n\nimport { getI18nConfig, getRtlLocales, isSupportedLocale as isSupported } from './config';\n\n/**\n * Check if a locale uses right-to-left text direction\n *\n * @param locale - Locale code to check\n * @returns true if locale is RTL, false otherwise\n *\n * @example\n * ```typescript\n * isRtlLocale('ar') // true (Arabic)\n * isRtlLocale('he') // true (Hebrew)\n * isRtlLocale('en') // false (English)\n * isRtlLocale('fr') // false (French)\n * ```\n */\nexport function isRtlLocale(locale: string): boolean {\n const rtlLocales = getRtlLocales();\n return rtlLocales.includes(locale);\n}\n\n/**\n * Get text direction for a locale\n *\n * @param locale - Locale code\n * @returns 'rtl' for right-to-left locales, 'ltr' for left-to-right\n *\n * @example\n * ```tsx\n * // In layout\n * <html lang={locale} dir={getTextDirection(locale)}>\n *\n * // Results:\n * getTextDirection('ar') // 'rtl'\n * getTextDirection('en') // 'ltr'\n * ```\n */\nexport function getTextDirection(locale: string): 'ltr' | 'rtl' {\n return isRtlLocale(locale) ? 'rtl' : 'ltr';\n}\n\n// Note: getLocalizedString is exported from lib/content/utils\n// Use that version for accessing localized content strings\n\n/**\n * Validate if a locale is supported\n *\n * @param locale - Locale code to validate\n * @returns true if locale is supported, false otherwise\n *\n * @example\n * ```typescript\n * // With config: locales: ['en', 'fr', 'es']\n * validateLocale('en') // true\n * validateLocale('fr') // true\n * validateLocale('de') // false\n * validateLocale('invalid') // false\n * ```\n */\nexport function validateLocale(locale: string): boolean {\n return isSupported(locale);\n}\n\n/**\n * Get all supported locales except the current one\n *\n * @param currentLocale - Current locale to exclude\n * @returns Array of alternate locales\n *\n * @example\n * ```typescript\n * // With config: locales: ['en', 'fr', 'es', 'de']\n * getAlternateLocales('en') // ['fr', 'es', 'de']\n * getAlternateLocales('fr') // ['en', 'es', 'de']\n * ```\n */\nexport function getAlternateLocales(currentLocale: string): string[] {\n try {\n const config = getI18nConfig();\n return config.locales.filter((l) => l !== currentLocale);\n } catch (error) {\n // Config not initialized - return empty array\n if (process.env.NODE_ENV !== 'production') {\n console.warn('getAlternateLocales: i18n config not initialized, returning []');\n }\n return [];\n }\n}\n\n/**\n * Normalize locale code to lowercase\n * Handles variants like 'en-US' -> 'en', 'zh-CN' -> 'zh'\n *\n * @param locale - Locale code (can include region)\n * @returns Normalized locale code\n *\n * @example\n * ```typescript\n * normalizeLocale('en-US') // 'en'\n * normalizeLocale('zh-CN') // 'zh'\n * normalizeLocale('FR') // 'fr'\n * normalizeLocale('es') // 'es'\n * ```\n */\nexport function normalizeLocale(locale: string): string {\n return locale.toLowerCase().split('-')[0];\n}\n\n/**\n * Check if a locale code matches a supported locale\n * Handles locale variants (e.g., 'en-US' matches 'en')\n *\n * @param locale - Locale code to check (can include region)\n * @returns Matching supported locale or null\n *\n * @example\n * ```typescript\n * // With config: locales: ['en', 'fr', 'es']\n * matchLocale('en-US') // 'en'\n * matchLocale('fr-CA') // 'fr'\n * matchLocale('de-DE') // null\n * ```\n */\nexport function matchLocale(locale: string): string | null {\n try {\n const config = getI18nConfig();\n const normalized = normalizeLocale(locale);\n\n // Exact match first\n if (config.locales.includes(locale)) {\n return locale;\n }\n\n // Match normalized (e.g., 'en-US' -> 'en')\n if (config.locales.includes(normalized)) {\n return normalized;\n }\n\n // Check if any supported locale starts with this language code\n const match = config.locales.find((l) => l.startsWith(normalized));\n if (match) {\n return match;\n }\n\n return null;\n } catch (error) {\n // Config not initialized - return null\n if (process.env.NODE_ENV !== 'production') {\n console.warn('matchLocale: i18n config not initialized, returning null');\n }\n return null;\n }\n}\n\n/**\n * Get locale display name in its own language (autonym)\n *\n * @param locale - Locale code\n * @returns Display name or locale code if not found\n *\n * @example\n * ```typescript\n * getLocaleAutonym('en') // 'English'\n * getLocaleAutonym('fr') // 'Français'\n * getLocaleAutonym('es') // 'Español'\n * ```\n */\nexport function getLocaleAutonym(locale: string): string {\n // Common language autonyms\n const autonyms: Record<string, string> = {\n en: 'English',\n fr: 'Français',\n es: 'Español',\n de: 'Deutsch',\n it: 'Italiano',\n pt: 'Português',\n ru: 'Русский',\n ja: '日本語',\n ko: '한국어',\n zh: '中文',\n ar: 'العربية',\n he: 'עברית',\n hi: 'हिन्दी',\n tr: 'Türkçe',\n pl: 'Polski',\n nl: 'Nederlands',\n sv: 'Svenska',\n da: 'Dansk',\n no: 'Norsk',\n fi: 'Suomi',\n cs: 'Čeština',\n el: 'Ελληνικά',\n th: 'ไทย',\n vi: 'Tiếng Việt',\n id: 'Bahasa Indonesia',\n ms: 'Bahasa Melayu',\n uk: 'Українська',\n };\n\n // Try to get from config first\n try {\n const { getLocaleNames } = require('./config');\n const names = getLocaleNames();\n if (names[locale]) {\n return names[locale];\n }\n } catch {\n // Config not available\n }\n\n // Fall back to autonym map\n return autonyms[locale] || locale.toUpperCase();\n}\n\n/**\n * Format locale for display (e.g., for language selector)\n *\n * @param locale - Locale code\n * @param format - Display format\n * @returns Formatted locale string\n *\n * @example\n * ```typescript\n * formatLocaleDisplay('en', 'name') // 'English'\n * formatLocaleDisplay('fr', 'label') // 'FR'\n * formatLocaleDisplay('es', 'code') // 'es'\n * ```\n */\nexport function formatLocaleDisplay(\n locale: string,\n format: 'name' | 'label' | 'code' = 'name'\n): string {\n if (format === 'code') {\n return locale;\n }\n\n if (format === 'label') {\n try {\n const { getLocaleLabel } = require('./config');\n return getLocaleLabel(locale);\n } catch {\n return locale.toUpperCase();\n }\n }\n\n // format === 'name'\n return getLocaleAutonym(locale);\n}\n"],"mappings":"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","names":["getI18nConfig","connector","setLocaleCookie","getLocaleNames","getLocaleLabel"]}