@umituz/react-native-localization 1.3.10 → 1.4.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.
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* i18next Configuration
|
|
3
3
|
* Nested translation structure - common translations spread, domain translations nested
|
|
4
|
+
*
|
|
5
|
+
* AUTOMATIC LANGUAGE LOADING:
|
|
6
|
+
* - Uses require.context to auto-discover all language directories
|
|
7
|
+
* - No manual imports needed - all languages loaded automatically
|
|
8
|
+
* - Project translations merged with package defaults
|
|
4
9
|
*/
|
|
5
10
|
import i18n from 'i18next';
|
|
6
11
|
export default i18n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/config/i18n.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/config/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,IAAI,MAAM,SAAS,CAAC;AAgR3B,eAAe,IAAI,CAAC"}
|
|
@@ -1,35 +1,210 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* i18next Configuration
|
|
3
3
|
* Nested translation structure - common translations spread, domain translations nested
|
|
4
|
+
*
|
|
5
|
+
* AUTOMATIC LANGUAGE LOADING:
|
|
6
|
+
* - Uses require.context to auto-discover all language directories
|
|
7
|
+
* - No manual imports needed - all languages loaded automatically
|
|
8
|
+
* - Project translations merged with package defaults
|
|
4
9
|
*/
|
|
5
10
|
import i18n from 'i18next';
|
|
6
11
|
import { initReactI18next } from 'react-i18next';
|
|
7
12
|
import { DEFAULT_LANGUAGE } from './languages';
|
|
8
13
|
/**
|
|
9
|
-
*
|
|
10
|
-
* Each locale has an index.ts that merges all JSON files
|
|
14
|
+
* AUTOMATIC LANGUAGE LOADING
|
|
11
15
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* en-US/ (universal translations in localization domain)
|
|
15
|
-
* index.ts (merges common.json, navigation.json, settings.json, onboarding.json, errors.json)
|
|
16
|
+
* Uses Metro bundler's require.context to automatically discover and load
|
|
17
|
+
* all language directories. No manual imports needed!
|
|
16
18
|
*
|
|
17
|
-
*
|
|
19
|
+
* Structure:
|
|
20
|
+
* locales/
|
|
21
|
+
* ar-SA/index.ts
|
|
22
|
+
* bg-BG/index.ts
|
|
23
|
+
* en-US/index.ts
|
|
24
|
+
* ... (all languages auto-discovered)
|
|
18
25
|
*/
|
|
19
|
-
//
|
|
20
|
-
|
|
26
|
+
// Auto-load all package locale directories using require.context
|
|
27
|
+
// This automatically discovers all language folders (ar-SA, bg-BG, en-US, etc.)
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
29
|
+
const packageLocalesContext = require.context('../locales', true, /\/index\.ts$/);
|
|
30
|
+
/**
|
|
31
|
+
* Load all package translations automatically
|
|
32
|
+
* Extracts language code from path (e.g., './ar-SA/index.ts' -> 'ar-SA')
|
|
33
|
+
*/
|
|
34
|
+
const loadPackageTranslations = () => {
|
|
35
|
+
const packageTranslations = {};
|
|
36
|
+
packageLocalesContext.keys().forEach((key) => {
|
|
37
|
+
// Extract language code from path: './ar-SA/index.ts' -> 'ar-SA'
|
|
38
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
39
|
+
if (match) {
|
|
40
|
+
const languageCode = match[1];
|
|
41
|
+
try {
|
|
42
|
+
const translations = packageLocalesContext(key);
|
|
43
|
+
packageTranslations[languageCode] = translations.default || translations;
|
|
44
|
+
/* eslint-disable-next-line no-console */
|
|
45
|
+
if (__DEV__)
|
|
46
|
+
console.log(`[i18n] ✅ Loaded package translations: ${languageCode}`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
/* eslint-disable-next-line no-console */
|
|
50
|
+
if (__DEV__)
|
|
51
|
+
console.warn(`[i18n] ⚠️ Failed to load package translations for ${languageCode}:`, error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return packageTranslations;
|
|
56
|
+
};
|
|
57
|
+
const packageTranslations = loadPackageTranslations();
|
|
58
|
+
/**
|
|
59
|
+
* Try to load project-specific translations
|
|
60
|
+
* Metro bundler will resolve these at build time if they exist
|
|
61
|
+
* If they don't exist, the require will fail gracefully
|
|
62
|
+
*/
|
|
63
|
+
let projectTranslations = {};
|
|
64
|
+
// Try to load project translations from common paths
|
|
65
|
+
// Metro bundler will include these if they exist at build time
|
|
66
|
+
try {
|
|
67
|
+
// Try DDD structure path with require.context for automatic discovery
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
69
|
+
const projectLocalesContext = require.context('../../../../../../src/domains/localization/infrastructure/locales', true, /\/index\.ts$/);
|
|
70
|
+
projectLocalesContext.keys().forEach((key) => {
|
|
71
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
72
|
+
if (match) {
|
|
73
|
+
const languageCode = match[1];
|
|
74
|
+
try {
|
|
75
|
+
const translations = projectLocalesContext(key);
|
|
76
|
+
if (!projectTranslations[languageCode]) {
|
|
77
|
+
projectTranslations[languageCode] = {};
|
|
78
|
+
}
|
|
79
|
+
projectTranslations[languageCode] = translations.default || translations;
|
|
80
|
+
/* eslint-disable-next-line no-console */
|
|
81
|
+
if (__DEV__)
|
|
82
|
+
console.log(`[i18n] ✅ Loaded project translations: ${languageCode}`);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
/* eslint-disable-next-line no-console */
|
|
86
|
+
if (__DEV__)
|
|
87
|
+
console.warn(`[i18n] ⚠️ Failed to load project translations for ${languageCode}:`, error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
/* eslint-disable-next-line no-console */
|
|
92
|
+
if (__DEV__)
|
|
93
|
+
console.log('[i18n] ✅ Loaded project translations from DDD structure');
|
|
94
|
+
}
|
|
95
|
+
catch (e1) {
|
|
96
|
+
try {
|
|
97
|
+
// Try alternative DDD structure path
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
99
|
+
const projectLocalesContext = require.context('../../../../../../domains/localization/infrastructure/locales', true, /\/index\.ts$/);
|
|
100
|
+
projectLocalesContext.keys().forEach((key) => {
|
|
101
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
102
|
+
if (match) {
|
|
103
|
+
const languageCode = match[1];
|
|
104
|
+
try {
|
|
105
|
+
const translations = projectLocalesContext(key);
|
|
106
|
+
if (!projectTranslations[languageCode]) {
|
|
107
|
+
projectTranslations[languageCode] = {};
|
|
108
|
+
}
|
|
109
|
+
projectTranslations[languageCode] = translations.default || translations;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
// Ignore individual language errors
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
/* eslint-disable-next-line no-console */
|
|
117
|
+
if (__DEV__)
|
|
118
|
+
console.log('[i18n] ✅ Loaded project translations from alternative DDD structure');
|
|
119
|
+
}
|
|
120
|
+
catch (e2) {
|
|
121
|
+
try {
|
|
122
|
+
// Try simple structure path
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
124
|
+
const projectLocalesContext = require.context('../../../../../../src/locales', true, /\/index\.ts$/);
|
|
125
|
+
projectLocalesContext.keys().forEach((key) => {
|
|
126
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
127
|
+
if (match) {
|
|
128
|
+
const languageCode = match[1];
|
|
129
|
+
try {
|
|
130
|
+
const translations = projectLocalesContext(key);
|
|
131
|
+
if (!projectTranslations[languageCode]) {
|
|
132
|
+
projectTranslations[languageCode] = {};
|
|
133
|
+
}
|
|
134
|
+
projectTranslations[languageCode] = translations.default || translations;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
// Ignore individual language errors
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
/* eslint-disable-next-line no-console */
|
|
142
|
+
if (__DEV__)
|
|
143
|
+
console.log('[i18n] ✅ Loaded project translations from simple structure');
|
|
144
|
+
}
|
|
145
|
+
catch (e3) {
|
|
146
|
+
// No project translations found - this is OK, use package defaults only
|
|
147
|
+
/* eslint-disable-next-line no-console */
|
|
148
|
+
if (__DEV__)
|
|
149
|
+
console.log('[i18n] ℹ️ No project-specific translations found, using package defaults only');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
21
153
|
/**
|
|
22
154
|
* Translation Resources
|
|
23
|
-
*
|
|
24
|
-
*
|
|
155
|
+
* Merge package defaults with project-specific translations
|
|
156
|
+
* Project translations override package defaults (deep merge)
|
|
157
|
+
*/
|
|
158
|
+
const mergeTranslations = (packageTranslations, projectTranslations) => {
|
|
159
|
+
if (!projectTranslations || Object.keys(projectTranslations).length === 0) {
|
|
160
|
+
return packageTranslations;
|
|
161
|
+
}
|
|
162
|
+
// Deep merge: project translations override package defaults
|
|
163
|
+
const merged = { ...packageTranslations };
|
|
164
|
+
for (const key in projectTranslations) {
|
|
165
|
+
if (projectTranslations.hasOwnProperty(key)) {
|
|
166
|
+
if (typeof projectTranslations[key] === 'object' &&
|
|
167
|
+
projectTranslations[key] !== null &&
|
|
168
|
+
!Array.isArray(projectTranslations[key]) &&
|
|
169
|
+
typeof packageTranslations[key] === 'object' &&
|
|
170
|
+
packageTranslations[key] !== null &&
|
|
171
|
+
!Array.isArray(packageTranslations[key])) {
|
|
172
|
+
// Deep merge nested objects
|
|
173
|
+
merged[key] = mergeTranslations(packageTranslations[key], projectTranslations[key]);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Override with project translation
|
|
177
|
+
merged[key] = projectTranslations[key];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return merged;
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Build resources object for all languages
|
|
185
|
+
* Automatically includes all package languages + project languages
|
|
25
186
|
*/
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
187
|
+
const buildResources = () => {
|
|
188
|
+
const resources = {};
|
|
189
|
+
// Get all unique language codes from both package and project translations
|
|
190
|
+
const allLanguageCodes = new Set([
|
|
191
|
+
...Object.keys(packageTranslations),
|
|
192
|
+
...Object.keys(projectTranslations),
|
|
193
|
+
]);
|
|
194
|
+
// Build resources for each language
|
|
195
|
+
allLanguageCodes.forEach((languageCode) => {
|
|
196
|
+
const packageTranslation = packageTranslations[languageCode] || {};
|
|
197
|
+
const projectTranslation = projectTranslations[languageCode] || {};
|
|
198
|
+
resources[languageCode] = {
|
|
199
|
+
translation: mergeTranslations(packageTranslation, projectTranslation),
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
/* eslint-disable-next-line no-console */
|
|
203
|
+
if (__DEV__)
|
|
204
|
+
console.log(`[i18n] 📦 Loaded ${Object.keys(resources).length} languages:`, Object.keys(resources).join(', '));
|
|
205
|
+
return resources;
|
|
32
206
|
};
|
|
207
|
+
const resources = buildResources();
|
|
33
208
|
/**
|
|
34
209
|
* Initialize i18next
|
|
35
210
|
* Deferred initialization to avoid React Native renderer conflicts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../src/infrastructure/config/i18n.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../src/infrastructure/config/i18n.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* i18next Configuration
|
|
3
3
|
* Nested translation structure - common translations spread, domain translations nested
|
|
4
|
+
*
|
|
5
|
+
* AUTOMATIC LANGUAGE LOADING:
|
|
6
|
+
* - Uses require.context to auto-discover all language directories
|
|
7
|
+
* - No manual imports needed - all languages loaded automatically
|
|
8
|
+
* - Project translations merged with package defaults
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
import i18n from 'i18next';
|
|
@@ -8,33 +13,210 @@ import { initReactI18next } from 'react-i18next';
|
|
|
8
13
|
import { SUPPORTED_LANGUAGES, DEFAULT_LANGUAGE } from './languages';
|
|
9
14
|
|
|
10
15
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
16
|
+
* AUTOMATIC LANGUAGE LOADING
|
|
17
|
+
*
|
|
18
|
+
* Uses Metro bundler's require.context to automatically discover and load
|
|
19
|
+
* all language directories. No manual imports needed!
|
|
20
|
+
*
|
|
21
|
+
* Structure:
|
|
15
22
|
* locales/
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
23
|
+
* ar-SA/index.ts
|
|
24
|
+
* bg-BG/index.ts
|
|
25
|
+
* en-US/index.ts
|
|
26
|
+
* ... (all languages auto-discovered)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// Auto-load all package locale directories using require.context
|
|
30
|
+
// This automatically discovers all language folders (ar-SA, bg-BG, en-US, etc.)
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
32
|
+
const packageLocalesContext = (require as any).context('../locales', true, /\/index\.ts$/);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Load all package translations automatically
|
|
36
|
+
* Extracts language code from path (e.g., './ar-SA/index.ts' -> 'ar-SA')
|
|
37
|
+
*/
|
|
38
|
+
const loadPackageTranslations = (): Record<string, any> => {
|
|
39
|
+
const packageTranslations: Record<string, any> = {};
|
|
40
|
+
|
|
41
|
+
packageLocalesContext.keys().forEach((key: string) => {
|
|
42
|
+
// Extract language code from path: './ar-SA/index.ts' -> 'ar-SA'
|
|
43
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
44
|
+
if (match) {
|
|
45
|
+
const languageCode = match[1];
|
|
46
|
+
try {
|
|
47
|
+
const translations = packageLocalesContext(key);
|
|
48
|
+
packageTranslations[languageCode] = translations.default || translations;
|
|
49
|
+
/* eslint-disable-next-line no-console */
|
|
50
|
+
if (__DEV__) console.log(`[i18n] ✅ Loaded package translations: ${languageCode}`);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
/* eslint-disable-next-line no-console */
|
|
53
|
+
if (__DEV__) console.warn(`[i18n] ⚠️ Failed to load package translations for ${languageCode}:`, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return packageTranslations;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const packageTranslations = loadPackageTranslations();
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Try to load project-specific translations
|
|
65
|
+
* Metro bundler will resolve these at build time if they exist
|
|
66
|
+
* If they don't exist, the require will fail gracefully
|
|
20
67
|
*/
|
|
68
|
+
let projectTranslations: Record<string, any> = {};
|
|
21
69
|
|
|
22
|
-
//
|
|
23
|
-
|
|
70
|
+
// Try to load project translations from common paths
|
|
71
|
+
// Metro bundler will include these if they exist at build time
|
|
72
|
+
try {
|
|
73
|
+
// Try DDD structure path with require.context for automatic discovery
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
75
|
+
const projectLocalesContext = (require as any).context('../../../../../../src/domains/localization/infrastructure/locales', true, /\/index\.ts$/);
|
|
76
|
+
|
|
77
|
+
projectLocalesContext.keys().forEach((key: string) => {
|
|
78
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
79
|
+
if (match) {
|
|
80
|
+
const languageCode = match[1];
|
|
81
|
+
try {
|
|
82
|
+
const translations = projectLocalesContext(key);
|
|
83
|
+
if (!projectTranslations[languageCode]) {
|
|
84
|
+
projectTranslations[languageCode] = {};
|
|
85
|
+
}
|
|
86
|
+
projectTranslations[languageCode] = translations.default || translations;
|
|
87
|
+
/* eslint-disable-next-line no-console */
|
|
88
|
+
if (__DEV__) console.log(`[i18n] ✅ Loaded project translations: ${languageCode}`);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
/* eslint-disable-next-line no-console */
|
|
91
|
+
if (__DEV__) console.warn(`[i18n] ⚠️ Failed to load project translations for ${languageCode}:`, error);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
/* eslint-disable-next-line no-console */
|
|
97
|
+
if (__DEV__) console.log('[i18n] ✅ Loaded project translations from DDD structure');
|
|
98
|
+
} catch (e1) {
|
|
99
|
+
try {
|
|
100
|
+
// Try alternative DDD structure path
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
102
|
+
const projectLocalesContext = (require as any).context('../../../../../../domains/localization/infrastructure/locales', true, /\/index\.ts$/);
|
|
103
|
+
|
|
104
|
+
projectLocalesContext.keys().forEach((key: string) => {
|
|
105
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
106
|
+
if (match) {
|
|
107
|
+
const languageCode = match[1];
|
|
108
|
+
try {
|
|
109
|
+
const translations = projectLocalesContext(key);
|
|
110
|
+
if (!projectTranslations[languageCode]) {
|
|
111
|
+
projectTranslations[languageCode] = {};
|
|
112
|
+
}
|
|
113
|
+
projectTranslations[languageCode] = translations.default || translations;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
// Ignore individual language errors
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
/* eslint-disable-next-line no-console */
|
|
121
|
+
if (__DEV__) console.log('[i18n] ✅ Loaded project translations from alternative DDD structure');
|
|
122
|
+
} catch (e2) {
|
|
123
|
+
try {
|
|
124
|
+
// Try simple structure path
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
126
|
+
const projectLocalesContext = (require as any).context('../../../../../../src/locales', true, /\/index\.ts$/);
|
|
127
|
+
|
|
128
|
+
projectLocalesContext.keys().forEach((key: string) => {
|
|
129
|
+
const match = key.match(/\.\/([^/]+)\/index\.ts$/);
|
|
130
|
+
if (match) {
|
|
131
|
+
const languageCode = match[1];
|
|
132
|
+
try {
|
|
133
|
+
const translations = projectLocalesContext(key);
|
|
134
|
+
if (!projectTranslations[languageCode]) {
|
|
135
|
+
projectTranslations[languageCode] = {};
|
|
136
|
+
}
|
|
137
|
+
projectTranslations[languageCode] = translations.default || translations;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
// Ignore individual language errors
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/* eslint-disable-next-line no-console */
|
|
145
|
+
if (__DEV__) console.log('[i18n] ✅ Loaded project translations from simple structure');
|
|
146
|
+
} catch (e3) {
|
|
147
|
+
// No project translations found - this is OK, use package defaults only
|
|
148
|
+
/* eslint-disable-next-line no-console */
|
|
149
|
+
if (__DEV__) console.log('[i18n] ℹ️ No project-specific translations found, using package defaults only');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
24
153
|
|
|
25
154
|
/**
|
|
26
155
|
* Translation Resources
|
|
27
|
-
*
|
|
28
|
-
*
|
|
156
|
+
* Merge package defaults with project-specific translations
|
|
157
|
+
* Project translations override package defaults (deep merge)
|
|
158
|
+
*/
|
|
159
|
+
const mergeTranslations = (packageTranslations: any, projectTranslations: any): any => {
|
|
160
|
+
if (!projectTranslations || Object.keys(projectTranslations).length === 0) {
|
|
161
|
+
return packageTranslations;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Deep merge: project translations override package defaults
|
|
165
|
+
const merged = { ...packageTranslations };
|
|
166
|
+
|
|
167
|
+
for (const key in projectTranslations) {
|
|
168
|
+
if (projectTranslations.hasOwnProperty(key)) {
|
|
169
|
+
if (
|
|
170
|
+
typeof projectTranslations[key] === 'object' &&
|
|
171
|
+
projectTranslations[key] !== null &&
|
|
172
|
+
!Array.isArray(projectTranslations[key]) &&
|
|
173
|
+
typeof packageTranslations[key] === 'object' &&
|
|
174
|
+
packageTranslations[key] !== null &&
|
|
175
|
+
!Array.isArray(packageTranslations[key])
|
|
176
|
+
) {
|
|
177
|
+
// Deep merge nested objects
|
|
178
|
+
merged[key] = mergeTranslations(packageTranslations[key], projectTranslations[key]);
|
|
179
|
+
} else {
|
|
180
|
+
// Override with project translation
|
|
181
|
+
merged[key] = projectTranslations[key];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return merged;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Build resources object for all languages
|
|
191
|
+
* Automatically includes all package languages + project languages
|
|
29
192
|
*/
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
193
|
+
const buildResources = (): Record<string, { translation: any }> => {
|
|
194
|
+
const resources: Record<string, { translation: any }> = {};
|
|
195
|
+
|
|
196
|
+
// Get all unique language codes from both package and project translations
|
|
197
|
+
const allLanguageCodes = new Set([
|
|
198
|
+
...Object.keys(packageTranslations),
|
|
199
|
+
...Object.keys(projectTranslations),
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
// Build resources for each language
|
|
203
|
+
allLanguageCodes.forEach((languageCode) => {
|
|
204
|
+
const packageTranslation = packageTranslations[languageCode] || {};
|
|
205
|
+
const projectTranslation = projectTranslations[languageCode] || {};
|
|
206
|
+
|
|
207
|
+
resources[languageCode] = {
|
|
208
|
+
translation: mergeTranslations(packageTranslation, projectTranslation),
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
/* eslint-disable-next-line no-console */
|
|
213
|
+
if (__DEV__) console.log(`[i18n] 📦 Loaded ${Object.keys(resources).length} languages:`, Object.keys(resources).join(', '));
|
|
214
|
+
|
|
215
|
+
return resources;
|
|
36
216
|
};
|
|
37
217
|
|
|
218
|
+
const resources = buildResources();
|
|
219
|
+
|
|
38
220
|
/**
|
|
39
221
|
* Initialize i18next
|
|
40
222
|
* Deferred initialization to avoid React Native renderer conflicts
|