@umituz/react-native-localization 1.2.0 → 1.2.2

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,23 +1,13 @@
1
1
  /**
2
2
  * Localization Store
3
3
  * Zustand state management for language preferences with AsyncStorage persistence
4
- *
5
- * REFACTORED: Now uses centralized AsyncStorageWrapper for DRY compliance
6
- * - Eliminates duplicate AsyncStorage calls
7
- * - Consistent error handling and logging
8
- * - Type-safe storage operations
9
4
  */
10
5
 
11
- import { create } from "zustand";
12
- import { StorageWrapper, STORAGE_KEYS } from "./AsyncStorageWrapper";
13
- import i18n from "../config/i18n";
14
- import {
15
- SUPPORTED_LANGUAGES,
16
- DEFAULT_LANGUAGE,
17
- getLanguageByCode,
18
- getDeviceLocale,
19
- } from "../config/languages";
20
- import type { Language } from "../../domain/repositories/ILocalizationRepository";
6
+ import { create } from 'zustand';
7
+ import { StorageWrapper, STORAGE_KEYS } from './AsyncStorageWrapper';
8
+ import i18n from '../config/i18n';
9
+ import { SUPPORTED_LANGUAGES, DEFAULT_LANGUAGE, getLanguageByCode, getDeviceLocale } from '../config/languages';
10
+ import type { Language } from '../../domain/repositories/ILocalizationRepository';
21
11
 
22
12
  interface LocalizationState {
23
13
  currentLanguage: string;
@@ -42,115 +32,37 @@ export const useLocalizationStore = create<LocalizationState>((set, get) => ({
42
32
  * - Fallback: English (en-US) if device locale not supported
43
33
  */
44
34
  initialize: async () => {
45
- try {
46
- /* eslint-disable-next-line no-console */
47
- if (__DEV__)
48
- console.log("[LocalizationStore] Starting initialization...");
49
-
50
- // CRITICAL FIX: Don't reset isInitialized if already initialized
51
- // This prevents UI flash on re-initialization
52
- const { isInitialized: alreadyInitialized } = get();
53
- if (alreadyInitialized) {
54
- /* eslint-disable-next-line no-console */
55
- if (__DEV__)
56
- console.log("[LocalizationStore] Already initialized, skipping");
57
- return;
58
- }
59
-
60
- /* eslint-disable-next-line no-console */
61
- if (__DEV__)
62
- console.log("[LocalizationStore] Getting saved language preference...");
63
- // ✅ Get saved language preference (returns null if not exists)
64
- const savedLanguage = await StorageWrapper.getString(
65
- STORAGE_KEYS.LANGUAGE,
66
- DEFAULT_LANGUAGE,
67
- );
68
- /* eslint-disable-next-line no-console */
69
- if (__DEV__)
70
- console.log("[LocalizationStore] Saved language:", savedLanguage);
71
-
72
- // ✅ DEVICE LOCALE DETECTION: Use device locale on first launch
73
- let languageCode: string;
74
- if (savedLanguage && savedLanguage !== DEFAULT_LANGUAGE) {
75
- // User has previously selected a language → Use their choice
76
- languageCode = savedLanguage;
77
- /* eslint-disable-next-line no-console */
78
- if (__DEV__)
79
- console.log(
80
- "[LocalizationStore] Using saved language:",
81
- languageCode,
82
- );
83
- } else {
84
- /* eslint-disable-next-line no-console */
85
- if (__DEV__)
86
- console.log(
87
- "[LocalizationStore] First launch, detecting device locale...",
88
- );
89
- // First launch → Detect device locale automatically
90
- languageCode = getDeviceLocale();
91
- /* eslint-disable-next-line no-console */
92
- if (__DEV__)
93
- console.log(
94
- "[LocalizationStore] Detected device locale:",
95
- languageCode,
96
- );
97
- // Save detected locale for future launches
98
- await StorageWrapper.setString(STORAGE_KEYS.LANGUAGE, languageCode);
99
- }
100
-
101
- /* eslint-disable-next-line no-console */
102
- if (__DEV__)
103
- console.log("[LocalizationStore] Validating language code...");
104
- // ✅ DEFENSIVE: Validate language exists, fallback to default
105
- const language = getLanguageByCode(languageCode);
106
- const finalLanguage = language ? languageCode : DEFAULT_LANGUAGE;
107
- const finalLanguageObj = getLanguageByCode(finalLanguage);
108
- /* eslint-disable-next-line no-console */
109
- if (__DEV__)
110
- console.log("[LocalizationStore] Final language:", finalLanguage);
111
-
112
- /* eslint-disable-next-line no-console */
113
- if (__DEV__) console.log("[LocalizationStore] Changing i18n language...");
114
- // Only change language if i18n is available
115
- if (i18n && typeof i18n.changeLanguage === "function") {
116
- await i18n.changeLanguage(finalLanguage);
117
- /* eslint-disable-next-line no-console */
118
- if (__DEV__) console.log("[LocalizationStore] i18n language changed");
119
- } else {
120
- /* eslint-disable-next-line no-console */
121
- if (__DEV__)
122
- console.warn(
123
- "[LocalizationStore] i18n not available, skipping language change",
124
- );
125
- }
126
-
127
- set({
128
- currentLanguage: finalLanguage,
129
- isRTL: finalLanguageObj?.rtl || false,
130
- isInitialized: true, // ✅ Always set true to unblock UI
131
- });
132
- /* eslint-disable-next-line no-console */
133
- if (__DEV__)
134
- console.log(
135
- "[LocalizationStore] Initialization completed successfully",
136
- );
137
- } catch (error) {
138
- /* eslint-disable-next-line no-console */
139
- if (__DEV__)
140
- console.error("[LocalizationStore] Initialization error:", error);
141
- /* eslint-disable-next-line no-console */
142
- if (__DEV__)
143
- console.error("[LocalizationStore] Error details:", {
144
- message: error instanceof Error ? error.message : String(error),
145
- stack: error instanceof Error ? error.stack : "No stack",
146
- name: error instanceof Error ? error.name : "Unknown",
147
- });
148
- // Set initialized even on error to prevent blocking UI
149
- set({
150
- isInitialized: true,
151
- });
152
- throw error;
35
+ // ✅ CRITICAL FIX: Don't reset isInitialized if already initialized
36
+ // This prevents UI flash on re-initialization
37
+ const { isInitialized: alreadyInitialized } = get();
38
+ if (alreadyInitialized) return;
39
+
40
+ // Get saved language preference
41
+ const savedLanguage = await StorageWrapper.getString(STORAGE_KEYS.LANGUAGE, DEFAULT_LANGUAGE);
42
+
43
+ // DEVICE LOCALE DETECTION: Use device locale on first launch
44
+ let languageCode: string;
45
+ if (savedLanguage && savedLanguage !== DEFAULT_LANGUAGE) {
46
+ // User has previously selected a language → Use their choice
47
+ languageCode = savedLanguage;
48
+ } else {
49
+ // First launch → Detect device locale automatically
50
+ languageCode = getDeviceLocale();
51
+ // Save detected locale for future launches
52
+ await StorageWrapper.setString(STORAGE_KEYS.LANGUAGE, languageCode);
153
53
  }
54
+
55
+ // ✅ DEFENSIVE: Validate language exists, fallback to default
56
+ const language = getLanguageByCode(languageCode);
57
+ const finalLanguage = language ? languageCode : DEFAULT_LANGUAGE;
58
+ const finalLanguageObj = getLanguageByCode(finalLanguage);
59
+
60
+ await i18n.changeLanguage(finalLanguage);
61
+ set({
62
+ currentLanguage: finalLanguage,
63
+ isRTL: finalLanguageObj?.rtl || false,
64
+ isInitialized: true, // ✅ Always set true to unblock UI
65
+ });
154
66
  },
155
67
 
156
68
  /**
@@ -163,10 +75,8 @@ export const useLocalizationStore = create<LocalizationState>((set, get) => ({
163
75
  // ✅ DEFENSIVE: Early return if unsupported language
164
76
  if (!language) return;
165
77
 
166
- // Update i18n (only if available)
167
- if (i18n && typeof i18n.changeLanguage === "function") {
168
- await i18n.changeLanguage(languageCode);
169
- }
78
+ // Update i18n
79
+ await i18n.changeLanguage(languageCode);
170
80
 
171
81
  // Update state
172
82
  set({
@@ -174,7 +84,7 @@ export const useLocalizationStore = create<LocalizationState>((set, get) => ({
174
84
  isRTL: language.rtl || false,
175
85
  });
176
86
 
177
- // DRY: Single line replaces try/catch/logging
87
+ // Persist language preference
178
88
  await StorageWrapper.setString(STORAGE_KEYS.LANGUAGE, languageCode);
179
89
  },
180
90
  }));
@@ -195,19 +105,8 @@ export const useLocalization = () => {
195
105
 
196
106
  const currentLanguageObject = getLanguageByCode(currentLanguage);
197
107
 
198
- // Safe translation function - returns key if i18n not available
199
- const t = (key: string, options?: any): string => {
200
- if (i18n && typeof i18n.t === "function") {
201
- const result = i18n.t(key, options);
202
- // i18n.t can return string or object, ensure we return string
203
- return typeof result === "string" ? result : key;
204
- }
205
- // Fallback: return key if i18n not available
206
- return key;
207
- };
208
-
209
108
  return {
210
- t,
109
+ t: i18n.t.bind(i18n), // Translation function
211
110
  currentLanguage,
212
111
  currentLanguageObject,
213
112
  isRTL,