@umituz/react-native-settings 5.2.26 → 5.2.28
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.28",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Translation Hook
|
|
3
3
|
*
|
|
4
|
-
* Provides translation function with proper language change reactivity
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - Type-safe translation function
|
|
4
|
+
* Provides translation function with proper language change reactivity.
|
|
5
|
+
* Keys use dot notation only: "namespace.key.subkey"
|
|
6
|
+
* The first segment before the dot is the i18next namespace.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import { useCallback } from 'react';
|
|
11
10
|
import { useTranslation } from 'react-i18next';
|
|
12
11
|
import i18n from '../config/i18n';
|
|
12
|
+
import { devWarn } from '../../../../utils/devUtils';
|
|
13
13
|
|
|
14
14
|
export interface TranslationOptions {
|
|
15
15
|
count?: number;
|
|
@@ -19,12 +19,11 @@ export interface TranslationOptions {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Hook for translation functionality
|
|
23
|
-
* Uses react-i18next for automatic language change reactivity
|
|
22
|
+
* Hook for translation functionality.
|
|
23
|
+
* Uses react-i18next for automatic language change reactivity.
|
|
24
24
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* - t('namespace.key.subkey') - auto-detected namespace (first segment before dot)
|
|
25
|
+
* Keys must use dot notation: t('namespace.key.subkey')
|
|
26
|
+
* The first segment is the i18next namespace: t('common.ok'), t('settings.title')
|
|
28
27
|
*/
|
|
29
28
|
export const useTranslationFunction = () => {
|
|
30
29
|
const { t: i18nextT, ready } = useTranslation(undefined, { i18n });
|
|
@@ -38,50 +37,20 @@ export const useTranslationFunction = () => {
|
|
|
38
37
|
return options.defaultValue || key;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
// Convert dot notation to i18next namespace:key format
|
|
41
|
+
// "namespace.key.subkey" → i18next "namespace:key.subkey"
|
|
42
|
+
const firstDotIndex = key.indexOf('.');
|
|
43
|
+
const i18nextKey = firstDotIndex > 0
|
|
44
|
+
? `${key.substring(0, firstDotIndex)}:${key.substring(firstDotIndex + 1)}`
|
|
45
|
+
: key;
|
|
43
46
|
|
|
44
|
-
//
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
finalResult = typeof result === 'string' ? result : key;
|
|
48
|
-
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
49
|
-
} else {
|
|
50
|
-
// Auto-detect namespace from first dot segment
|
|
51
|
-
const firstDotIndex = key.indexOf('.');
|
|
52
|
-
if (firstDotIndex > 0) {
|
|
53
|
-
const potentialNamespace = key.substring(0, firstDotIndex);
|
|
54
|
-
const restOfKey = key.substring(firstDotIndex + 1);
|
|
55
|
-
const hasNamespace = i18n.hasResourceBundle(i18n.language, potentialNamespace);
|
|
56
|
-
|
|
57
|
-
if (hasNamespace) {
|
|
58
|
-
const namespacedKey = `${potentialNamespace}:${restOfKey}`;
|
|
59
|
-
const namespacedResult = i18nextT(namespacedKey, options);
|
|
60
|
-
|
|
61
|
-
if (namespacedResult !== namespacedKey && namespacedResult !== restOfKey) {
|
|
62
|
-
finalResult = typeof namespacedResult === 'string' ? namespacedResult : key;
|
|
63
|
-
translationFound = true;
|
|
64
|
-
} else {
|
|
65
|
-
// Fallback to original key
|
|
66
|
-
const result = i18nextT(key, options);
|
|
67
|
-
finalResult = typeof result === 'string' ? result : key;
|
|
68
|
-
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
// Fallback to original key
|
|
72
|
-
const result = i18nextT(key, options);
|
|
73
|
-
finalResult = typeof result === 'string' ? result : key;
|
|
74
|
-
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
75
|
-
}
|
|
76
|
-
} else {
|
|
77
|
-
// Fallback to original key
|
|
78
|
-
const result = i18nextT(key, options);
|
|
79
|
-
finalResult = typeof result === 'string' ? result : key;
|
|
80
|
-
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
81
|
-
}
|
|
47
|
+
// Missing translation is a critical issue — warn in development
|
|
48
|
+
if (!i18n.exists(i18nextKey)) {
|
|
49
|
+
devWarn(`[i18n] Missing translation: "${key}"`);
|
|
82
50
|
}
|
|
83
51
|
|
|
84
|
-
|
|
52
|
+
const result = i18nextT(i18nextKey, options);
|
|
53
|
+
return typeof result === 'string' ? result : (options.defaultValue ?? key);
|
|
85
54
|
}, [i18nextT, ready]);
|
|
86
55
|
|
|
87
56
|
return {
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
import { useMemo } from 'react';
|
|
13
13
|
import { createStore, storageService } from '@umituz/react-native-design-system';
|
|
14
|
-
import { excludeTransientState } from '../../../../infrastructure/storage/storeConfig';
|
|
15
14
|
import type { Reminder, QuietHoursConfig, NotificationPreferences } from '../services/types';
|
|
16
15
|
|
|
17
16
|
// ============================================================================
|
|
@@ -86,7 +86,7 @@ export interface BaseStoreState {
|
|
|
86
86
|
export const excludeTransientState = <T extends BaseStoreState>(
|
|
87
87
|
state: T
|
|
88
88
|
): Partial<T> => {
|
|
89
|
-
const { isLoading, isInitialized, ...persistedState } = state;
|
|
89
|
+
const { isLoading: _isLoading, isInitialized: _isInitialized, ...persistedState } = state;
|
|
90
90
|
return persistedState as Partial<T>;
|
|
91
91
|
};
|
|
92
92
|
|