@umituz/react-native-localization 3.5.8 → 3.5.10
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 +2 -4
- package/src/infrastructure/hooks/useTranslation.ts +53 -17
- package/src/presentation/components/LanguageItem.tsx +1 -1
- package/src/presentation/components/LanguageSection.tsx +5 -2
- package/src/presentation/components/SearchInput.tsx +1 -1
- package/src/presentation/screens/LanguageSelectionScreen.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-localization",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.10",
|
|
4
4
|
"description": "Generic localization system for React Native apps with i18n support",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -42,7 +42,6 @@
|
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@expo/vector-icons": ">=14.0.0",
|
|
44
44
|
"@react-navigation/native": ">=6.0.0",
|
|
45
|
-
"@umituz/react-native-design-system-theme": "*",
|
|
46
45
|
"@umituz/react-native-filesystem": "latest",
|
|
47
46
|
"@umituz/react-native-storage": "latest",
|
|
48
47
|
"expo-localization": ">=15.0.0",
|
|
@@ -67,7 +66,6 @@
|
|
|
67
66
|
"@testing-library/react-native": "^13.3.3",
|
|
68
67
|
"@types/react": "^18.2.45",
|
|
69
68
|
"@types/react-native": "^0.73.0",
|
|
70
|
-
"@umituz/react-native-design-system-theme": "^1.8.0",
|
|
71
69
|
"@umituz/react-native-filesystem": "^1.4.0",
|
|
72
70
|
"@umituz/react-native-storage": "^2.4.0",
|
|
73
71
|
"expo-localization": "~15.0.0",
|
|
@@ -93,4 +91,4 @@
|
|
|
93
91
|
"README.md",
|
|
94
92
|
"LICENSE"
|
|
95
93
|
]
|
|
96
|
-
}
|
|
94
|
+
}
|
|
@@ -35,35 +35,71 @@ export const useTranslationFunction = () => {
|
|
|
35
35
|
: defaultValueOrOptions || {};
|
|
36
36
|
|
|
37
37
|
if (!ready || !i18n.isInitialized) {
|
|
38
|
+
if (__DEV__) {
|
|
39
|
+
console.log(`[i18n] ⏳ Not ready - Key: "${key}" → Fallback: "${options.defaultValue || key}"`);
|
|
40
|
+
}
|
|
38
41
|
return options.defaultValue || key;
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
let finalResult: string;
|
|
45
|
+
let translationFound = false;
|
|
46
|
+
let usedKey = key;
|
|
47
|
+
|
|
41
48
|
// If key already has namespace separator (:), use as-is
|
|
42
49
|
if (key.includes(':')) {
|
|
43
50
|
const result = i18nextT(key, options);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
finalResult = typeof result === 'string' ? result : key;
|
|
52
|
+
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
53
|
+
usedKey = key;
|
|
54
|
+
} else {
|
|
55
|
+
// Auto-detect namespace from first dot segment
|
|
56
|
+
const firstDotIndex = key.indexOf('.');
|
|
57
|
+
if (firstDotIndex > 0) {
|
|
58
|
+
const potentialNamespace = key.substring(0, firstDotIndex);
|
|
59
|
+
const restOfKey = key.substring(firstDotIndex + 1);
|
|
60
|
+
const hasNamespace = i18n.hasResourceBundle(i18n.language, potentialNamespace);
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
if (hasNamespace) {
|
|
63
|
+
const namespacedKey = `${potentialNamespace}:${restOfKey}`;
|
|
64
|
+
const namespacedResult = i18nextT(namespacedKey, options);
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
if (namespacedResult !== namespacedKey && namespacedResult !== restOfKey) {
|
|
67
|
+
finalResult = typeof namespacedResult === 'string' ? namespacedResult : key;
|
|
68
|
+
translationFound = true;
|
|
69
|
+
usedKey = namespacedKey;
|
|
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
|
+
usedKey = key;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
// Fallback to original key
|
|
79
|
+
const result = i18nextT(key, options);
|
|
80
|
+
finalResult = typeof result === 'string' ? result : key;
|
|
81
|
+
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
82
|
+
usedKey = key;
|
|
60
83
|
}
|
|
84
|
+
} else {
|
|
85
|
+
// Fallback to original key
|
|
86
|
+
const result = i18nextT(key, options);
|
|
87
|
+
finalResult = typeof result === 'string' ? result : key;
|
|
88
|
+
translationFound = finalResult !== key && finalResult !== options.defaultValue;
|
|
89
|
+
usedKey = key;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Development mode logging
|
|
94
|
+
if (__DEV__) {
|
|
95
|
+
if (translationFound) {
|
|
96
|
+
console.log(`[i18n] ✅ Found - Key: "${usedKey}" → "${finalResult}"`);
|
|
97
|
+
} else {
|
|
98
|
+
console.warn(`[i18n] ⚠️ Missing - Key: "${usedKey}" → Fallback: "${finalResult}"`);
|
|
61
99
|
}
|
|
62
100
|
}
|
|
63
101
|
|
|
64
|
-
|
|
65
|
-
const result = i18nextT(key, options);
|
|
66
|
-
return typeof result === 'string' ? result : key;
|
|
102
|
+
return finalResult;
|
|
67
103
|
}, [i18nextT, ready]);
|
|
68
104
|
|
|
69
105
|
return {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
type TextStyle,
|
|
17
17
|
} from 'react-native';
|
|
18
18
|
// @ts-ignore - Optional peer dependency
|
|
19
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system
|
|
19
|
+
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
20
20
|
import type { Language } from '../../infrastructure/storage/types/LocalizationState';
|
|
21
21
|
|
|
22
22
|
interface LanguageItemProps {
|
|
@@ -5,7 +5,7 @@ import { Feather } from '@expo/vector-icons';
|
|
|
5
5
|
// @ts-ignore - Optional peer dependency
|
|
6
6
|
import { useNavigation } from '@react-navigation/native';
|
|
7
7
|
// @ts-ignore - Optional peer dependency
|
|
8
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system
|
|
8
|
+
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
9
9
|
import { useLocalization } from '../../infrastructure/hooks/useLocalization';
|
|
10
10
|
import { getLanguageByCode } from '../../infrastructure/config/languages';
|
|
11
11
|
|
|
@@ -20,11 +20,13 @@ export interface LanguageSectionConfig {
|
|
|
20
20
|
export interface LanguageSectionProps {
|
|
21
21
|
config?: LanguageSectionConfig;
|
|
22
22
|
containerStyle?: ViewStyle;
|
|
23
|
+
sectionTitle?: string;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export const LanguageSection: React.FC<LanguageSectionProps> = ({
|
|
26
27
|
config,
|
|
27
28
|
containerStyle,
|
|
29
|
+
sectionTitle,
|
|
28
30
|
}) => {
|
|
29
31
|
const navigation = useNavigation();
|
|
30
32
|
const tokens = useAppDesignTokens();
|
|
@@ -33,6 +35,7 @@ export const LanguageSection: React.FC<LanguageSectionProps> = ({
|
|
|
33
35
|
|
|
34
36
|
const route = config?.route || 'LanguageSelection';
|
|
35
37
|
const title = config?.title || t('settings.languageSelection.title') || 'Language';
|
|
38
|
+
const displaySectionTitle = sectionTitle || title;
|
|
36
39
|
const description = config?.description || '';
|
|
37
40
|
|
|
38
41
|
const currentLang = getLanguageByCode(currentLanguage);
|
|
@@ -47,7 +50,7 @@ export const LanguageSection: React.FC<LanguageSectionProps> = ({
|
|
|
47
50
|
|
|
48
51
|
return (
|
|
49
52
|
<View style={[styles.sectionContainer, { backgroundColor: colors.surface }, containerStyle]}>
|
|
50
|
-
<Text style={[styles.sectionTitle, { color: colors.textPrimary }]}>{
|
|
53
|
+
<Text style={[styles.sectionTitle, { color: colors.textPrimary }]}>{displaySectionTitle}</Text>
|
|
51
54
|
|
|
52
55
|
<Pressable
|
|
53
56
|
style={({ pressed }) => [
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
type TextStyle,
|
|
18
18
|
} from 'react-native';
|
|
19
19
|
// @ts-ignore - Optional peer dependency
|
|
20
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system
|
|
20
|
+
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
21
21
|
|
|
22
22
|
interface SearchInputProps {
|
|
23
23
|
value: string;
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from 'react-native';
|
|
15
15
|
// @ts-ignore - Optional peer dependency
|
|
16
16
|
import { useNavigation } from '@react-navigation/native';
|
|
17
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system
|
|
17
|
+
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
18
18
|
import { useLocalization, searchLanguages, Language } from '../../index';
|
|
19
19
|
import { LanguageItem } from '../components/LanguageItem';
|
|
20
20
|
import { SearchInput } from '../components/SearchInput';
|