@jsarc/intl 0.0.1-beta.0.3 → 0.0.1-beta.0.5
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/js/providers/IntlProvider.jsx +97 -17
- package/package.json +3 -3
- package/providers/IntlProvider.tsx +125 -34
|
@@ -1,8 +1,104 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { createContext, useContext, useState, useEffect, useMemo, useCallback } from 'react';
|
|
3
3
|
import { TranslationService } from '../core/TranslationService';
|
|
4
4
|
import { getSavedLocale, saveLocale, SUPPORTED_LOCALES } from '../config';
|
|
5
5
|
const ArcIntlContext = createContext(null);
|
|
6
|
+
export const ArcIntlProvider = ({
|
|
7
|
+
translations,
|
|
8
|
+
supportedLocales,
|
|
9
|
+
children
|
|
10
|
+
}) => {
|
|
11
|
+
const finalSupportedLocales = useMemo(() => {
|
|
12
|
+
return typeof supportedLocales === 'object' && !!Array.isArray(supportedLocales) && supportedLocales.length > 0 ? supportedLocales : SUPPORTED_LOCALES;
|
|
13
|
+
}, [supportedLocales]);
|
|
14
|
+
const [service] = useState(() => new TranslationService(finalSupportedLocales, translations));
|
|
15
|
+
const [currentLocale, setCurrentLocale] = useState(() => getSavedLocale(finalSupportedLocales));
|
|
16
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
17
|
+
const [initialized, setInitialized] = useState(false);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const initialize = async () => {
|
|
20
|
+
setIsLoading(true);
|
|
21
|
+
try {
|
|
22
|
+
if (!initialized) {
|
|
23
|
+
await service.initialize(currentLocale);
|
|
24
|
+
setInitialized(true);
|
|
25
|
+
} else {
|
|
26
|
+
await service.initialize(currentLocale);
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error('❌ Failed to initialize translations:', error);
|
|
30
|
+
} finally {
|
|
31
|
+
setIsLoading(false);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const timer = setTimeout(() => {
|
|
35
|
+
initialize();
|
|
36
|
+
}, 0);
|
|
37
|
+
return () => clearTimeout(timer);
|
|
38
|
+
}, [currentLocale, service, initialized]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!initialized || isLoading || !translations.modules) return;
|
|
41
|
+
const loadAllModules = async () => {
|
|
42
|
+
const moduleNames = Object.keys(translations.modules || {});
|
|
43
|
+
for (const moduleName of moduleNames) {
|
|
44
|
+
try {
|
|
45
|
+
await service.loadModule(moduleName);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(`❌ Failed to load module ${moduleName}:`, error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
loadAllModules();
|
|
52
|
+
}, [initialized, translations.modules, service, isLoading]);
|
|
53
|
+
const changeLocale = useCallback(async locale => {
|
|
54
|
+
if (!finalSupportedLocales.includes(locale)) {
|
|
55
|
+
console.warn(`⚠️ Locale ${locale} is not supported`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (locale === currentLocale) return;
|
|
59
|
+
setIsLoading(true);
|
|
60
|
+
try {
|
|
61
|
+
await service.initialize(locale);
|
|
62
|
+
setCurrentLocale(locale);
|
|
63
|
+
saveLocale(locale);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('❌ Failed to change locale:', error);
|
|
66
|
+
} finally {
|
|
67
|
+
setIsLoading(false);
|
|
68
|
+
}
|
|
69
|
+
}, [currentLocale, finalSupportedLocales, service]);
|
|
70
|
+
const loadModuleTranslations = useCallback(async moduleName => {
|
|
71
|
+
setIsLoading(true);
|
|
72
|
+
try {
|
|
73
|
+
await service.loadModule(moduleName);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(`❌ Failed to load module ${moduleName}:`, error);
|
|
76
|
+
throw error;
|
|
77
|
+
} finally {
|
|
78
|
+
setIsLoading(false);
|
|
79
|
+
}
|
|
80
|
+
}, [service]);
|
|
81
|
+
const t = useCallback((key, params, options) => {
|
|
82
|
+
const result = service.t(key, params || {}, options || {});
|
|
83
|
+
return result;
|
|
84
|
+
}, [service]);
|
|
85
|
+
const contextValue = useMemo(() => ({
|
|
86
|
+
t,
|
|
87
|
+
changeLocale,
|
|
88
|
+
currentLocale,
|
|
89
|
+
isLoading,
|
|
90
|
+
loadModuleTranslations,
|
|
91
|
+
isInitialized: initialized
|
|
92
|
+
}), [t, changeLocale, currentLocale, isLoading, loadModuleTranslations, initialized]);
|
|
93
|
+
return React.createElement(ArcIntlContext.Provider, {
|
|
94
|
+
value: contextValue
|
|
95
|
+
}, children);
|
|
96
|
+
};
|
|
97
|
+
export const useArcIntl = () => {
|
|
98
|
+
const context = useContext(ArcIntlContext);
|
|
99
|
+
if (!context) throw new Error('useArcIntl must be used within an ArcIntlProvider');
|
|
100
|
+
return context;
|
|
101
|
+
};
|
|
6
102
|
const useArcIntlValue = (translationsConfig, supportedLocales = SUPPORTED_LOCALES) => {
|
|
7
103
|
const [service] = useState(() => new TranslationService(supportedLocales, translationsConfig));
|
|
8
104
|
const [currentLocale, setCurrentLocale] = useState(getSavedLocale(supportedLocales));
|
|
@@ -84,23 +180,7 @@ const useArcIntlValue = (translationsConfig, supportedLocales = SUPPORTED_LOCALE
|
|
|
84
180
|
isInitialized: initialized
|
|
85
181
|
};
|
|
86
182
|
};
|
|
87
|
-
export const ArcIntlProvider = ({
|
|
88
|
-
translations,
|
|
89
|
-
supportedLocales,
|
|
90
|
-
children
|
|
91
|
-
}) => {
|
|
92
|
-
const value = useArcIntlValue(translations, typeof supportedLocales === 'object' && !!Array.isArray(supportedLocales) && supportedLocales.length > 0 ? supportedLocales : SUPPORTED_LOCALES);
|
|
93
|
-
return React.createElement(ArcIntlContext.Provider, {
|
|
94
|
-
value: value
|
|
95
|
-
}, children);
|
|
96
|
-
};
|
|
97
|
-
export const useArcIntl = () => {
|
|
98
|
-
const context = useContext(ArcIntlContext);
|
|
99
|
-
if (!context) throw new Error('useArcIntl must be used within an ArcIntlProvider');
|
|
100
|
-
return context;
|
|
101
|
-
};
|
|
102
183
|
export default {
|
|
103
|
-
useArcIntlValue,
|
|
104
184
|
ArcIntlProvider,
|
|
105
185
|
useArcIntl
|
|
106
186
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.0.1-beta.0.
|
|
6
|
+
"version": "0.0.1-beta.0.5",
|
|
7
7
|
"description": "INTL est un système de gestion d'internationalisation (i18n) modulaire et performant pour les applications React avec TypeScript/JavaScript. Il fournit une gestion avancée des traductions, un chargement dynamique des modules, et une intégration transparente avec l'écosystème Arc.",
|
|
8
8
|
"main": "index.ts",
|
|
9
9
|
"keywords": [],
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"react": "^19.
|
|
20
|
-
"@jsarc/cooks": "^0.0.1-beta.0.
|
|
19
|
+
"react": "^19.1.0",
|
|
20
|
+
"@jsarc/cooks": "^0.0.1-beta.0.5"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -3,7 +3,127 @@ import { TranslationService } from '../core/TranslationService';
|
|
|
3
3
|
import { getSavedLocale, saveLocale, SUPPORTED_LOCALES, type TranslationsConfig } from '../config';
|
|
4
4
|
import type { Locale } from '../config';
|
|
5
5
|
|
|
6
|
-
const ArcIntlContext = createContext<
|
|
6
|
+
const ArcIntlContext = createContext<any | null>(null);
|
|
7
|
+
|
|
8
|
+
export const ArcIntlProvider: React.FC<{
|
|
9
|
+
children: React.ReactNode
|
|
10
|
+
translations: TranslationsConfig
|
|
11
|
+
supportedLocales?: string[];
|
|
12
|
+
}> = ({
|
|
13
|
+
translations,
|
|
14
|
+
supportedLocales,
|
|
15
|
+
children,
|
|
16
|
+
}) => {
|
|
17
|
+
const finalSupportedLocales = useMemo(() => {
|
|
18
|
+
return (typeof supportedLocales === 'object' &&
|
|
19
|
+
!!Array.isArray(supportedLocales) &&
|
|
20
|
+
supportedLocales.length > 0)
|
|
21
|
+
? supportedLocales
|
|
22
|
+
: SUPPORTED_LOCALES;
|
|
23
|
+
}, [supportedLocales]);
|
|
24
|
+
|
|
25
|
+
const [service] = useState(() => new TranslationService(finalSupportedLocales, translations));
|
|
26
|
+
|
|
27
|
+
const [currentLocale, setCurrentLocale] = useState<Locale>(() => getSavedLocale(finalSupportedLocales));
|
|
28
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
29
|
+
const [initialized, setInitialized] = useState(false);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const initialize = async () => {
|
|
33
|
+
setIsLoading(true);
|
|
34
|
+
try {
|
|
35
|
+
if (!initialized) {
|
|
36
|
+
await service.initialize(currentLocale);
|
|
37
|
+
setInitialized(true);
|
|
38
|
+
} else {
|
|
39
|
+
await service.initialize(currentLocale);
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('❌ Failed to initialize translations:', error);
|
|
43
|
+
} finally {
|
|
44
|
+
setIsLoading(false);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
initialize();
|
|
50
|
+
}, 0);
|
|
51
|
+
|
|
52
|
+
return () => clearTimeout(timer);
|
|
53
|
+
}, [currentLocale, service, initialized]);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!initialized || isLoading || !translations.modules) return;
|
|
57
|
+
|
|
58
|
+
const loadAllModules = async () => {
|
|
59
|
+
const moduleNames = Object.keys(translations.modules || {});
|
|
60
|
+
|
|
61
|
+
for (const moduleName of moduleNames) {
|
|
62
|
+
try {
|
|
63
|
+
await service.loadModule(moduleName);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error(`❌ Failed to load module ${moduleName}:`, error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
loadAllModules();
|
|
71
|
+
}, [initialized, translations.modules, service, isLoading]);
|
|
72
|
+
|
|
73
|
+
const changeLocale = useCallback(async (locale: Locale) => {
|
|
74
|
+
if (!finalSupportedLocales.includes(locale)) {
|
|
75
|
+
console.warn(`⚠️ Locale ${locale} is not supported`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (locale === currentLocale) return;
|
|
80
|
+
|
|
81
|
+
setIsLoading(true);
|
|
82
|
+
try {
|
|
83
|
+
await service.initialize(locale);
|
|
84
|
+
setCurrentLocale(locale);
|
|
85
|
+
saveLocale(locale);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('❌ Failed to change locale:', error);
|
|
88
|
+
} finally {
|
|
89
|
+
setIsLoading(false);
|
|
90
|
+
}
|
|
91
|
+
}, [currentLocale, finalSupportedLocales, service]);
|
|
92
|
+
|
|
93
|
+
const loadModuleTranslations = useCallback(async (moduleName: string) => {
|
|
94
|
+
setIsLoading(true);
|
|
95
|
+
try {
|
|
96
|
+
await service.loadModule(moduleName);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`❌ Failed to load module ${moduleName}:`, error);
|
|
99
|
+
throw error;
|
|
100
|
+
} finally {
|
|
101
|
+
setIsLoading(false);
|
|
102
|
+
}
|
|
103
|
+
}, [service]);
|
|
104
|
+
|
|
105
|
+
const t = useCallback((key: string, params?: Record<string, any>, options?: any) => {
|
|
106
|
+
const result = service.t(key, params || {}, options || {});
|
|
107
|
+
return result;
|
|
108
|
+
}, [service]);
|
|
109
|
+
|
|
110
|
+
const contextValue = useMemo(() => ({
|
|
111
|
+
t,
|
|
112
|
+
changeLocale,
|
|
113
|
+
currentLocale,
|
|
114
|
+
isLoading,
|
|
115
|
+
loadModuleTranslations,
|
|
116
|
+
isInitialized: initialized,
|
|
117
|
+
}), [t, changeLocale, currentLocale, isLoading, loadModuleTranslations, initialized]);
|
|
118
|
+
|
|
119
|
+
return <ArcIntlContext.Provider value={contextValue}>{children}</ArcIntlContext.Provider>;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const useArcIntl = () => {
|
|
123
|
+
const context = useContext(ArcIntlContext);
|
|
124
|
+
if (!context) throw new Error('useArcIntl must be used within an ArcIntlProvider');
|
|
125
|
+
return context;
|
|
126
|
+
};
|
|
7
127
|
|
|
8
128
|
const useArcIntlValue = (
|
|
9
129
|
translationsConfig: TranslationsConfig,
|
|
@@ -13,7 +133,7 @@ const useArcIntlValue = (
|
|
|
13
133
|
const [currentLocale, setCurrentLocale] = useState<Locale>(getSavedLocale(supportedLocales));
|
|
14
134
|
const [isLoading, setIsLoading] = useState(true);
|
|
15
135
|
const [initialized, setInitialized] = useState(false);
|
|
16
|
-
|
|
136
|
+
|
|
17
137
|
useEffect(() => {
|
|
18
138
|
const initialize = async () => {
|
|
19
139
|
setIsLoading(true);
|
|
@@ -30,14 +150,14 @@ const useArcIntlValue = (
|
|
|
30
150
|
setIsLoading(false);
|
|
31
151
|
}
|
|
32
152
|
};
|
|
33
|
-
|
|
153
|
+
|
|
34
154
|
const timer = setTimeout(() => {
|
|
35
155
|
initialize();
|
|
36
156
|
}, 0);
|
|
37
157
|
|
|
38
158
|
return () => clearTimeout(timer);
|
|
39
159
|
}, [currentLocale, service, initialized]);
|
|
40
|
-
|
|
160
|
+
|
|
41
161
|
useEffect(() => {
|
|
42
162
|
if (!initialized || isLoading || !translationsConfig.modules) return;
|
|
43
163
|
|
|
@@ -103,36 +223,7 @@ const useArcIntlValue = (
|
|
|
103
223
|
};
|
|
104
224
|
};
|
|
105
225
|
|
|
106
|
-
export const ArcIntlProvider: React.FC<{
|
|
107
|
-
children: React.ReactNode
|
|
108
|
-
translations: TranslationsConfig
|
|
109
|
-
supportedLocales?: string[];
|
|
110
|
-
}> = ({
|
|
111
|
-
translations,
|
|
112
|
-
supportedLocales,
|
|
113
|
-
children,
|
|
114
|
-
}) => {
|
|
115
|
-
|
|
116
|
-
const value = useArcIntlValue(
|
|
117
|
-
translations,
|
|
118
|
-
(typeof supportedLocales === 'object' &&
|
|
119
|
-
!!Array.isArray(supportedLocales) &&
|
|
120
|
-
supportedLocales.length > 0)
|
|
121
|
-
? supportedLocales
|
|
122
|
-
: SUPPORTED_LOCALES
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
return <ArcIntlContext.Provider value={value}>{children}</ArcIntlContext.Provider>;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
export const useArcIntl = () => {
|
|
129
|
-
const context = useContext(ArcIntlContext);
|
|
130
|
-
if (!context) throw new Error('useArcIntl must be used within an ArcIntlProvider');
|
|
131
|
-
return context;
|
|
132
|
-
};
|
|
133
|
-
|
|
134
226
|
export default {
|
|
135
|
-
useArcIntlValue,
|
|
136
227
|
ArcIntlProvider,
|
|
137
228
|
useArcIntl,
|
|
138
|
-
}
|
|
229
|
+
};
|