@lastbrain/app 2.0.15 → 2.0.21

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 (257) hide show
  1. package/dist/app-shell/not-found.js +2 -2
  2. package/dist/components/LanguageSwitcher.d.ts +7 -0
  3. package/dist/components/LanguageSwitcher.d.ts.map +1 -0
  4. package/dist/components/LanguageSwitcher.js +62 -0
  5. package/dist/config/version.d.ts.map +1 -1
  6. package/dist/config/version.js +19 -21
  7. package/dist/i18n/LanguageProvider.d.ts +4 -0
  8. package/dist/i18n/LanguageProvider.d.ts.map +1 -0
  9. package/dist/i18n/LanguageProvider.js +6 -0
  10. package/dist/i18n/TranslationsScript.d.ts +8 -0
  11. package/dist/i18n/TranslationsScript.d.ts.map +1 -0
  12. package/dist/i18n/TranslationsScript.js +10 -0
  13. package/dist/i18n/cookies.d.ts +6 -0
  14. package/dist/i18n/cookies.d.ts.map +1 -0
  15. package/dist/i18n/cookies.js +24 -0
  16. package/dist/i18n/langHrefHelper.d.ts +36 -0
  17. package/dist/i18n/langHrefHelper.d.ts.map +1 -0
  18. package/dist/i18n/langHrefHelper.js +41 -0
  19. package/dist/i18n/server-helpers.d.ts +33 -0
  20. package/dist/i18n/server-helpers.d.ts.map +1 -0
  21. package/dist/i18n/server-helpers.js +39 -0
  22. package/dist/i18n/server-lang.d.ts +10 -0
  23. package/dist/i18n/server-lang.d.ts.map +1 -0
  24. package/dist/i18n/server-lang.js +42 -0
  25. package/dist/i18n/server.d.ts +10 -0
  26. package/dist/i18n/server.d.ts.map +1 -0
  27. package/dist/i18n/server.js +8 -0
  28. package/dist/i18n/types.d.ts +38 -0
  29. package/dist/i18n/types.d.ts.map +1 -0
  30. package/dist/i18n/types.js +4 -0
  31. package/dist/i18n/useLangRouter.d.ts +12 -0
  32. package/dist/i18n/useLangRouter.d.ts.map +1 -0
  33. package/dist/i18n/useLangRouter.js +18 -0
  34. package/dist/i18n/useLink.d.ts +34 -0
  35. package/dist/i18n/useLink.d.ts.map +1 -0
  36. package/dist/i18n/useLink.js +58 -0
  37. package/dist/i18n/useModuleTranslation.d.ts +11 -0
  38. package/dist/i18n/useModuleTranslation.d.ts.map +1 -0
  39. package/dist/i18n/useModuleTranslation.js +23 -0
  40. package/dist/index.d.ts +7 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +7 -0
  43. package/dist/layouts/AdminLayout.js +1 -1
  44. package/dist/layouts/AppProviders.d.ts +4 -1
  45. package/dist/layouts/AppProviders.d.ts.map +1 -1
  46. package/dist/layouts/AppProviders.js +18 -8
  47. package/dist/layouts/AuthLayout.js +1 -1
  48. package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -1
  49. package/dist/layouts/AuthLayoutWithSidebar.js +5 -3
  50. package/dist/layouts/PublicLayout.d.ts.map +1 -1
  51. package/dist/layouts/PublicLayout.js +1 -1
  52. package/dist/layouts/RootLayout.d.ts +4 -1
  53. package/dist/layouts/RootLayout.d.ts.map +1 -1
  54. package/dist/layouts/RootLayout.js +2 -2
  55. package/dist/scripts/i18n-build.d.ts +7 -0
  56. package/dist/scripts/i18n-build.d.ts.map +1 -0
  57. package/dist/scripts/i18n-build.js +100 -0
  58. package/dist/scripts/init-app.js +12 -12
  59. package/dist/scripts/module-build.d.ts.map +1 -1
  60. package/dist/scripts/module-build.js +390 -83
  61. package/dist/styles.css +1 -1
  62. package/dist/templates/DefaultDoc.d.ts.map +1 -1
  63. package/dist/templates/DefaultDoc.js +90 -2
  64. package/dist/templates/middleware-i18n.example.d.ts +16 -0
  65. package/dist/templates/middleware-i18n.example.d.ts.map +1 -0
  66. package/dist/templates/middleware-i18n.example.js +72 -0
  67. package/package.json +14 -3
  68. package/src/app-shell/not-found.tsx +2 -2
  69. package/src/components/LanguageSwitcher.tsx +156 -0
  70. package/src/config/version.ts +19 -21
  71. package/src/i18n/LanguageProvider.tsx +7 -0
  72. package/src/i18n/README_LANG_HELPERS.md +187 -0
  73. package/src/i18n/TranslationsScript.tsx +17 -0
  74. package/src/i18n/cookies.ts +24 -0
  75. package/src/i18n/langHrefHelper.ts +51 -0
  76. package/src/i18n/server-helpers.ts +48 -0
  77. package/src/i18n/server-lang.ts +51 -0
  78. package/src/i18n/server.ts +13 -0
  79. package/src/i18n/types.ts +39 -0
  80. package/src/i18n/useLangRouter.ts +21 -0
  81. package/src/i18n/useLink.ts +60 -0
  82. package/src/i18n/useModuleTranslation.ts +27 -0
  83. package/src/index.ts +20 -0
  84. package/src/layouts/AdminLayout.tsx +1 -1
  85. package/src/layouts/AppProviders.tsx +35 -16
  86. package/src/layouts/AuthLayout.tsx +1 -1
  87. package/src/layouts/AuthLayoutWithSidebar.tsx +5 -3
  88. package/src/layouts/PublicLayout.tsx +3 -1
  89. package/src/layouts/RootLayout.tsx +13 -6
  90. package/src/scripts/i18n-build.ts +122 -0
  91. package/src/scripts/init-app.ts +12 -12
  92. package/src/scripts/module-build.ts +483 -96
  93. package/src/templates/DefaultDoc.tsx +511 -1
  94. package/src/templates/middleware-i18n.example.ts +92 -0
  95. package/dist/app-shell/(admin)/dashboard/page.d.ts +0 -2
  96. package/dist/app-shell/(admin)/dashboard/page.d.ts.map +0 -1
  97. package/dist/app-shell/(admin)/dashboard/page.js +0 -5
  98. package/dist/app-shell/(admin)/page.d.ts +0 -2
  99. package/dist/app-shell/(admin)/page.d.ts.map +0 -1
  100. package/dist/app-shell/(admin)/page.js +0 -5
  101. package/dist/app-shell/(auth)/dashboard/page.d.ts +0 -2
  102. package/dist/app-shell/(auth)/dashboard/page.d.ts.map +0 -1
  103. package/dist/app-shell/(auth)/dashboard/page.js +0 -5
  104. package/dist/app-shell/(auth)/page.d.ts +0 -2
  105. package/dist/app-shell/(auth)/page.d.ts.map +0 -1
  106. package/dist/app-shell/(auth)/page.js +0 -5
  107. package/dist/components/TableStructure.d.ts +0 -8
  108. package/dist/components/TableStructure.d.ts.map +0 -1
  109. package/dist/components/TableStructure.js +0 -37
  110. package/dist/hooks/useNotificationsSimple.d.ts +0 -20
  111. package/dist/hooks/useNotificationsSimple.d.ts.map +0 -1
  112. package/dist/hooks/useNotificationsSimple.js +0 -37
  113. package/dist/module-build.d.ts +0 -2
  114. package/dist/module-build.d.ts.map +0 -1
  115. package/dist/module-build.js +0 -50
  116. package/dist/modules/index.d.ts +0 -3
  117. package/dist/modules/index.d.ts.map +0 -1
  118. package/dist/modules/index.js +0 -2
  119. package/dist/src/__tests__/module-registry.test.d.ts +0 -2
  120. package/dist/src/__tests__/module-registry.test.d.ts.map +0 -1
  121. package/dist/src/__tests__/module-registry.test.js +0 -53
  122. package/dist/src/app-shell/(admin)/layout.d.ts +0 -4
  123. package/dist/src/app-shell/(admin)/layout.d.ts.map +0 -1
  124. package/dist/src/app-shell/(admin)/layout.js +0 -5
  125. package/dist/src/app-shell/(auth)/layout.d.ts +0 -4
  126. package/dist/src/app-shell/(auth)/layout.d.ts.map +0 -1
  127. package/dist/src/app-shell/(auth)/layout.js +0 -5
  128. package/dist/src/app-shell/(public)/page.d.ts +0 -2
  129. package/dist/src/app-shell/(public)/page.d.ts.map +0 -1
  130. package/dist/src/app-shell/(public)/page.js +0 -5
  131. package/dist/src/app-shell/layout.d.ts +0 -3
  132. package/dist/src/app-shell/layout.d.ts.map +0 -1
  133. package/dist/src/app-shell/layout.js +0 -3
  134. package/dist/src/app-shell/not-found.d.ts +0 -2
  135. package/dist/src/app-shell/not-found.d.ts.map +0 -1
  136. package/dist/src/app-shell/not-found.js +0 -10
  137. package/dist/src/auth/authHelpers.d.ts +0 -7
  138. package/dist/src/auth/authHelpers.d.ts.map +0 -1
  139. package/dist/src/auth/authHelpers.js +0 -19
  140. package/dist/src/auth/useAuthSession.d.ts +0 -7
  141. package/dist/src/auth/useAuthSession.d.ts.map +0 -1
  142. package/dist/src/auth/useAuthSession.js +0 -49
  143. package/dist/src/cli.d.ts +0 -3
  144. package/dist/src/cli.d.ts.map +0 -1
  145. package/dist/src/cli.js +0 -143
  146. package/dist/src/components/NotificationContainer.d.ts +0 -2
  147. package/dist/src/components/NotificationContainer.d.ts.map +0 -1
  148. package/dist/src/components/NotificationContainer.js +0 -8
  149. package/dist/src/hooks/useNotifications.d.ts +0 -30
  150. package/dist/src/hooks/useNotifications.d.ts.map +0 -1
  151. package/dist/src/hooks/useNotifications.js +0 -165
  152. package/dist/src/index.d.ts +0 -22
  153. package/dist/src/index.d.ts.map +0 -1
  154. package/dist/src/index.js +0 -22
  155. package/dist/src/layouts/AdminLayout.d.ts +0 -4
  156. package/dist/src/layouts/AdminLayout.d.ts.map +0 -1
  157. package/dist/src/layouts/AdminLayout.js +0 -4
  158. package/dist/src/layouts/AdminLayoutWithSidebar.d.ts +0 -10
  159. package/dist/src/layouts/AdminLayoutWithSidebar.d.ts.map +0 -1
  160. package/dist/src/layouts/AdminLayoutWithSidebar.js +0 -62
  161. package/dist/src/layouts/AppProviders.d.ts +0 -27
  162. package/dist/src/layouts/AppProviders.d.ts.map +0 -1
  163. package/dist/src/layouts/AppProviders.js +0 -48
  164. package/dist/src/layouts/AuthLayout.d.ts +0 -4
  165. package/dist/src/layouts/AuthLayout.d.ts.map +0 -1
  166. package/dist/src/layouts/AuthLayout.js +0 -4
  167. package/dist/src/layouts/AuthLayoutWithSidebar.d.ts +0 -12
  168. package/dist/src/layouts/AuthLayoutWithSidebar.d.ts.map +0 -1
  169. package/dist/src/layouts/AuthLayoutWithSidebar.js +0 -60
  170. package/dist/src/layouts/PublicLayout.d.ts +0 -8
  171. package/dist/src/layouts/PublicLayout.d.ts.map +0 -1
  172. package/dist/src/layouts/PublicLayout.js +0 -6
  173. package/dist/src/layouts/PublicLayoutWithSidebar.d.ts +0 -9
  174. package/dist/src/layouts/PublicLayoutWithSidebar.d.ts.map +0 -1
  175. package/dist/src/layouts/PublicLayoutWithSidebar.js +0 -60
  176. package/dist/src/layouts/RootLayout.d.ts +0 -6
  177. package/dist/src/layouts/RootLayout.d.ts.map +0 -1
  178. package/dist/src/layouts/RootLayout.js +0 -9
  179. package/dist/src/modules/module-loader.d.ts +0 -5
  180. package/dist/src/modules/module-loader.d.ts.map +0 -1
  181. package/dist/src/modules/module-loader.js +0 -10
  182. package/dist/src/scripts/db-init.d.ts +0 -2
  183. package/dist/src/scripts/db-init.d.ts.map +0 -1
  184. package/dist/src/scripts/db-init.js +0 -300
  185. package/dist/src/scripts/db-migrations-sync.d.ts +0 -2
  186. package/dist/src/scripts/db-migrations-sync.d.ts.map +0 -1
  187. package/dist/src/scripts/db-migrations-sync.js +0 -84
  188. package/dist/src/scripts/dev-sync.d.ts +0 -2
  189. package/dist/src/scripts/dev-sync.d.ts.map +0 -1
  190. package/dist/src/scripts/dev-sync.js +0 -194
  191. package/dist/src/scripts/init-app.d.ts +0 -12
  192. package/dist/src/scripts/init-app.d.ts.map +0 -1
  193. package/dist/src/scripts/init-app.js +0 -2175
  194. package/dist/src/scripts/module-add.d.ts +0 -2
  195. package/dist/src/scripts/module-add.d.ts.map +0 -1
  196. package/dist/src/scripts/module-add.js +0 -232
  197. package/dist/src/scripts/module-build.d.ts +0 -2
  198. package/dist/src/scripts/module-build.d.ts.map +0 -1
  199. package/dist/src/scripts/module-build.js +0 -1280
  200. package/dist/src/scripts/module-create.d.ts +0 -28
  201. package/dist/src/scripts/module-create.d.ts.map +0 -1
  202. package/dist/src/scripts/module-create.js +0 -1429
  203. package/dist/src/scripts/module-delete.d.ts +0 -6
  204. package/dist/src/scripts/module-delete.d.ts.map +0 -1
  205. package/dist/src/scripts/module-delete.js +0 -147
  206. package/dist/src/scripts/module-list.d.ts +0 -2
  207. package/dist/src/scripts/module-list.d.ts.map +0 -1
  208. package/dist/src/scripts/module-list.js +0 -61
  209. package/dist/src/scripts/module-remove.d.ts +0 -2
  210. package/dist/src/scripts/module-remove.d.ts.map +0 -1
  211. package/dist/src/scripts/module-remove.js +0 -311
  212. package/dist/src/scripts/readme-build.d.ts +0 -2
  213. package/dist/src/scripts/readme-build.d.ts.map +0 -1
  214. package/dist/src/scripts/readme-build.js +0 -39
  215. package/dist/src/scripts/script-runner.d.ts +0 -5
  216. package/dist/src/scripts/script-runner.d.ts.map +0 -1
  217. package/dist/src/scripts/script-runner.js +0 -25
  218. package/dist/src/templates/AuthGuidePage.d.ts +0 -2
  219. package/dist/src/templates/AuthGuidePage.d.ts.map +0 -1
  220. package/dist/src/templates/AuthGuidePage.js +0 -9
  221. package/dist/src/templates/DefaultDoc.d.ts +0 -2
  222. package/dist/src/templates/DefaultDoc.d.ts.map +0 -1
  223. package/dist/src/templates/DefaultDoc.js +0 -240
  224. package/dist/src/templates/DocPage.d.ts +0 -17
  225. package/dist/src/templates/DocPage.d.ts.map +0 -1
  226. package/dist/src/templates/DocPage.js +0 -193
  227. package/dist/src/templates/DocsPageWithModules.d.ts +0 -2
  228. package/dist/src/templates/DocsPageWithModules.d.ts.map +0 -1
  229. package/dist/src/templates/DocsPageWithModules.js +0 -8
  230. package/dist/src/templates/MigrationsGuidePage.d.ts +0 -2
  231. package/dist/src/templates/MigrationsGuidePage.d.ts.map +0 -1
  232. package/dist/src/templates/MigrationsGuidePage.js +0 -11
  233. package/dist/src/templates/ModuleGuidePage.d.ts +0 -2
  234. package/dist/src/templates/ModuleGuidePage.d.ts.map +0 -1
  235. package/dist/src/templates/ModuleGuidePage.js +0 -14
  236. package/dist/src/templates/SimpleDocPage.d.ts +0 -2
  237. package/dist/src/templates/SimpleDocPage.d.ts.map +0 -1
  238. package/dist/src/templates/SimpleDocPage.js +0 -28
  239. package/dist/src/templates/SimpleHomePage.d.ts +0 -6
  240. package/dist/src/templates/SimpleHomePage.d.ts.map +0 -1
  241. package/dist/src/templates/SimpleHomePage.js +0 -7
  242. package/dist/src/types/menu.d.ts +0 -23
  243. package/dist/src/types/menu.d.ts.map +0 -1
  244. package/dist/src/types/menu.js +0 -1
  245. package/dist/templates/HomePage.d.ts +0 -6
  246. package/dist/templates/HomePage.d.ts.map +0 -1
  247. package/dist/templates/HomePage.js +0 -6
  248. package/dist/templates/components/AppAside.d.ts +0 -6
  249. package/dist/templates/components/AppAside.d.ts.map +0 -1
  250. package/dist/templates/components/AppAside.js +0 -9
  251. package/dist/templates/layouts/admin-layout.d.ts +0 -4
  252. package/dist/templates/layouts/admin-layout.d.ts.map +0 -1
  253. package/dist/templates/layouts/admin-layout.js +0 -6
  254. package/dist/templates/layouts/auth-layout.d.ts +0 -4
  255. package/dist/templates/layouts/auth-layout.d.ts.map +0 -1
  256. package/dist/templates/layouts/auth-layout.js +0 -6
  257. package/dist/templates/migrations/20201010100000_init.sql +0 -123
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { useLanguage } from "./LanguageProvider";
3
+ /**
4
+ * Helper pour transformer un URL avec le paramètre [lang]
5
+ * Utile pour les transformations statiques avant le rendu React
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const href = langHref("/settings", "fr"); // "/fr/settings"
10
+ * const href = langHref("/api/users", "en"); // "/api/users" (API non modifiée)
11
+ * ```
12
+ */
13
+ export function langHref(href, lang) {
14
+ const normalizedHref = String(href);
15
+ const isAbsolute = normalizedHref.startsWith("http");
16
+ const hasLangPrefix = normalizedHref.startsWith(`/${lang}/`);
17
+ if (isAbsolute) {
18
+ return normalizedHref;
19
+ }
20
+ else if (hasLangPrefix) {
21
+ return normalizedHref;
22
+ }
23
+ else if (normalizedHref === "/") {
24
+ return `/${lang}`;
25
+ }
26
+ else if (normalizedHref.startsWith("/api/")) {
27
+ return normalizedHref;
28
+ }
29
+ else {
30
+ return `/${lang}${normalizedHref}`;
31
+ }
32
+ }
33
+ /**
34
+ * Hook pour générer des URLs avec le paramètre [lang] injecté automatiquement
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * "use client";
39
+ * import { useLink } from "@lastbrain/app";
40
+ *
41
+ * export function MyComponent() {
42
+ * const link = useLink();
43
+ *
44
+ * return (
45
+ * <>
46
+ * <img src={link("/api/storage/avatar.jpg")} />
47
+ * <a href={link("/recipes")}>Recettes</a>
48
+ * </>
49
+ * );
50
+ * }
51
+ * ```
52
+ */
53
+ export function useLink() {
54
+ const { lang } = useLanguage();
55
+ return (href) => {
56
+ return langHref(href, lang);
57
+ };
58
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hook pour utiliser les traductions d'un module spécifique
3
+ * Préfixe automatiquement les clés avec le nom du module
4
+ *
5
+ * @example
6
+ * const t = useModuleTranslation("auth");
7
+ * t("hello") // -> cherche "module-auth.hello"
8
+ * t("hello", "Hello") // -> cherche "module-auth.hello", fallback à "Hello"
9
+ */
10
+ export declare function useModuleTranslation(moduleName: string): (key: string, defaultValue?: string) => string;
11
+ //# sourceMappingURL=useModuleTranslation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useModuleTranslation.d.ts","sourceRoot":"","sources":["../../src/i18n/useModuleTranslation.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,IAG7C,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,MAAM,CAUpD"}
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { useLanguage } from "./LanguageProvider";
3
+ /**
4
+ * Hook pour utiliser les traductions d'un module spécifique
5
+ * Préfixe automatiquement les clés avec le nom du module
6
+ *
7
+ * @example
8
+ * const t = useModuleTranslation("auth");
9
+ * t("hello") // -> cherche "module-auth.hello"
10
+ * t("hello", "Hello") // -> cherche "module-auth.hello", fallback à "Hello"
11
+ */
12
+ export function useModuleTranslation(moduleName) {
13
+ const { t: globalT } = useLanguage();
14
+ return (key, defaultValue) => {
15
+ const prefixedKey = `module-${moduleName}.${key}`;
16
+ const translation = globalT(prefixedKey);
17
+ // Si la traduction retourne exactement la clé (non trouvée), utiliser le fallback
18
+ if (translation === prefixedKey && defaultValue !== undefined) {
19
+ return defaultValue;
20
+ }
21
+ return translation;
22
+ };
23
+ }
package/dist/index.d.ts CHANGED
@@ -11,6 +11,13 @@ export { AuthLayoutWithSidebar, type AuthLayoutWithSidebarProps, type MenuIgnore
11
11
  export { AdminLayout } from "./layouts/AdminLayout";
12
12
  export { AdminLayoutWithSidebar } from "./layouts/AdminLayoutWithSidebar";
13
13
  export { getModuleConfigs } from "./modules/module-loader";
14
+ export { LanguageProvider, useLanguage, type Language, } from "./i18n/LanguageProvider";
15
+ export { useLink, langHref } from "./i18n/useLink";
16
+ export { useLangRouter } from "./i18n/useLangRouter";
17
+ export { useModuleTranslation } from "@lastbrain/core";
18
+ export { transformLangHrefs, transformLangHref } from "./i18n/langHrefHelper";
19
+ export { LanguageSwitcher } from "./components/LanguageSwitcher";
20
+ export type { TranslationKey, Translations, I18nConfig, LangParams, LangIdParams, ModuleTranslations, } from "./i18n/types";
14
21
  export { AppAside } from "@lastbrain/ui";
15
22
  export type { AppAsideMenuItem, AppAsideMenuConfig } from "@lastbrain/ui";
16
23
  export { SimpleHomePage } from "./templates/SimpleHomePage";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,gBAAgB,IAAI,uBAAuB,GAC5C,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,gBAAgB,IAAI,uBAAuB,GAC5C,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,KAAK,QAAQ,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,13 @@ export { AuthLayoutWithSidebar, } from "./layouts/AuthLayoutWithSidebar";
11
11
  export { AdminLayout } from "./layouts/AdminLayout";
12
12
  export { AdminLayoutWithSidebar } from "./layouts/AdminLayoutWithSidebar";
13
13
  export { getModuleConfigs } from "./modules/module-loader";
14
+ // i18n
15
+ export { LanguageProvider, useLanguage, } from "./i18n/LanguageProvider";
16
+ export { useLink, langHref } from "./i18n/useLink";
17
+ export { useLangRouter } from "./i18n/useLangRouter";
18
+ export { useModuleTranslation } from "@lastbrain/core";
19
+ export { transformLangHrefs, transformLangHref } from "./i18n/langHrefHelper";
20
+ export { LanguageSwitcher } from "./components/LanguageSwitcher";
14
21
  // Components
15
22
  export { AppAside } from "@lastbrain/ui";
16
23
  // Templates de pages (starter + docs)
@@ -1,4 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  export function AdminLayout({ children }) {
3
- return _jsx("div", { className: "max-w-screen pt-18 px-2 md:px-5", children: children });
3
+ return _jsx("div", { className: "max-w-screen px-2 md:px-5", children: children });
4
4
  }
@@ -1,3 +1,4 @@
1
+ import { type Language } from "../i18n/LanguageProvider";
1
2
  import type { User } from "@supabase/supabase-js";
2
3
  import type { ModuleRealtimeConfig } from "@lastbrain/core";
3
4
  import type { NotificationsData } from "../hooks/useNotifications";
@@ -20,8 +21,10 @@ export declare function useAuth(): {
20
21
  loading: boolean;
21
22
  isSuperAdmin: boolean;
22
23
  };
23
- export declare function AppProviders({ children, realtimeConfig, }: {
24
+ export declare function AppProviders({ children, realtimeConfig, lang, translations, }: {
24
25
  children: React.ReactNode;
25
26
  realtimeConfig?: ModuleRealtimeConfig[];
27
+ lang?: Language;
28
+ translations?: Record<string, string>;
26
29
  }): import("react/jsx-runtime").JSX.Element;
27
30
  //# sourceMappingURL=AppProviders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layouts/AppProviders.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAuCnE,wBAAgB,UAAU,kDAEzB;AAED,wBAAgB,gBAAgB;UAvCxB,iBAAiB;aACd,OAAO;WACT,MAAM,GAAG,IAAI;aACX,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;mBAC1B,MAAM,OAAO,CAAC,IAAI,CAAC;wBACd,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;aACxC,OAAO;eACL,OAAO;oBACF,OAAO;yBACF,OAAO;EA+B7B;AAED,wBAAgB,OAAO;UAjBf,IAAI,GAAG,IAAI;aACR,OAAO;kBACF,OAAO;EAiBtB;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,cAAmB,GACpB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACzC,2CA4BA"}
1
+ {"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layouts/AppProviders.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAuCnE,wBAAgB,UAAU,kDAEzB;AAED,wBAAgB,gBAAgB;UAvCxB,iBAAiB;aACd,OAAO;WACT,MAAM,GAAG,IAAI;aACX,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;mBAC1B,MAAM,OAAO,CAAC,IAAI,CAAC;wBACd,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;aACxC,OAAO;eACL,OAAO;oBACF,OAAO;yBACF,OAAO;EA+B7B;AAED,wBAAgB,OAAO;UAjBf,IAAI,GAAG,IAAI;aACR,OAAO;kBACF,OAAO;EAiBtB;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,cAAmB,EACnB,IAAW,EACX,YAAiB,GAClB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC,2CA0CA"}
@@ -2,10 +2,11 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { createContext, useContext, useMemo } from "react";
4
4
  import { getModuleConfigs } from "../modules/module-loader";
5
- import { ToastProvider } from "@lastbrain/ui";
5
+ import { ToastProvider, AppLinkProvider } from "@lastbrain/ui";
6
6
  import { RealtimeProvider } from "@lastbrain/core";
7
7
  import { useAuthSession } from "../auth/useAuthSession";
8
8
  import { useNotifications as useNotificationsHook } from "../hooks/useNotifications";
9
+ import { LanguageProvider } from "../i18n/LanguageProvider";
9
10
  const ModuleContext = createContext(getModuleConfigs());
10
11
  const NotificationContext = createContext({
11
12
  data: { notifications: [], unreadCount: 0 },
@@ -34,15 +35,24 @@ export function useNotifications() {
34
35
  export function useAuth() {
35
36
  return useContext(AuthContext);
36
37
  }
37
- export function AppProviders({ children, realtimeConfig = [], }) {
38
+ export function AppProviders({ children, realtimeConfig = [], lang = "fr", translations = {}, }) {
38
39
  const modules = useMemo(() => getModuleConfigs(), []);
39
40
  const { user, loading: authLoading, isSuperAdmin } = useAuthSession();
40
41
  // Hook de notifications seulement quand l'auth est prête
41
42
  const notificationsData = useNotificationsHook(user);
42
- const authValue = useMemo(() => ({ user, loading: authLoading, isSuperAdmin }), [user, authLoading, isSuperAdmin]); // const handleLogout = async () => {
43
- // const { signOut } = await import("../auth/authHelpers.js");
44
- // await signOut();
45
- // router.push("/auth/signin");
46
- // };
47
- return (_jsx(AuthContext.Provider, { value: authValue, children: _jsx(ModuleContext.Provider, { value: modules, children: _jsx(NotificationContext.Provider, { value: notificationsData, children: _jsxs(RealtimeProvider, { userId: user?.id, config: realtimeConfig, children: [children, _jsx(ToastProvider, { placement: "bottom-right", toastOffset: 5 })] }) }) }) }));
43
+ const authValue = useMemo(() => ({ user, loading: authLoading, isSuperAdmin }), [user, authLoading, isSuperAdmin]);
44
+ // Mémoriser les traductions pour éviter les changements
45
+ const memoizedTranslations = useMemo(() => {
46
+ // Si des traductions non-vides sont fournies, les utiliser
47
+ if (Object.keys(translations).length > 0) {
48
+ return translations;
49
+ }
50
+ // Sinon, tenter de récupérer celles du script injecté côté client
51
+ if (typeof window !== "undefined" && window.__TRANSLATIONS__) {
52
+ return window.__TRANSLATIONS__;
53
+ }
54
+ // Ne retourner un objet vide que si vraiment rien n'est disponible
55
+ return {};
56
+ }, [translations]);
57
+ return (_jsx(LanguageProvider, { initialLang: lang, translations: memoizedTranslations, children: _jsx(AppLinkProvider, { lang: lang || "fr", children: _jsx(AuthContext.Provider, { value: authValue, children: _jsx(ModuleContext.Provider, { value: modules, children: _jsx(NotificationContext.Provider, { value: notificationsData, children: _jsxs(RealtimeProvider, { userId: user?.id, config: realtimeConfig, children: [children, _jsx(ToastProvider, { placement: "bottom-right", toastOffset: 5 })] }) }) }) }) }) }));
48
58
  }
@@ -1,4 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  export function AuthLayout({ children }) {
3
- return _jsx("div", { className: "pt-18 px-2 md:px-5 ", children: children });
3
+ return _jsx("div", { className: "pt-4 px-2 md:px-5 max-w-screen", children: children });
4
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG7D,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AAExC,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,UAAU,EACV,SAAc,EACd,WAAW,EACX,UAAU,GACX,EAAE,0BAA0B,2CAiG5B"}
1
+ {"version":3,"file":"AuthLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG7D,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AAExC,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,UAAU,EACV,SAAc,EACd,WAAW,EACX,UAAU,GACX,EAAE,0BAA0B,2CAkG5B"}
@@ -3,9 +3,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { AuthLayout } from "./AuthLayout";
4
4
  import { AppAside, AppAsideSkeleton, } from "@lastbrain/ui";
5
5
  import { useAuthSession } from "../auth/useAuthSession";
6
+ import { usePathname } from "next/navigation";
6
7
  import { useEffect, useState } from "react";
7
8
  export function AuthLayoutWithSidebar({ children, menuConfig, className = "", menuIgnored, menuCustom, }) {
8
9
  const { isSuperAdmin, loading, user } = useAuthSession();
10
+ const pathname = usePathname();
9
11
  const [isCollapsed, setIsCollapsed] = useState(() => {
10
12
  if (typeof window !== "undefined") {
11
13
  const savedState = localStorage.getItem("aside-collapsed");
@@ -40,8 +42,8 @@ export function AuthLayoutWithSidebar({ children, menuConfig, className = "", me
40
42
  };
41
43
  }
42
44
  }, []);
43
- // Pour la section auth, isAdminSection sera false
44
- const isAdminSection = false;
45
+ // Détecter si on est dans la section auth pour le skeleton (avec support [lang])
46
+ const isAuthSection = pathname.includes("/auth");
45
47
  // Créer un menuConfig sûr avec des valeurs par défaut
46
48
  const safeMenuConfig = {
47
49
  public: menuConfig?.public || [],
@@ -56,5 +58,5 @@ export function AuthLayoutWithSidebar({ children, menuConfig, className = "", me
56
58
  safeMenuConfig.public.length > 0);
57
59
  // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
58
60
  const shouldShowSkeleton = loading || !hasValidMenuConfig;
59
- return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className, ...(menuIgnored ? { menuIgnored } : {}), ...(menuCustom ? { menuCustom } : {}) })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AuthLayout, { children: children }) })] }));
61
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAuthSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className, ...(menuIgnored ? { menuIgnored } : {}), ...(menuCustom ? { menuCustom } : {}) })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AuthLayout, { children: children }) })] }));
60
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PublicLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,iBAAiB,2CAOzE"}
1
+ {"version":3,"file":"PublicLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,iBAAiB,2CASzE"}
@@ -2,5 +2,5 @@
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Footer } from "@lastbrain/ui";
4
4
  export function PublicLayout({ children, footerConfig }) {
5
- return (_jsxs(_Fragment, { children: [_jsx("section", { className: "pt-16 min-h-[calc(100vh)]", children: children }), footerConfig && _jsx(Footer, { config: footerConfig })] }));
5
+ return (_jsxs(_Fragment, { children: [_jsx("section", { className: "pt-16 min-h-[calc(100vh)] max-w-screen", children: children }), footerConfig && _jsx(Footer, { config: footerConfig })] }));
6
6
  }
@@ -1,6 +1,9 @@
1
1
  import type { ModuleRealtimeConfig } from "@lastbrain/core";
2
- export declare function RootLayout({ children, realtimeConfig, }: {
2
+ import type { Language } from "../i18n/LanguageProvider";
3
+ export declare function RootLayout({ children, realtimeConfig, lang, translations, }: {
3
4
  children: React.ReactNode;
4
5
  realtimeConfig?: ModuleRealtimeConfig[];
6
+ lang?: Language;
7
+ translations?: Record<string, string>;
5
8
  }): import("react/jsx-runtime").JSX.Element;
6
9
  //# sourceMappingURL=RootLayout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RootLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/RootLayout.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI5D,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,cAAmB,GACpB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACzC,2CAmBA"}
1
+ {"version":3,"file":"RootLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/RootLayout.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAIzD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,cAAmB,EACnB,IAAW,EACX,YAAiB,GAClB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC,2CAqBA"}
@@ -4,6 +4,6 @@ import { ThemeProvider } from "next-themes";
4
4
  import { AppProviders } from "./AppProviders";
5
5
  // Note: L'app Next.js doit importer son propre globals.css dans son layout
6
6
  // Note: La configuration realtime doit être fournie par l'app qui utilise ce layout
7
- export function RootLayout({ children, realtimeConfig = [], }) {
8
- return (_jsx("html", { lang: "fr", suppressHydrationWarning: true, children: _jsx("body", { className: "min-h-screen", children: _jsx(ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, storageKey: "lastbrain-theme", children: _jsx(AppProviders, { realtimeConfig: realtimeConfig, children: _jsx("div", { className: " min-h-screen bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-white", children: children }) }) }) }) }));
7
+ export function RootLayout({ children, realtimeConfig = [], lang = "fr", translations = {}, }) {
8
+ return (_jsx("html", { lang: lang, suppressHydrationWarning: true, children: _jsx("body", { className: "min-h-screen max-w-screen", children: _jsx(ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, storageKey: "lastbrain-theme", children: _jsx(AppProviders, { realtimeConfig: realtimeConfig, lang: lang, translations: translations, children: _jsx("div", { className: " min-h-screen pt-12", children: children }) }) }) }) }));
9
9
  }
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Script pour collecter tous les fichiers i18n des modules et les concaténer
4
+ * dans le dossier i18n de l'application
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=i18n-build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n-build.d.ts","sourceRoot":"","sources":["../../src/scripts/i18n-build.ts"],"names":[],"mappings":";AACA;;;GAGG"}
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Script pour collecter tous les fichiers i18n des modules et les concaténer
4
+ * dans le dossier i18n de l'application
5
+ */
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ const projectRoot = process.env.PROJECT_ROOT || process.cwd();
9
+ const monorepoRoot = projectRoot.includes("/apps/")
10
+ ? path.resolve(projectRoot, "..", "..")
11
+ : projectRoot;
12
+ const packagesDir = path.join(monorepoRoot, "packages");
13
+ const appI18nDir = path.join(projectRoot, "i18n");
14
+ /**
15
+ * Collecte tous les fichiers i18n des modules
16
+ */
17
+ async function collectTranslations() {
18
+ const translations = {
19
+ fr: {},
20
+ en: {},
21
+ };
22
+ try {
23
+ // Importer glob dynamiquement
24
+ const { glob } = await import("glob");
25
+ // Rechercher tous les fichiers i18n dans packages/**/src/i18n/*.json
26
+ const pattern = path.join(packagesDir, "**/src/i18n/*.json");
27
+ const files = await glob(pattern, {
28
+ ignore: ["**/node_modules/**", "**/dist/**"],
29
+ });
30
+ console.log(`\n🔍 Found ${files.length} i18n files\n`);
31
+ for (const file of files) {
32
+ const fileName = path.basename(file, ".json");
33
+ const lang = fileName; // fr.json -> fr, en.json -> en
34
+ if (!translations[lang]) {
35
+ translations[lang] = {};
36
+ }
37
+ try {
38
+ const content = JSON.parse(fs.readFileSync(file, "utf-8"));
39
+ const moduleName = extractModuleName(file);
40
+ console.log(` ✓ ${moduleName} (${lang})`);
41
+ // Préfixer les clés avec le nom du module pour éviter les collisions
42
+ for (const [key, value] of Object.entries(content)) {
43
+ const prefixedKey = `${moduleName}.${key}`;
44
+ translations[lang][prefixedKey] = value;
45
+ }
46
+ }
47
+ catch (error) {
48
+ console.warn(` ⚠️ Error reading ${file}:`, error);
49
+ }
50
+ }
51
+ }
52
+ catch (error) {
53
+ console.error("❌ Error collecting translations:", error);
54
+ }
55
+ return translations;
56
+ }
57
+ /**
58
+ * Extrait le nom du module depuis le chemin du fichier
59
+ */
60
+ function extractModuleName(filePath) {
61
+ // packages/module-auth/src/i18n/fr.json -> module-auth
62
+ const parts = filePath.split(path.sep);
63
+ const packagesIndex = parts.indexOf("packages");
64
+ if (packagesIndex !== -1 && packagesIndex < parts.length - 1) {
65
+ return parts[packagesIndex + 1];
66
+ }
67
+ return "unknown";
68
+ }
69
+ /**
70
+ * Écrit les traductions concaténées dans le dossier i18n de l'app
71
+ */
72
+ function writeTranslations(translations) {
73
+ // Créer le dossier i18n s'il n'existe pas
74
+ if (!fs.existsSync(appI18nDir)) {
75
+ fs.mkdirSync(appI18nDir, { recursive: true });
76
+ }
77
+ for (const [lang, content] of Object.entries(translations)) {
78
+ const filePath = path.join(appI18nDir, `${lang}.json`);
79
+ fs.writeFileSync(filePath, JSON.stringify(content, null, 2), "utf-8");
80
+ const keyCount = Object.keys(content).length;
81
+ console.log(`\n✅ Generated ${filePath} (${keyCount} keys)`);
82
+ }
83
+ }
84
+ /**
85
+ * Point d'entrée principal
86
+ */
87
+ async function buildI18n() {
88
+ console.log("🌍 Building i18n files...\n");
89
+ console.log(`📁 Project root: ${projectRoot}`);
90
+ console.log(`📦 Packages dir: ${packagesDir}`);
91
+ console.log(`🎯 App i18n dir: ${appI18nDir}\n`);
92
+ const translations = await collectTranslations();
93
+ writeTranslations(translations);
94
+ console.log("\n✨ i18n build complete!\n");
95
+ }
96
+ // Exécuter
97
+ buildI18n().catch((error) => {
98
+ console.error("\n❌ Error:", error);
99
+ process.exit(1);
100
+ });
@@ -368,19 +368,18 @@ async function createNextStructure(targetDir, force, useHeroUI, withAuth) {
368
368
  if (!fs.existsSync(layoutDest) || force) {
369
369
  let layoutContent = "";
370
370
  if (useHeroUI) {
371
- // Layout avec HeroUI - Server Component
371
+ // Layout avec HeroUI - Server Component (juste HTML, providers gérés par [lang]/layout.tsx)
372
372
  layoutContent = `// GENERATED BY LASTBRAIN APP-SHELL
373
373
  // Server Component pour permettre le SSR des pages enfants
374
374
 
375
375
  import "../styles/globals.css";
376
- import { ClientLayout } from "../components/ClientLayout";
377
376
  import type { PropsWithChildren } from "react";
378
377
 
379
378
  export default function RootLayout({ children }: PropsWithChildren<{}>) {
380
379
  return (
381
380
  <html lang="fr" suppressHydrationWarning>
382
381
  <body className="min-h-screen">
383
- <ClientLayout>{children}</ClientLayout>
382
+ {children}
384
383
  </body>
385
384
  </html>
386
385
  );
@@ -388,19 +387,18 @@ export default function RootLayout({ children }: PropsWithChildren<{}>) {
388
387
  `;
389
388
  }
390
389
  else {
391
- // Layout Tailwind CSS uniquement - Server Component
390
+ // Layout Tailwind CSS uniquement - Server Component (juste HTML, providers gérés par [lang]/layout.tsx)
392
391
  layoutContent = `// GENERATED BY LASTBRAIN APP-SHELL
393
392
  // Server Component pour permettre le SSR des pages enfants
394
393
 
395
394
  import "../styles/globals.css";
396
- import { ClientLayout } from "../components/ClientLayout";
397
395
  import type { PropsWithChildren } from "react";
398
396
 
399
397
  export default function RootLayout({ children }: PropsWithChildren<{}>) {
400
398
  return (
401
399
  <html lang="fr" suppressHydrationWarning>
402
400
  <body className="min-h-screen">
403
- <ClientLayout>{children}</ClientLayout>
401
+ {children}
404
402
  </body>
405
403
  </html>
406
404
  );
@@ -424,7 +422,7 @@ export default function RootLayout({ children }: PropsWithChildren<{}>) {
424
422
  console.log(chalk.green("✓ styles/globals.css créé"));
425
423
  }
426
424
  // Créer la page d'accueil publique (racine)
427
- const homePagePath = path.join(appDir, "page.tsx");
425
+ const homePagePath = path.join(appDir, "[lang]", "page.tsx");
428
426
  if (!fs.existsSync(homePagePath) || force) {
429
427
  const homePageContent = `// GENERATED BY LASTBRAIN APP-SHELL
430
428
 
@@ -449,10 +447,10 @@ export default function RootPage() {
449
447
  if (!fs.existsSync(notFoundPath) || force) {
450
448
  const notFoundContent = `"use client";
451
449
  import { Button } from "@lastbrain/ui";
452
- import { useRouter } from "next/navigation";
450
+ import { useLocalizedRouter } from "@lastbrain/core";
453
451
 
454
452
  export default function NotFound() {
455
- const router = useRouter();
453
+ const router = useLocalizedRouter();
456
454
  return (
457
455
  <div className="flex min-h-screen items-center justify-center bg-background">
458
456
  <div className="mx-auto max-w-md text-center">
@@ -510,7 +508,7 @@ import { AppHeader } from "./AppHeader";
510
508
  import type { ReactNode } from "react";
511
509
 
512
510
  export function ClientLayout({ children }: { children: ReactNode }) {
513
- const router = useRouter();
511
+ const router = useLocalizedRouter();
514
512
 
515
513
  return (
516
514
  <HeroUIProvider navigate={router.push}>
@@ -686,7 +684,7 @@ import { Header, type MenuItem } from "@lastbrain/ui";
686
684
  import { menuConfig } from "../config/menu";
687
685
  import { supabaseBrowserClient } from "@lastbrain/core";
688
686
  import { useRouter } from "next/navigation";
689
- import { useAuthSession, useNotificationsContext } from "@lastbrain/app";
687
+ import { useAuthSession, useNotificationsContext,LanguageSwitcher } from "@lastbrain/app";
690
688
  import { useState, useEffect } from "react";
691
689
 
692
690
  interface MenuIgnored {
@@ -695,7 +693,7 @@ interface MenuIgnored {
695
693
  }
696
694
 
697
695
  export function AppHeader() {
698
- const router = useRouter();
696
+ const router = useLocalizedRouter();
699
697
  const { user, isSuperAdmin } = useAuthSession();
700
698
  const { data, loading, markAsRead, markAllAsRead, deleteNotification } =
701
699
  useNotificationsContext();
@@ -757,6 +755,8 @@ export function AppHeader() {
757
755
  {...(menuIgnored ? { menuIgnored } : {})}
758
756
  {...(menuCustom ? { menuCustom } : {})}
759
757
  {...{ isLoadingMenus: isLoading }}
758
+ languageSwitcher={<LanguageSwitcher variant="minimal" />}
759
+
760
760
  />
761
761
  );
762
762
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AAi6CA,wBAAsB,cAAc,kBA+FnC"}
1
+ {"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AAqxDA,wBAAsB,cAAc,kBA8GnC"}