@lastbrain/app 2.0.23 → 2.0.31
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.
- package/dist/components/LanguageSwitcher.d.ts +3 -1
- package/dist/components/LanguageSwitcher.d.ts.map +1 -1
- package/dist/components/LanguageSwitcher.js +50 -21
- package/dist/config/version.js +19 -19
- package/dist/i18n/server-lang.d.ts +1 -1
- package/dist/i18n/server-lang.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +1 -1
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/layouts/AppProviders.d.ts +3 -1
- package/dist/layouts/AppProviders.d.ts.map +1 -1
- package/dist/layouts/AppProviders.js +2 -2
- package/dist/scripts/init-app.d.ts.map +1 -1
- package/dist/scripts/init-app.js +46 -4
- package/dist/scripts/module-build.d.ts.map +1 -1
- package/dist/scripts/module-build.js +407 -17
- package/package.json +23 -25
- package/src/components/LanguageSwitcher.tsx +85 -52
- package/src/config/version.ts +19 -19
- package/src/i18n/server-lang.ts +2 -1
- package/src/i18n/types.ts +2 -1
- package/src/layouts/AppProviders.tsx +8 -1
- package/src/scripts/init-app.ts +62 -4
- package/src/scripts/module-build.ts +495 -17
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
interface LanguageSwitcherProps {
|
|
2
2
|
variant?: "default" | "minimal";
|
|
3
3
|
className?: string;
|
|
4
|
+
availableLanguages?: string[];
|
|
5
|
+
localeMap?: Record<string, string>;
|
|
4
6
|
}
|
|
5
|
-
export declare function LanguageSwitcher({ variant, className, }: LanguageSwitcherProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function LanguageSwitcher({ variant, className, availableLanguages, localeMap, }: LanguageSwitcherProps): import("react/jsx-runtime").JSX.Element;
|
|
6
8
|
export {};
|
|
7
9
|
//# sourceMappingURL=LanguageSwitcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LanguageSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/LanguageSwitcher.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LanguageSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/LanguageSwitcher.tsx"],"names":[],"mappings":"AAcA,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAmB,EACnB,SAAc,EACd,kBAAiC,EACjC,SAAwC,GACzC,EAAE,qBAAqB,2CAkKvB"}
|
|
@@ -1,35 +1,56 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
4
5
|
import { useLanguage } from "../i18n/LanguageProvider";
|
|
5
6
|
import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Spinner, } from "@lastbrain/ui";
|
|
6
|
-
export function LanguageSwitcher({ variant = "default", className = "", }) {
|
|
7
|
-
const { lang, setLang } = useLanguage();
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
en: "",
|
|
11
|
-
});
|
|
7
|
+
export function LanguageSwitcher({ variant = "default", className = "", availableLanguages = ["fr", "en"], localeMap = { fr: "fr_FR", en: "en_US" }, }) {
|
|
8
|
+
const { lang, setLang: setLangFromContext } = useLanguage();
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const [flagUrls, setFlagUrls] = useState({});
|
|
12
11
|
const [loading, setLoading] = useState(false);
|
|
13
12
|
const [isHydrated, setIsHydrated] = useState(false);
|
|
14
13
|
// Marquer l'hydration comme terminée
|
|
15
14
|
useEffect(() => {
|
|
16
15
|
setIsHydrated(true);
|
|
17
16
|
}, []);
|
|
17
|
+
// Fonction pour changer la langue avec redirection correcte
|
|
18
|
+
const handleLanguageChange = (newLang) => {
|
|
19
|
+
const currentPath = window.location.pathname;
|
|
20
|
+
// Extraire les segments du chemin
|
|
21
|
+
const segments = currentPath.split("/").filter(Boolean);
|
|
22
|
+
// Nettoyer TOUS les codes langue (2 lettres) du début du path
|
|
23
|
+
// Ça corrige les paths corrompus comme /en/es/recipes
|
|
24
|
+
while (segments.length > 0 && /^[a-z]{2}$/.test(segments[0])) {
|
|
25
|
+
segments.shift(); // Enlever le premier segment s'il est une langue
|
|
26
|
+
}
|
|
27
|
+
// Reconstruire le path avec la nouvelle langue
|
|
28
|
+
const pathWithoutLang = segments.length > 0 ? "/" + segments.join("/") : "";
|
|
29
|
+
const newPath = `/${newLang}${pathWithoutLang}`;
|
|
30
|
+
// Naviguer directement - le LanguageProvider lira la nouvelle langue depuis l'URL
|
|
31
|
+
window.location.href = newPath;
|
|
32
|
+
};
|
|
18
33
|
useEffect(() => {
|
|
19
34
|
let canceled = false;
|
|
20
35
|
const objectUrls = [];
|
|
21
36
|
async function loadFlags() {
|
|
22
37
|
setLoading(true);
|
|
23
38
|
try {
|
|
24
|
-
const entries = await Promise.all(
|
|
25
|
-
const apiCode = code === "fr" ? "fr" : "gb";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
const entries = await Promise.all(availableLanguages.map(async (code) => {
|
|
40
|
+
const apiCode = code === "fr" ? "fr" : code === "en" ? "gb" : code;
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(`https://flagcdn.com/${apiCode}.svg`);
|
|
43
|
+
if (!response.ok)
|
|
44
|
+
throw new Error(`Flag fetch failed: ${code}`);
|
|
45
|
+
const blob = await response.blob();
|
|
46
|
+
const url = URL.createObjectURL(blob);
|
|
47
|
+
objectUrls.push(url);
|
|
48
|
+
return [code, url];
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Fallback to direct URL if fetch fails
|
|
52
|
+
return [code, `https://flagcdn.com/${apiCode}.svg`];
|
|
53
|
+
}
|
|
33
54
|
}));
|
|
34
55
|
if (!canceled) {
|
|
35
56
|
setFlagUrls(Object.fromEntries(entries));
|
|
@@ -37,10 +58,13 @@ export function LanguageSwitcher({ variant = "default", className = "", }) {
|
|
|
37
58
|
}
|
|
38
59
|
catch (_err) {
|
|
39
60
|
if (!canceled) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
61
|
+
// Fallback: create a map with direct URLs
|
|
62
|
+
const fallbackUrls = {};
|
|
63
|
+
availableLanguages.forEach((code) => {
|
|
64
|
+
const apiCode = code === "fr" ? "fr" : code === "en" ? "gb" : code;
|
|
65
|
+
fallbackUrls[code] = `https://flagcdn.com/${apiCode}.svg`;
|
|
43
66
|
});
|
|
67
|
+
setFlagUrls(fallbackUrls);
|
|
44
68
|
}
|
|
45
69
|
}
|
|
46
70
|
finally {
|
|
@@ -53,10 +77,15 @@ export function LanguageSwitcher({ variant = "default", className = "", }) {
|
|
|
53
77
|
canceled = true;
|
|
54
78
|
objectUrls.forEach((url) => URL.revokeObjectURL(url));
|
|
55
79
|
};
|
|
56
|
-
}, []);
|
|
80
|
+
}, [availableLanguages]);
|
|
57
81
|
const renderFlag = (code) => (_jsx("span", { className: "inline-flex items-center gap-2", children: flagUrls[code] ? (_jsx("img", { src: flagUrls[code], alt: code === "fr" ? "Drapeau français" : "Flag English", className: "h-4 w-6 rounded-sm border border-slate-200 object-cover" })) : isHydrated ? (_jsx("span", { className: "inline-flex h-4 w-6 items-center justify-center rounded-sm bg-slate-200 text-[10px] font-semibold text-slate-600", children: code.toUpperCase() })) : null }));
|
|
82
|
+
// SSR placeholder - ne pas rendre le Dropdown avant l'hydration
|
|
83
|
+
// pour éviter les mismatches d'ID React Aria
|
|
84
|
+
if (!isHydrated) {
|
|
85
|
+
return (_jsx("span", { className: "inline-flex h-4 w-6 items-center justify-center rounded-sm bg-slate-200 text-[10px] font-semibold text-slate-600", children: lang.toUpperCase() }));
|
|
86
|
+
}
|
|
58
87
|
if (variant === "minimal") {
|
|
59
|
-
return (_jsxs(Dropdown, { size: "sm", className: "px-0 m-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: renderFlag(lang) }),
|
|
88
|
+
return (_jsxs(Dropdown, { size: "sm", className: "px-0 m-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: renderFlag(lang) }), _jsx(DropdownMenu, { children: availableLanguages.map((code) => (_jsxs(DropdownItem, { onPress: () => handleLanguageChange(code), startContent: renderFlag(code), className: lang === code ? "bg-primary/10" : "", children: [code === "fr" ? "Français" : code === "en" ? "English" : code, isHydrated && lang === code && " ✓"] }, code))) })] }));
|
|
60
89
|
}
|
|
61
|
-
return (_jsxs(Dropdown, { size: "sm", className: "px-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: _jsx(Button, { variant: "light", size: "sm", className: "px-0 m-0", startContent: renderFlag(lang), endContent: loading ? _jsx(Spinner, { size: "sm" }) : null }) }),
|
|
90
|
+
return (_jsxs(Dropdown, { size: "sm", className: "px-0", children: [_jsx(DropdownTrigger, { className: "px-0 m-0", children: _jsx(Button, { variant: "light", size: "sm", className: "px-0 m-0", "aria-label": `Switch language (current: ${lang})`, startContent: renderFlag(lang), endContent: loading ? _jsx(Spinner, { size: "sm" }) : null }) }), _jsx(DropdownMenu, { children: availableLanguages.map((code) => (_jsxs(DropdownItem, { onPress: () => handleLanguageChange(code), className: lang === code ? "bg-primary/10" : "", children: [renderFlag(code), " ", code === "fr" ? "Français" : code === "en" ? "English" : code, isHydrated && lang === code && " ✓"] }, code))) })] }));
|
|
62
91
|
}
|
package/dist/config/version.js
CHANGED
|
@@ -4,23 +4,23 @@
|
|
|
4
4
|
* Mise à jour automatique lors de pnpm version:patch/minor/major
|
|
5
5
|
*/
|
|
6
6
|
export const PACKAGE_VERSIONS = {
|
|
7
|
-
"@lastbrain-labs/module-billing-pro": "^2.0.
|
|
8
|
-
"@lastbrain-labs/module-cj-analyzer-pro": "^0.1.
|
|
9
|
-
"@lastbrain-labs/module-core-cart-pro": "^2.0.
|
|
10
|
-
"@lastbrain-labs/module-core-commerce-pro": "^2.0.
|
|
11
|
-
"@lastbrain-labs/module-core-order-pro": "^2.0.
|
|
12
|
-
"@lastbrain-labs/module-core-payment-pro": "^2.0.
|
|
13
|
-
"@lastbrain-labs/module-core-product-pro": "^2.0.
|
|
14
|
-
"@lastbrain-labs/module-recipes-pro": "^2.0.
|
|
15
|
-
"@lastbrain-labs/module-shop-pro": "^0.1.
|
|
16
|
-
"@lastbrain/app": "^2.0.
|
|
17
|
-
"@lastbrain/core": "^2.0.
|
|
18
|
-
"@lastbrain/module-ai": "^2.0.
|
|
19
|
-
"@lastbrain/module-auth": "^2.0.
|
|
20
|
-
"@lastbrain/module-legal": "^2.0.
|
|
21
|
-
"@lastbrain/module-project-board": "^2.0.
|
|
22
|
-
"@lastbrain/module-tasks": "^2.0.
|
|
23
|
-
"@lastbrain/ui": "^2.0.
|
|
24
|
-
"apps/recipe": "^2.0.
|
|
25
|
-
"lastbrain": "^2.0.
|
|
7
|
+
"@lastbrain-labs/module-billing-pro": "^2.0.25",
|
|
8
|
+
"@lastbrain-labs/module-cj-analyzer-pro": "^0.1.17",
|
|
9
|
+
"@lastbrain-labs/module-core-cart-pro": "^2.0.25",
|
|
10
|
+
"@lastbrain-labs/module-core-commerce-pro": "^2.0.25",
|
|
11
|
+
"@lastbrain-labs/module-core-order-pro": "^2.0.25",
|
|
12
|
+
"@lastbrain-labs/module-core-payment-pro": "^2.0.25",
|
|
13
|
+
"@lastbrain-labs/module-core-product-pro": "^2.0.25",
|
|
14
|
+
"@lastbrain-labs/module-recipes-pro": "^2.0.27",
|
|
15
|
+
"@lastbrain-labs/module-shop-pro": "^0.1.17",
|
|
16
|
+
"@lastbrain/app": "^2.0.30",
|
|
17
|
+
"@lastbrain/core": "^2.0.26",
|
|
18
|
+
"@lastbrain/module-ai": "^2.0.25",
|
|
19
|
+
"@lastbrain/module-auth": "^2.0.26",
|
|
20
|
+
"@lastbrain/module-legal": "^2.0.25",
|
|
21
|
+
"@lastbrain/module-project-board": "^2.0.25",
|
|
22
|
+
"@lastbrain/module-tasks": "^2.0.25",
|
|
23
|
+
"@lastbrain/ui": "^2.0.26",
|
|
24
|
+
"apps/recipe": "^2.0.13",
|
|
25
|
+
"lastbrain": "^2.0.13",
|
|
26
26
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-lang.d.ts","sourceRoot":"","sources":["../../src/i18n/server-lang.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-lang.d.ts","sourceRoot":"","sources":["../../src/i18n/server-lang.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAI3D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA8BjC"}
|
package/dist/i18n/types.d.ts
CHANGED
package/dist/i18n/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,QAAQ,CAAC;IACxB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC"}
|
|
@@ -21,10 +21,12 @@ export declare function useAuth(): {
|
|
|
21
21
|
loading: boolean;
|
|
22
22
|
isSuperAdmin: boolean;
|
|
23
23
|
};
|
|
24
|
-
export declare function AppProviders({ children, realtimeConfig, lang, translations, }: {
|
|
24
|
+
export declare function AppProviders({ children, realtimeConfig, lang, translations, availableLanguages, }: {
|
|
25
25
|
children: React.ReactNode;
|
|
26
26
|
realtimeConfig?: ModuleRealtimeConfig[];
|
|
27
27
|
lang?: Language;
|
|
28
28
|
translations?: Record<string, string>;
|
|
29
|
+
/** Liste des langues disponibles depuis locales.generated.ts */
|
|
30
|
+
availableLanguages?: string[];
|
|
29
31
|
}): import("react/jsx-runtime").JSX.Element;
|
|
30
32
|
//# sourceMappingURL=AppProviders.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,EACjB,kBAAiC,GAClC,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;IACtC,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B,2CA8CA"}
|
|
@@ -35,7 +35,7 @@ export function useNotifications() {
|
|
|
35
35
|
export function useAuth() {
|
|
36
36
|
return useContext(AuthContext);
|
|
37
37
|
}
|
|
38
|
-
export function AppProviders({ children, realtimeConfig = [], lang = "fr", translations = {}, }) {
|
|
38
|
+
export function AppProviders({ children, realtimeConfig = [], lang = "fr", translations = {}, availableLanguages = ["fr", "en"], }) {
|
|
39
39
|
const modules = useMemo(() => getModuleConfigs(), []);
|
|
40
40
|
const { user, loading: authLoading, isSuperAdmin } = useAuthSession();
|
|
41
41
|
// Hook de notifications seulement quand l'auth est prête
|
|
@@ -54,5 +54,5 @@ export function AppProviders({ children, realtimeConfig = [], lang = "fr", trans
|
|
|
54
54
|
// Ne retourner un objet vide que si vraiment rien n'est disponible
|
|
55
55
|
return {};
|
|
56
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 })] }) }) }) }) }) }));
|
|
57
|
+
return (_jsx(LanguageProvider, { initialLang: lang, translations: memoizedTranslations, availableLanguages: availableLanguages, 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 })] }) }) }) }) }) }));
|
|
58
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBAqSpD"}
|
package/dist/scripts/init-app.js
CHANGED
|
@@ -88,6 +88,8 @@ export async function initApp(options) {
|
|
|
88
88
|
await createEnvExample(targetDir, force);
|
|
89
89
|
await createEnvLocal(targetDir, force, isMonorepoProject);
|
|
90
90
|
await createEnvProd(targetDir, force);
|
|
91
|
+
// 6b. Créer les fichiers i18n/default pour les traductions personnalisées
|
|
92
|
+
await createI18nDefaults(targetDir, force, projectName);
|
|
91
93
|
// 7. Créer la structure Supabase avec migrations (seulement pour projets indépendants)
|
|
92
94
|
if (!isMonorepoProject) {
|
|
93
95
|
console.log(chalk.blue("🗄️ Création de la structure Supabase locale...\n"));
|
|
@@ -891,6 +893,17 @@ export async function middleware(request: NextRequest) {
|
|
|
891
893
|
const { pathname } = request.nextUrl;
|
|
892
894
|
const isApi = pathname.startsWith("/api/");
|
|
893
895
|
|
|
896
|
+
// Détecter la langue depuis l'URL (ex: /fr/... ou /es/...)
|
|
897
|
+
const langMatch = pathname.match(/^\\/([a-z]{2})(\\/|$)/);
|
|
898
|
+
const detectedLang = langMatch ? langMatch[1] : "en";
|
|
899
|
+
|
|
900
|
+
// Créer la réponse de base avec les headers de langue
|
|
901
|
+
const createResponseWithLang = (response: NextResponse) => {
|
|
902
|
+
response.headers.set("x-locale", detectedLang);
|
|
903
|
+
response.headers.set("x-pathname", pathname);
|
|
904
|
+
return response;
|
|
905
|
+
};
|
|
906
|
+
|
|
894
907
|
// Pages publiques d'authentification (ne pas protéger)
|
|
895
908
|
const publicAuthPages = [
|
|
896
909
|
"/signin",
|
|
@@ -911,7 +924,7 @@ export async function middleware(request: NextRequest) {
|
|
|
911
924
|
|
|
912
925
|
// Ne pas protéger les pages publiques d'authentification
|
|
913
926
|
if (isPublicAuthPage) {
|
|
914
|
-
return NextResponse.next();
|
|
927
|
+
return createResponseWithLang(NextResponse.next());
|
|
915
928
|
}
|
|
916
929
|
|
|
917
930
|
// Protéger les routes /auth/* (espace membre)
|
|
@@ -1003,7 +1016,7 @@ export async function middleware(request: NextRequest) {
|
|
|
1003
1016
|
}
|
|
1004
1017
|
}
|
|
1005
1018
|
|
|
1006
|
-
return NextResponse.next();
|
|
1019
|
+
return createResponseWithLang(NextResponse.next());
|
|
1007
1020
|
}
|
|
1008
1021
|
|
|
1009
1022
|
export const config = {
|
|
@@ -1470,8 +1483,6 @@ export const menuCustom: MenuCustom = {
|
|
|
1470
1483
|
import type { FooterConfig } from "@lastbrain/ui";
|
|
1471
1484
|
|
|
1472
1485
|
export const footerConfig: FooterConfig = {
|
|
1473
|
-
companyName: "${projectName}",
|
|
1474
|
-
companyDescription: "Application LastBrain",
|
|
1475
1486
|
links: [],
|
|
1476
1487
|
social: [],
|
|
1477
1488
|
};
|
|
@@ -2173,3 +2184,34 @@ export async function GET(
|
|
|
2173
2184
|
}
|
|
2174
2185
|
console.log(chalk.green("✓ Système de proxy storage configuré"));
|
|
2175
2186
|
}
|
|
2187
|
+
async function createI18nDefaults(targetDir, force, projectName) {
|
|
2188
|
+
console.log(chalk.blue("📝 Création des fichiers i18n/default...\n"));
|
|
2189
|
+
const i18nDefaultDir = path.join(targetDir, "i18n", "default");
|
|
2190
|
+
await fs.ensureDir(i18nDefaultDir);
|
|
2191
|
+
// Fichier FR
|
|
2192
|
+
const frPath = path.join(i18nDefaultDir, "fr.json");
|
|
2193
|
+
const frContent = {
|
|
2194
|
+
"app.name": projectName,
|
|
2195
|
+
"app.description": `Bienvenue dans ${projectName}`,
|
|
2196
|
+
"app.tagline": "Votre plateforme de gestion",
|
|
2197
|
+
"app.icon": "Utensils",
|
|
2198
|
+
};
|
|
2199
|
+
if (!fs.existsSync(frPath) || force) {
|
|
2200
|
+
await fs.writeJson(frPath, frContent, { spaces: 2 });
|
|
2201
|
+
console.log(chalk.green(`✓ i18n/default/fr.json créé`));
|
|
2202
|
+
}
|
|
2203
|
+
// Fichier EN
|
|
2204
|
+
const enPath = path.join(i18nDefaultDir, "en.json");
|
|
2205
|
+
const enContent = {
|
|
2206
|
+
"app.name": projectName,
|
|
2207
|
+
"app.description": `Welcome to ${projectName}`,
|
|
2208
|
+
"app.tagline": "Your management platform",
|
|
2209
|
+
"app.icon": "Utensils",
|
|
2210
|
+
};
|
|
2211
|
+
if (!fs.existsSync(enPath) || force) {
|
|
2212
|
+
await fs.writeJson(enPath, enContent, { spaces: 2 });
|
|
2213
|
+
console.log(chalk.green(`✓ i18n/default/en.json créé`));
|
|
2214
|
+
}
|
|
2215
|
+
console.log(chalk.yellow("\n💡 Vous pouvez personnaliser ces fichiers pour votre application"));
|
|
2216
|
+
console.log(chalk.gray(" Chemin: i18n/default/{fr,en}.json\n"));
|
|
2217
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AA0uEA,wBAAsB,cAAc,kBAgInC"}
|