@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;;;GAGG;AAEH,OAAO,IAAI,MAAM,SAAS,CAAC;AA+F3B,eAAe,IAAI,CAAC"}
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
- * Import all translations from modular folder structure
10
- * Each locale has an index.ts that merges all JSON files
14
+ * AUTOMATIC LANGUAGE LOADING
11
15
  *
12
- * Structure (OFFLINE-ONLY):
13
- * locales/
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
- * All translations are offline-compatible and work without backend.
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
- // Import universal translations from localization domain
20
- import localizationEnUS from '../locales/en-US';
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
- * Nested structure - domain-based organization with direct key access
24
- * Example: settings.theme.title, onboarding.welcome.title
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 resources = {
27
- 'en-US': {
28
- translation: {
29
- ...localizationEnUS,
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;;;GAGG;AAEH,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAuB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;;GAUG;AAEH,yDAAyD;AACzD,OAAO,gBAAgB,MAAM,kBAAkB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,SAAS,GAAG;IAChB,OAAO,EAAE;QACP,WAAW,EAAE;YACX,GAAG,gBAAgB;SACpB;KACF;CACF,CAAC;AAEF;;;GAGG;AACH,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,MAAM,cAAc,GAAG,GAAG,EAAE;IAC1B,IAAI,aAAa;QAAE,OAAO;IAE1B,IAAI,CAAC;QACH,yCAAyC;QACzC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;QAE3D,yCAAyC;QACzC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,yCAAyC;QACzC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAE3E,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC;YAC9B,SAAS;YACT,GAAG,EAAE,gBAAgB;YACrB,WAAW,EAAE,gBAAgB;YAE7B,aAAa,EAAE;gBACb,WAAW,EAAE,KAAK,EAAE,+BAA+B;aACpD;YAED,KAAK,EAAE;gBACL,WAAW,EAAE,KAAK,EAAE,oCAAoC;aACzD;YAED,iBAAiB,EAAE,IAAI,EAAE,+DAA+D;YACxF,eAAe,EAAE,GAAG,EAAE,2CAA2C;YACjE,YAAY,EAAE,GAAG,EAAE,oCAAoC;SACxD,CAAC,CAAC;QAEH,aAAa,GAAG,IAAI,CAAC;QACrB,yCAAyC;QACzC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yCAAyC;QACzC,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QAClE,mDAAmD;QACnD,yCAAyC;QACzC,IAAI,OAAO;YAAE,OAAO,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC,CAAC;AAEF,4CAA4C;AAC5C,2DAA2D;AAC3D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IAClC,yCAAyC;IACzC,UAAU,CAAC,GAAG,EAAE;QACd,cAAc,EAAE,CAAC;IACnB,CAAC,EAAE,CAAC,CAAC,CAAC;AACR,CAAC;KAAM,CAAC;IACN,mCAAmC;IACnC,cAAc,EAAE,CAAC;AACnB,CAAC;AAED,eAAe,IAAI,CAAC"}
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,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-localization",
3
- "version": "1.3.10",
3
+ "version": "1.4.0",
4
4
  "description": "Universal localization system for React Native apps with i18n support",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -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
- * Import all translations from modular folder structure
12
- * Each locale has an index.ts that merges all JSON files
13
- *
14
- * Structure (OFFLINE-ONLY):
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
- * en-US/ (universal translations in localization domain)
17
- * index.ts (merges common.json, navigation.json, settings.json, onboarding.json, errors.json)
18
- *
19
- * All translations are offline-compatible and work without backend.
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
- // Import universal translations from localization domain
23
- import localizationEnUS from '../locales/en-US';
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
- * Nested structure - domain-based organization with direct key access
28
- * Example: settings.theme.title, onboarding.welcome.title
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 resources = {
31
- 'en-US': {
32
- translation: {
33
- ...localizationEnUS,
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