@umituz/react-native-localization 3.5.49 → 3.5.51

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.
Files changed (24) hide show
  1. package/package.json +5 -3
  2. package/src/infrastructure/components/LanguageSwitcher.styles.ts +40 -0
  3. package/src/infrastructure/components/LanguageSwitcher.tsx +38 -63
  4. package/src/infrastructure/components/__tests__/LanguageSwitcher.test.tsx +2 -2
  5. package/src/infrastructure/components/useLanguageNavigation.ts +2 -2
  6. package/src/infrastructure/components/useLanguageSwitcher.ts +3 -3
  7. package/src/infrastructure/config/DeviceLocale.ts +2 -2
  8. package/src/infrastructure/config/LanguageQuery.ts +9 -9
  9. package/src/infrastructure/config/__tests__/languagesData.test.ts +17 -17
  10. package/src/infrastructure/config/constants/defaultLanguages.ts +43 -0
  11. package/src/infrastructure/config/languages.ts +5 -5
  12. package/src/infrastructure/config/languagesData.ts +17 -136
  13. package/src/infrastructure/repository/LanguageRepository.ts +53 -0
  14. package/src/infrastructure/storage/LanguageInitializer.ts +3 -3
  15. package/src/infrastructure/storage/LanguageSwitcher.ts +2 -2
  16. package/src/infrastructure/storage/LocalizationStore.ts +47 -59
  17. package/src/infrastructure/storage/types/Language.ts +13 -0
  18. package/src/infrastructure/storage/types/LocalizationState.ts +3 -7
  19. package/src/presentation/components/LanguageItem.styles.ts +44 -0
  20. package/src/presentation/components/LanguageItem.tsx +2 -40
  21. package/src/presentation/components/SearchInput.styles.ts +34 -0
  22. package/src/presentation/components/SearchInput.tsx +1 -30
  23. package/src/presentation/screens/LanguageSelectionScreen.styles.ts +15 -0
  24. package/src/presentation/screens/LanguageSelectionScreen.tsx +3 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-localization",
3
- "version": "3.5.49",
3
+ "version": "3.5.51",
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",
@@ -31,7 +31,8 @@
31
31
  "i18next": ">=23.0.0",
32
32
  "react": ">=18.2.0",
33
33
  "react-i18next": ">=15.0.0",
34
- "react-native": ">=0.74.0"
34
+ "react-native": ">=0.74.0",
35
+ "zustand": ">=4.0.0"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@react-native-async-storage/async-storage": "~2.1.2",
@@ -42,7 +43,8 @@
42
43
  "react": "19.1.0",
43
44
  "react-i18next": "^15.2.0",
44
45
  "react-native": "0.81.5",
45
- "typescript": "~5.9.2"
46
+ "typescript": "~5.9.2",
47
+ "zustand": "^4.5.0"
46
48
  },
47
49
  "publishConfig": {
48
50
  "access": "public"
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Language Switcher Component Styles
3
+ */
4
+
5
+ import { StyleSheet } from 'react-native';
6
+
7
+ const DEFAULT_CONFIG = {
8
+ defaultIconSize: 20,
9
+ };
10
+
11
+ export const styles = StyleSheet.create({
12
+ container: {
13
+ flexDirection: 'row',
14
+ alignItems: 'center',
15
+ gap: 8,
16
+ paddingHorizontal: 4,
17
+ paddingVertical: 4,
18
+ },
19
+ disabled: {
20
+ opacity: 0.5,
21
+ },
22
+ flag: {
23
+ fontSize: DEFAULT_CONFIG.defaultIconSize,
24
+ textAlign: 'center',
25
+ },
26
+ languageName: {
27
+ fontSize: 14,
28
+ fontWeight: '600',
29
+ textAlign: 'center',
30
+ },
31
+ icon: {
32
+ fontSize: DEFAULT_CONFIG.defaultIconSize,
33
+ textAlign: 'center',
34
+ },
35
+ });
36
+
37
+ export const DEFAULT_CONFIG_VALUES = {
38
+ hitSlop: { top: 10, bottom: 10, left: 10, right: 10 } as const,
39
+ activeOpacity: 0.7,
40
+ };
@@ -4,8 +4,9 @@
4
4
  */
5
5
 
6
6
  import React, { useMemo } from 'react';
7
- import { TouchableOpacity, Text, StyleSheet } from 'react-native';
7
+ import { TouchableOpacity, Text } from 'react-native';
8
8
  import { useLanguageSwitcher } from './useLanguageSwitcher';
9
+ import { styles, DEFAULT_CONFIG_VALUES } from './LanguageSwitcher.styles';
9
10
 
10
11
  export interface LanguageSwitcherProps {
11
12
  showName?: boolean;
@@ -20,10 +21,39 @@ export interface LanguageSwitcherProps {
20
21
  accessibilityLabel?: string;
21
22
  }
22
23
 
23
- const DEFAULT_CONFIG = {
24
- defaultIconSize: 20,
25
- hitSlop: { top: 10, bottom: 10, left: 10, right: 10 } as const,
26
- activeOpacity: 0.7,
24
+ const renderContent = (
25
+ showFlag: boolean,
26
+ showName: boolean,
27
+ flag: string | undefined,
28
+ nativeName: string,
29
+ color: string | undefined,
30
+ iconStyle: any,
31
+ textStyle: any
32
+ ) => {
33
+ if (showFlag && showName) {
34
+ return (
35
+ <>
36
+ <Text style={[styles.flag, iconStyle]}>{flag}</Text>
37
+ <Text style={[styles.languageName, { color }, textStyle]}>
38
+ {nativeName}
39
+ </Text>
40
+ </>
41
+ );
42
+ }
43
+
44
+ if (showFlag) {
45
+ return <Text style={[styles.flag, iconStyle]}>{flag}</Text>;
46
+ }
47
+
48
+ if (showName) {
49
+ return (
50
+ <Text style={[styles.languageName, { color }, textStyle]}>
51
+ {nativeName}
52
+ </Text>
53
+ );
54
+ }
55
+
56
+ return <Text style={[styles.icon, { color }, iconStyle]}>🌐</Text>;
27
57
  };
28
58
 
29
59
  export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
@@ -40,8 +70,6 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
40
70
  }) => {
41
71
  const { currentLang, handlePress } = useLanguageSwitcher({ onPress, disabled });
42
72
 
43
- const iconColor = color;
44
-
45
73
  const accessibilityProps = useMemo(() => ({
46
74
  accessibilityRole: 'button' as const,
47
75
  accessibilityLabel: accessibilityLabel || `Current language: ${currentLang.nativeName}`,
@@ -49,72 +77,19 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
49
77
  accessible: true,
50
78
  }), [accessibilityLabel, currentLang.nativeName, disabled]);
51
79
 
52
- const renderContent = () => {
53
- if (showFlag && showName) {
54
- return (
55
- <>
56
- <Text style={[styles.flag, iconStyle]}>{currentLang.flag}</Text>
57
- <Text style={[styles.languageName, { color: iconColor }, textStyle]}>
58
- {currentLang.nativeName}
59
- </Text>
60
- </>
61
- );
62
- }
63
-
64
- if (showFlag) {
65
- return <Text style={[styles.flag, iconStyle]}>{currentLang.flag}</Text>;
66
- }
67
-
68
- if (showName) {
69
- return (
70
- <Text style={[styles.languageName, { color: iconColor }, textStyle]}>
71
- {currentLang.nativeName}
72
- </Text>
73
- );
74
- }
75
-
76
- return <Text style={[styles.icon, { color: iconColor }, iconStyle]}>🌐</Text>;
77
- };
78
-
79
80
  return (
80
81
  <TouchableOpacity
81
82
  style={[styles.container, style, disabled && styles.disabled]}
82
83
  onPress={handlePress}
83
- activeOpacity={disabled ? 1 : DEFAULT_CONFIG.activeOpacity}
84
- hitSlop={DEFAULT_CONFIG.hitSlop}
84
+ activeOpacity={disabled ? 1 : DEFAULT_CONFIG_VALUES.activeOpacity}
85
+ hitSlop={DEFAULT_CONFIG_VALUES.hitSlop}
85
86
  testID={testID}
86
87
  disabled={disabled}
87
88
  {...accessibilityProps}
88
89
  >
89
- {renderContent()}
90
+ {renderContent(showFlag, showName, currentLang.flag, currentLang.nativeName, color, iconStyle, textStyle)}
90
91
  </TouchableOpacity>
91
92
  );
92
93
  };
93
94
 
94
- const styles = StyleSheet.create({
95
- container: {
96
- flexDirection: 'row',
97
- alignItems: 'center',
98
- gap: 8,
99
- paddingHorizontal: 4,
100
- paddingVertical: 4,
101
- },
102
- disabled: {
103
- opacity: 0.5,
104
- },
105
- flag: {
106
- fontSize: DEFAULT_CONFIG.defaultIconSize,
107
- textAlign: 'center',
108
- },
109
- languageName: {
110
- fontSize: 14,
111
- fontWeight: '600',
112
- textAlign: 'center',
113
- },
114
- icon: {
115
- fontSize: DEFAULT_CONFIG.defaultIconSize,
116
- textAlign: 'center',
117
- },
118
- });
119
-
120
95
  export default LanguageSwitcher;
@@ -24,8 +24,8 @@ jest.mock('../../hooks/useLocalization', () => ({
24
24
  }),
25
25
  }));
26
26
 
27
- jest.mock('../../config/languagesData', () => ({
28
- languageRegistry: {
27
+ jest.mock('../../repository/LanguageRepository', () => ({
28
+ languageRepository: {
29
29
  getLanguageByCode: jest.fn(() => ({
30
30
  code: 'en-US',
31
31
  name: 'English',
@@ -1,13 +1,13 @@
1
1
  // @ts-ignore - Optional peer dependency
2
2
  import { useNavigation } from '@react-navigation/native';
3
3
  import { useLocalization } from '../hooks/useLocalization';
4
- import { languageRegistry } from '../config/languagesData';
4
+ import { languageRepository } from '../repository/LanguageRepository';
5
5
 
6
6
 
7
7
  export const useLanguageNavigation = (navigationScreen: string) => {
8
8
  const navigation = useNavigation();
9
9
  const { currentLanguage } = useLocalization();
10
- const currentLang = languageRegistry.getLanguageByCode(currentLanguage) || languageRegistry.getDefaultLanguage();
10
+ const currentLang = languageRepository.getLanguageByCode(currentLanguage) || languageRepository.getDefaultLanguage();
11
11
 
12
12
  const navigateToLanguageSelection = () => {
13
13
  if (navigation && navigationScreen) {
@@ -5,8 +5,8 @@
5
5
 
6
6
  import { useMemo, useCallback } from 'react';
7
7
  import { useLocalization } from '../hooks/useLocalization';
8
- import { languageRegistry } from '../config/languagesData';
9
- import type { Language } from '../storage/types/LocalizationState';
8
+ import { languageRepository } from '../repository/LanguageRepository';
9
+ import type { Language } from '../storage/types/Language';
10
10
 
11
11
  export interface UseLanguageSwitcherProps {
12
12
  onPress?: () => void;
@@ -17,7 +17,7 @@ export const useLanguageSwitcher = ({ onPress, disabled }: UseLanguageSwitcherPr
17
17
  const { currentLanguage } = useLocalization();
18
18
 
19
19
  const currentLang = useMemo((): Language => {
20
- return languageRegistry.getLanguageByCode(currentLanguage) || languageRegistry.getDefaultLanguage();
20
+ return languageRepository.getLanguageByCode(currentLanguage) || languageRepository.getDefaultLanguage();
21
21
  }, [currentLanguage]);
22
22
 
23
23
  const handlePress = useCallback(() => {
@@ -5,7 +5,7 @@
5
5
 
6
6
  import * as Localization from 'expo-localization';
7
7
  import { LOCALE_MAPPING } from './LocaleMapping';
8
- import { languageRegistry } from './languagesData';
8
+ import { languageRepository } from '../repository/LanguageRepository';
9
9
 
10
10
  export const DEFAULT_LANGUAGE = 'en-US';
11
11
 
@@ -36,7 +36,7 @@ export const getDeviceLocale = (): string => {
36
36
  }
37
37
 
38
38
  // Check if directly supported
39
- if (languageRegistry.isLanguageSupported(deviceLocale)) {
39
+ if (languageRepository.isLanguageSupported(deviceLocale)) {
40
40
  return deviceLocale;
41
41
  }
42
42
 
@@ -3,31 +3,31 @@
3
3
  * Provides functions to query and search languages
4
4
  */
5
5
 
6
- import { languageRegistry } from './languagesData';
7
- import type { Language } from '../storage/types/LocalizationState';
6
+ import { languageRepository } from '../repository/LanguageRepository';
7
+ import type { Language } from '../storage/types/Language';
8
8
 
9
- export const getSupportedLanguages = () => languageRegistry.getLanguages();
9
+ export const getSupportedLanguages = () => languageRepository.getLanguages();
10
10
 
11
11
  export const getLanguageByCode = (code: string): Language | undefined => {
12
- return languageRegistry.getLanguageByCode(code);
12
+ return languageRepository.getLanguageByCode(code);
13
13
  };
14
14
 
15
15
  export const isLanguageSupported = (code: string): boolean => {
16
- return languageRegistry.isLanguageSupported(code);
16
+ return languageRepository.isLanguageSupported(code);
17
17
  };
18
18
 
19
19
  export const getDefaultLanguage = (): Language => {
20
- const langs = languageRegistry.getLanguages();
20
+ const langs = languageRepository.getLanguages();
21
21
  const firstLang = langs[0];
22
22
  if (firstLang) return firstLang;
23
23
 
24
- // Final fallback to system defaults if registry is empty
25
- return languageRegistry.getDefaultLanguage();
24
+ // Final fallback to system defaults if repository is empty
25
+ return languageRepository.getDefaultLanguage();
26
26
  };
27
27
 
28
28
  export const searchLanguages = (query: string): Language[] => {
29
29
  const lowerQuery = query.toLowerCase();
30
- return languageRegistry.getLanguages().filter(
30
+ return languageRepository.getLanguages().filter(
31
31
  (lang) =>
32
32
  lang.name.toLowerCase().includes(lowerQuery) ||
33
33
  lang.nativeName.toLowerCase().includes(lowerQuery)
@@ -1,48 +1,48 @@
1
1
  /**
2
- * Simple tests for language registry
2
+ * Simple tests for language repository
3
3
  */
4
4
 
5
- import { languageRegistry } from '../../config/languagesData';
5
+ import { languageRepository } from '../../repository/LanguageRepository';
6
6
 
7
- describe('LanguageRegistry', () => {
7
+ describe('LanguageRepository', () => {
8
8
  beforeEach(() => {
9
- languageRegistry.clearLanguages();
9
+ languageRepository.clearLanguages();
10
10
  });
11
11
 
12
12
  it('should get default language', () => {
13
- const defaultLang = languageRegistry.getDefaultLanguage();
13
+ const defaultLang = languageRepository.getDefaultLanguage();
14
14
  expect(defaultLang).toBeDefined();
15
15
  expect(defaultLang.code).toBe('en-US');
16
16
  });
17
17
 
18
18
  it('should check if language is supported', () => {
19
- const supported = languageRegistry.isLanguageSupported('en-US');
19
+ const supported = languageRepository.isLanguageSupported('en-US');
20
20
  expect(supported).toBe(true);
21
21
  });
22
22
 
23
23
  it('should check if language is not supported', () => {
24
- const supported = languageRegistry.isLanguageSupported('unknown');
24
+ const supported = languageRepository.isLanguageSupported('unknown');
25
25
  expect(supported).toBe(false);
26
26
  });
27
27
 
28
28
  it('should get language by code', () => {
29
- const language = languageRegistry.getLanguageByCode('en-US');
29
+ const language = languageRepository.getLanguageByCode('en-US');
30
30
  expect(language).toBeDefined();
31
31
  expect(language?.code).toBe('en-US');
32
32
  });
33
33
 
34
34
  it('should return undefined for unknown code', () => {
35
- const language = languageRegistry.getLanguageByCode('unknown');
35
+ const language = languageRepository.getLanguageByCode('unknown');
36
36
  expect(language).toBeUndefined();
37
37
  });
38
38
 
39
39
  it('should search languages', () => {
40
- const results = languageRegistry.searchLanguages('english');
40
+ const results = languageRepository.searchLanguages('english');
41
41
  expect(Array.isArray(results)).toBe(true);
42
42
  });
43
43
 
44
44
  it('should get supported languages', () => {
45
- const languages = languageRegistry.getLanguages();
45
+ const languages = languageRepository.getLanguages();
46
46
  expect(Array.isArray(languages)).toBe(true);
47
47
  expect(languages.length).toBeGreaterThan(0);
48
48
  // Should now support many languages (29+)
@@ -50,19 +50,19 @@ describe('LanguageRegistry', () => {
50
50
  });
51
51
 
52
52
  it('should support newly added languages', () => {
53
- expect(languageRegistry.isLanguageSupported('cs-CZ')).toBe(true);
54
- expect(languageRegistry.isLanguageSupported('pt-BR')).toBe(true);
55
- expect(languageRegistry.isLanguageSupported('zh-TW')).toBe(true);
56
- expect(languageRegistry.isLanguageSupported('el-GR')).toBe(true);
53
+ expect(languageRepository.isLanguageSupported('cs-CZ')).toBe(true);
54
+ expect(languageRepository.isLanguageSupported('pt-BR')).toBe(true);
55
+ expect(languageRepository.isLanguageSupported('zh-TW')).toBe(true);
56
+ expect(languageRepository.isLanguageSupported('el-GR')).toBe(true);
57
57
  });
58
58
 
59
59
  it('should find language attributes correctly', () => {
60
- const czech = languageRegistry.getLanguageByCode('cs-CZ');
60
+ const czech = languageRepository.getLanguageByCode('cs-CZ');
61
61
  expect(czech).toBeDefined();
62
62
  expect(czech?.name).toBe('Czech');
63
63
  expect(czech?.flag).toBe('🇨🇿');
64
64
 
65
- const brazil = languageRegistry.getLanguageByCode('pt-BR');
65
+ const brazil = languageRepository.getLanguageByCode('pt-BR');
66
66
  expect(brazil).toBeDefined();
67
67
  expect(brazil?.name).toBe('Portuguese (Brazil)');
68
68
  });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Default Languages Configuration
3
+ * Applications can override this by providing their own language list
4
+ */
5
+
6
+ import type { Language } from '../../storage/types/Language';
7
+
8
+ export const DEFAULT_LANGUAGES: Language[] = [
9
+ { code: 'ar-SA', name: 'Arabic', nativeName: 'العربية', flag: '🇸🇦', isRTL: true },
10
+ { code: 'bg-BG', name: 'Bulgarian', nativeName: 'Български', flag: '🇧🇬', isRTL: false },
11
+ { code: 'cs-CZ', name: 'Czech', nativeName: 'Čeština', flag: '🇨🇿', isRTL: false },
12
+ { code: 'da-DK', name: 'Danish', nativeName: 'Dansk', flag: '🇩🇰', isRTL: false },
13
+ { code: 'de-DE', name: 'German', nativeName: 'Deutsch', flag: '🇩🇪', isRTL: false },
14
+ { code: 'el-GR', name: 'Greek', nativeName: 'Ελληνικά', flag: '🇬🇷', isRTL: false },
15
+ { code: 'en-US', name: 'English', nativeName: 'English', flag: '🇺🇸', isRTL: false },
16
+ { code: 'es-ES', name: 'Spanish', nativeName: 'Español', flag: '🇪🇸', isRTL: false },
17
+ { code: 'fi-FI', name: 'Finnish', nativeName: 'Suomi', flag: '🇫🇮', isRTL: false },
18
+ { code: 'fr-FR', name: 'French', nativeName: 'Français', flag: '🇫🇷', isRTL: false },
19
+ { code: 'hi-IN', name: 'Hindi', nativeName: 'हिन्दी', flag: '🇮🇳', isRTL: false },
20
+ { code: 'hr-HR', name: 'Croatian', nativeName: 'Hrvatski', flag: '🇭🇷', isRTL: false },
21
+ { code: 'hu-HU', name: 'Hungarian', nativeName: 'Magyar', flag: '🇭🇺', isRTL: false },
22
+ { code: 'id-ID', name: 'Indonesian', nativeName: 'Bahasa Indonesia', flag: '🇮', isRTL: false },
23
+ { code: 'it-IT', name: 'Italian', nativeName: 'Italiano', flag: '🇮🇹', isRTL: false },
24
+ { code: 'ja-JP', name: 'Japanese', nativeName: '日本語', flag: '🇯🇵', isRTL: false },
25
+ { code: 'ko-KR', name: 'Korean', nativeName: '한국어', flag: '🇰🇷', isRTL: false },
26
+ { code: 'ms-MY', name: 'Malay', nativeName: 'Bahasa Melayu', flag: '🇲🇾', isRTL: false },
27
+ { code: 'nl-NL', name: 'Dutch', nativeName: 'Nederlands', flag: '🇳🇱', isRTL: false },
28
+ { code: 'no-NO', name: 'Norwegian', nativeName: 'Norsk', flag: '🇳🇴', isRTL: false },
29
+ { code: 'pl-PL', name: 'Polish', nativeName: 'Polski', flag: '🇵🇱', isRTL: false },
30
+ { code: 'pt-BR', name: 'Portuguese (Brazil)', nativeName: 'Português (Brasil)', flag: '🇧🇷', isRTL: false },
31
+ { code: 'pt-PT', name: 'Portuguese', nativeName: 'Português', flag: '🇵🇹', isRTL: false },
32
+ { code: 'ro-RO', name: 'Romanian', nativeName: 'Română', flag: '🇷🇴', isRTL: false },
33
+ { code: 'ru-RU', name: 'Russian', nativeName: 'Русский', flag: '🇷🇺', isRTL: false },
34
+ { code: 'sk-SK', name: 'Slovak', nativeName: 'Slovenčina', flag: '🇸🇰', isRTL: false },
35
+ { code: 'sv-SE', name: 'Swedish', nativeName: 'Svenska', flag: '🇸🇪', isRTL: false },
36
+ { code: 'th-TH', name: 'Thai', nativeName: 'ไทย', flag: '🇹🇭', isRTL: false },
37
+ { code: 'tl-PH', name: 'Filipino', nativeName: 'Filipino', flag: '🇵🇭', isRTL: false },
38
+ { code: 'tr-TR', name: 'Turkish', nativeName: 'Türkçe', flag: '🇹🇷', isRTL: false },
39
+ { code: 'uk-UA', name: 'Ukrainian', nativeName: 'Українська', flag: '🇺🇦', isRTL: false },
40
+ { code: 'vi-VN', name: 'Vietnamese', nativeName: 'Tiếng Việt', flag: '🇻🇳', isRTL: false },
41
+ { code: 'zh-CN', name: 'Chinese (Simplified)', nativeName: '简体中文', flag: '🇨🇳', isRTL: false },
42
+ { code: 'zh-TW', name: 'Chinese (Traditional)', nativeName: '繁體中文', flag: '🇹🇼', isRTL: false },
43
+ ];
@@ -3,8 +3,8 @@
3
3
  * Central export point for all language-related functionality
4
4
  */
5
5
 
6
- import { languageRegistry } from './languagesData';
7
- import type { Language } from '../storage/types/LocalizationState';
6
+ import { languageRepository } from '../repository/LanguageRepository';
7
+ import type { Language } from '../storage/types/Language';
8
8
 
9
9
  // Re-export from DeviceLocale
10
10
  export { DEFAULT_LANGUAGE, getDeviceLocale } from './DeviceLocale';
@@ -22,7 +22,7 @@ export {
22
22
  export { LOCALE_MAPPING } from './LocaleMapping';
23
23
 
24
24
  // Backward compatibility
25
- export const getSUPPORTED_LANGUAGES = () => languageRegistry.getLanguages();
26
- export const getLANGUAGES = () => languageRegistry.getLanguages();
27
- export const SUPPORTED_LANGUAGES: Language[] = languageRegistry.getLanguages();
25
+ export const getSUPPORTED_LANGUAGES = () => languageRepository.getLanguages();
26
+ export const getLANGUAGES = () => languageRepository.getLanguages();
27
+ export const SUPPORTED_LANGUAGES: Language[] = languageRepository.getLanguages();
28
28
  export const LANGUAGES = SUPPORTED_LANGUAGES;
@@ -1,145 +1,26 @@
1
1
  /**
2
- * Language Configuration
3
- * Generic language interface and utilities for localization packages
4
- * This is a base configuration that can be extended by consuming applications
2
+ * Language Data Exports
3
+ * Centralized exports for language management
5
4
  */
6
5
 
7
- export interface Language {
8
- code: string;
9
- name: string;
10
- nativeName: string;
11
- flag?: string;
12
- isRTL?: boolean;
13
- }
6
+ import { languageRepository } from '../repository/LanguageRepository';
7
+ import { DEFAULT_LANGUAGES } from './constants/defaultLanguages';
8
+ import type { Language } from '../storage/types/Language';
14
9
 
15
- /**
16
- * Default language configuration
17
- * Applications can override this by providing their own language list
18
- */
19
- export const DEFAULT_LANGUAGES: Language[] = [
20
- { code: 'ar-SA', name: 'Arabic', nativeName: 'العربية', flag: '🇸🇦', isRTL: true },
21
- { code: 'bg-BG', name: 'Bulgarian', nativeName: 'Български', flag: '🇧🇬', isRTL: false },
22
- { code: 'cs-CZ', name: 'Czech', nativeName: 'Čeština', flag: '🇨🇿', isRTL: false },
23
- { code: 'da-DK', name: 'Danish', nativeName: 'Dansk', flag: '🇩🇰', isRTL: false },
24
- { code: 'de-DE', name: 'German', nativeName: 'Deutsch', flag: '🇩🇪', isRTL: false },
25
- { code: 'el-GR', name: 'Greek', nativeName: 'Ελληνικά', flag: '🇬🇷', isRTL: false },
26
- { code: 'en-US', name: 'English', nativeName: 'English', flag: '🇺🇸', isRTL: false },
27
- { code: 'es-ES', name: 'Spanish', nativeName: 'Español', flag: '🇪🇸', isRTL: false },
28
- { code: 'fi-FI', name: 'Finnish', nativeName: 'Suomi', flag: '🇫🇮', isRTL: false },
29
- { code: 'fr-FR', name: 'French', nativeName: 'Français', flag: '🇫🇷', isRTL: false },
30
- { code: 'hi-IN', name: 'Hindi', nativeName: 'हिन्दी', flag: '🇮🇳', isRTL: false },
31
- { code: 'hr-HR', name: 'Croatian', nativeName: 'Hrvatski', flag: '🇭🇷', isRTL: false },
32
- { code: 'hu-HU', name: 'Hungarian', nativeName: 'Magyar', flag: '🇭🇺', isRTL: false },
33
- { code: 'id-ID', name: 'Indonesian', nativeName: 'Bahasa Indonesia', flag: '🇮', isRTL: false },
34
- { code: 'it-IT', name: 'Italian', nativeName: 'Italiano', flag: '🇮🇹', isRTL: false },
35
- { code: 'ja-JP', name: 'Japanese', nativeName: '日本語', flag: '🇯🇵', isRTL: false },
36
- { code: 'ko-KR', name: 'Korean', nativeName: '한국어', flag: '🇰🇷', isRTL: false },
37
- { code: 'ms-MY', name: 'Malay', nativeName: 'Bahasa Melayu', flag: '🇲🇾', isRTL: false },
38
- { code: 'nl-NL', name: 'Dutch', nativeName: 'Nederlands', flag: '🇳🇱', isRTL: false },
39
- { code: 'no-NO', name: 'Norwegian', nativeName: 'Norsk', flag: '🇳🇴', isRTL: false },
40
- { code: 'pl-PL', name: 'Polish', nativeName: 'Polski', flag: '🇵🇱', isRTL: false },
41
- { code: 'pt-BR', name: 'Portuguese (Brazil)', nativeName: 'Português (Brasil)', flag: '🇧🇷', isRTL: false },
42
- { code: 'pt-PT', name: 'Portuguese', nativeName: 'Português', flag: '🇵🇹', isRTL: false },
43
- { code: 'ro-RO', name: 'Romanian', nativeName: 'Română', flag: '🇷🇴', isRTL: false },
44
- { code: 'ru-RU', name: 'Russian', nativeName: 'Русский', flag: '🇷🇺', isRTL: false },
45
- { code: 'sk-SK', name: 'Slovak', nativeName: 'Slovenčina', flag: '🇸🇰', isRTL: false },
46
- { code: 'sv-SE', name: 'Swedish', nativeName: 'Svenska', flag: '🇸🇪', isRTL: false },
47
- { code: 'th-TH', name: 'Thai', nativeName: 'ไทย', flag: '🇹🇭', isRTL: false },
48
- { code: 'tl-PH', name: 'Filipino', nativeName: 'Filipino', flag: '🇵🇭', isRTL: false },
49
- { code: 'tr-TR', name: 'Turkish', nativeName: 'Türkçe', flag: '🇹🇷', isRTL: false },
50
- { code: 'uk-UA', name: 'Ukrainian', nativeName: 'Українська', flag: '🇺🇦', isRTL: false },
51
- { code: 'vi-VN', name: 'Vietnamese', nativeName: 'Tiếng Việt', flag: '🇻🇳', isRTL: false },
52
- { code: 'zh-CN', name: 'Chinese (Simplified)', nativeName: '简体中文', flag: '🇨🇳', isRTL: false },
53
- { code: 'zh-TW', name: 'Chinese (Traditional)', nativeName: '繁體中文', flag: '🇹🇼', isRTL: false },
54
- ];
55
-
56
- /**
57
- * Language registry for dynamic language management
58
- */
59
- class LanguageRegistry {
60
- private languages: Language[] = [...DEFAULT_LANGUAGES];
61
-
62
- /**
63
- * Register new languages
64
- */
65
- registerLanguages(languages: Language[]): void {
66
- this.languages = [...this.languages, ...languages];
67
- }
68
-
69
- /**
70
- * Get all registered languages
71
- */
72
- getLanguages(): Language[] {
73
- return [...this.languages];
74
- }
75
-
76
- /**
77
- * Clear all languages (reset to default)
78
- */
79
- clearLanguages(): void {
80
- this.languages = [...DEFAULT_LANGUAGES];
81
- }
82
-
83
- /**
84
- * Get language by code
85
- */
86
- getLanguageByCode(code: string): Language | undefined {
87
- return this.languages.find(lang => lang.code === code);
88
- }
89
-
90
- /**
91
- * Search languages by name or native name
92
- */
93
- searchLanguages(query: string): Language[] {
94
- const lowerQuery = query.toLowerCase();
95
- return this.languages.filter(
96
- lang =>
97
- lang.name.toLowerCase().includes(lowerQuery) ||
98
- lang.nativeName.toLowerCase().includes(lowerQuery)
99
- );
100
- }
101
-
102
- /**
103
- * Check if language is supported
104
- */
105
- isLanguageSupported(code: string): boolean {
106
- return this.languages.some(lang => lang.code === code);
107
- }
108
-
109
- /**
110
- * Get default language
111
- * Prioritizes en-US, otherwise returns first available
112
- */
113
- getDefaultLanguage(): Language {
114
- const en = this.languages.find(l => l.code === 'en-US');
115
- if (en) return en;
116
- const first = this.languages[0];
117
- if (first) return first;
118
- const systemDefault = DEFAULT_LANGUAGES[0];
119
- if (systemDefault) return systemDefault;
120
- throw new Error('No languages registered in registry or defaults');
121
- }
122
- }
123
-
124
- // Singleton instance
125
- export const languageRegistry = new LanguageRegistry();
10
+ export { languageRepository };
11
+ export { DEFAULT_LANGUAGES };
12
+ export type { Language };
126
13
 
127
- // Export convenience functions that delegate to registry
128
- export const getLanguageByCode = (code: string): Language | undefined => {
129
- return languageRegistry.getLanguageByCode(code);
130
- };
14
+ export const getLanguageByCode = (code: string) =>
15
+ languageRepository.getLanguageByCode(code);
131
16
 
132
- export const searchLanguages = (query: string): Language[] => {
133
- return languageRegistry.searchLanguages(query);
134
- };
17
+ export const searchLanguages = (query: string) =>
18
+ languageRepository.searchLanguages(query);
135
19
 
136
- export const isLanguageSupported = (code: string): boolean => {
137
- return languageRegistry.isLanguageSupported(code);
138
- };
20
+ export const isLanguageSupported = (code: string) =>
21
+ languageRepository.isLanguageSupported(code);
139
22
 
140
- export const getDefaultLanguage = (): Language => {
141
- return languageRegistry.getDefaultLanguage();
142
- };
23
+ export const getDefaultLanguage = () =>
24
+ languageRepository.getDefaultLanguage();
143
25
 
144
- // Legacy exports for backward compatibility
145
- export const LANGUAGES = languageRegistry.getLanguages();
26
+ export const LANGUAGES = languageRepository.getLanguages();
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Language Repository
3
+ * Manages language data with repository pattern
4
+ * Provides dynamic language management for multiple applications
5
+ */
6
+
7
+ import type { Language } from '../storage/types/Language';
8
+ import { DEFAULT_LANGUAGES } from '../config/constants/defaultLanguages';
9
+
10
+ class LanguageRepository {
11
+ private languages: Language[] = [...DEFAULT_LANGUAGES];
12
+
13
+ registerLanguages(languages: Language[]): void {
14
+ this.languages = [...this.languages, ...languages];
15
+ }
16
+
17
+ getLanguages(): Language[] {
18
+ return [...this.languages];
19
+ }
20
+
21
+ clearLanguages(): void {
22
+ this.languages = [...DEFAULT_LANGUAGES];
23
+ }
24
+
25
+ getLanguageByCode(code: string): Language | undefined {
26
+ return this.languages.find(lang => lang.code === code);
27
+ }
28
+
29
+ searchLanguages(query: string): Language[] {
30
+ const lowerQuery = query.toLowerCase();
31
+ return this.languages.filter(
32
+ lang =>
33
+ lang.name.toLowerCase().includes(lowerQuery) ||
34
+ lang.nativeName.toLowerCase().includes(lowerQuery)
35
+ );
36
+ }
37
+
38
+ isLanguageSupported(code: string): boolean {
39
+ return this.languages.some(lang => lang.code === code);
40
+ }
41
+
42
+ getDefaultLanguage(): Language {
43
+ const en = this.languages.find(l => l.code === 'en-US');
44
+ if (en) return en;
45
+ const first = this.languages[0];
46
+ if (first) return first;
47
+ const systemDefault = DEFAULT_LANGUAGES[0];
48
+ if (systemDefault) return systemDefault;
49
+ throw new Error('No languages registered in repository or defaults');
50
+ }
51
+ }
52
+
53
+ export const languageRepository = new LanguageRepository();
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { storageRepository } from '@umituz/react-native-storage';
11
11
  import i18n from '../config/i18n';
12
- import { languageRegistry } from '../config/languagesData';
12
+ import { languageRepository } from '../repository/LanguageRepository';
13
13
  import { getDeviceLocale } from '../config/languages';
14
14
 
15
15
  const LANGUAGE_STORAGE_KEY = '@localization:language';
@@ -49,9 +49,9 @@ export class LanguageInitializer {
49
49
  languageCode: string;
50
50
  isRTL: boolean;
51
51
  }> {
52
- const language = languageRegistry.getLanguageByCode(languageCode);
52
+ const language = languageRepository.getLanguageByCode(languageCode);
53
53
  const finalLanguageCode = language ? languageCode : 'en-US';
54
- const finalLanguageObj = languageRegistry.getLanguageByCode(finalLanguageCode);
54
+ const finalLanguageObj = languageRepository.getLanguageByCode(finalLanguageCode);
55
55
 
56
56
  await i18n.changeLanguage(finalLanguageCode);
57
57
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { storageRepository } from '@umituz/react-native-storage';
10
10
  import i18n from '../config/i18n';
11
- import { languageRegistry } from '../config/languagesData';
11
+ import { languageRepository } from '../repository/LanguageRepository';
12
12
 
13
13
  const LANGUAGE_STORAGE_KEY = '@localization:language';
14
14
 
@@ -20,7 +20,7 @@ export class LanguageSwitcher {
20
20
  languageCode: string;
21
21
  isRTL: boolean;
22
22
  }> {
23
- const language = languageRegistry.getLanguageByCode(languageCode);
23
+ const language = languageRepository.getLanguageByCode(languageCode);
24
24
 
25
25
  await i18n.changeLanguage(languageCode);
26
26
  await storageRepository.setString(LANGUAGE_STORAGE_KEY, languageCode);
@@ -3,85 +3,73 @@
3
3
  * Creates and manages localization state with proper separation of concerns
4
4
  */
5
5
 
6
- import { createStore } from '@umituz/react-native-storage';
6
+ import { create } from 'zustand';
7
7
  import type { LocalizationState, LocalizationActions, LocalizationGetters } from './types/LocalizationState';
8
8
  import { LanguageInitializer } from './LanguageInitializer';
9
9
  import { LanguageSwitcher } from './LanguageSwitcher';
10
- import { languageRegistry } from '../config/languagesData';
10
+ import { languageRepository } from '../repository/LanguageRepository';
11
11
 
12
- type LocalizationStoreActions = LocalizationActions & LocalizationGetters;
12
+ type LocalizationStoreType = LocalizationState & LocalizationActions & LocalizationGetters;
13
13
 
14
- const initialLocalizationState: LocalizationState = {
14
+ export const useLocalizationStore = create<LocalizationStoreType>((set, get) => ({
15
+ // State
15
16
  currentLanguage: 'en-US',
16
17
  isRTL: false,
17
18
  isInitialized: false,
18
- supportedLanguages: languageRegistry.getLanguages(),
19
- };
19
+ supportedLanguages: languageRepository.getLanguages(),
20
20
 
21
- // Create singleton instance
22
- export const useLocalizationStore = createStore<LocalizationState, LocalizationStoreActions>({
23
- name: 'localization-store',
24
- initialState: initialLocalizationState,
25
- persist: false,
26
- actions: (set, get) => ({
27
- // Actions
28
- initialize: async () => {
29
- const { isInitialized: alreadyInitialized } = get();
30
- if (alreadyInitialized) {
31
- return;
32
- }
21
+ // Actions
22
+ initialize: async () => {
23
+ const { isInitialized: alreadyInitialized } = get();
24
+ if (alreadyInitialized) {
25
+ return;
26
+ }
33
27
 
34
- try {
35
- const result = await LanguageInitializer.initialize();
36
-
37
- set({
38
- currentLanguage: result.languageCode,
39
- isRTL: result.isRTL,
40
- isInitialized: true,
41
- });
42
- } catch {
43
- set({
44
- currentLanguage: 'en-US',
45
- isRTL: false,
46
- isInitialized: true,
47
- });
48
- }
49
- },
50
-
51
- setLanguage: async (languageCode: string) => {
52
- const result = await LanguageSwitcher.switchLanguage(languageCode);
28
+ try {
29
+ const result = await LanguageInitializer.initialize();
53
30
 
54
31
  set({
55
32
  currentLanguage: result.languageCode,
56
33
  isRTL: result.isRTL,
34
+ isInitialized: true,
57
35
  });
58
- },
59
-
60
- reset: () => {
36
+ } catch {
61
37
  set({
62
38
  currentLanguage: 'en-US',
63
39
  isRTL: false,
64
- isInitialized: false,
40
+ isInitialized: true,
65
41
  });
66
- },
42
+ }
43
+ },
67
44
 
68
- // Getters
69
- getCurrentLanguage: () => {
70
- const { currentLanguage } = get();
71
- return languageRegistry.getLanguageByCode(currentLanguage);
72
- },
45
+ setLanguage: async (languageCode: string) => {
46
+ const result = await LanguageSwitcher.switchLanguage(languageCode);
73
47
 
74
- isLanguageSupported: (code: string) => {
75
- return languageRegistry.isLanguageSupported(code);
76
- },
48
+ set({
49
+ currentLanguage: result.languageCode,
50
+ isRTL: result.isRTL,
51
+ });
52
+ },
77
53
 
78
- getSupportedLanguages: () => {
79
- return languageRegistry.getLanguages();
80
- },
81
- }),
82
- });
54
+ reset: () => {
55
+ set({
56
+ currentLanguage: 'en-US',
57
+ isRTL: false,
58
+ isInitialized: false,
59
+ });
60
+ },
83
61
 
84
- /**
85
- * @deprecated Use useLocalizationStore directly
86
- */
87
- export const createLocalizationStore = () => useLocalizationStore;
62
+ // Getters
63
+ getCurrentLanguage: () => {
64
+ const { currentLanguage } = get();
65
+ return languageRepository.getLanguageByCode(currentLanguage);
66
+ },
67
+
68
+ isLanguageSupported: (code: string) => {
69
+ return languageRepository.isLanguageSupported(code);
70
+ },
71
+
72
+ getSupportedLanguages: () => {
73
+ return languageRepository.getLanguages();
74
+ },
75
+ }));
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Language Type
3
+ * Generic language interface for localization packages
4
+ * This is a base configuration that can be extended by consuming applications
5
+ */
6
+
7
+ export interface Language {
8
+ code: string;
9
+ name: string;
10
+ nativeName: string;
11
+ flag?: string;
12
+ isRTL?: boolean;
13
+ }
@@ -3,13 +3,9 @@
3
3
  * Defines the shape of localization state management
4
4
  */
5
5
 
6
- export interface Language {
7
- code: string;
8
- name: string;
9
- nativeName: string;
10
- flag?: string;
11
- isRTL?: boolean;
12
- }
6
+ import type { Language } from './Language';
7
+
8
+ export type { Language };
13
9
 
14
10
  export interface LocalizationState {
15
11
  currentLanguage: string;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Language Item Component Styles
3
+ */
4
+
5
+ import { StyleSheet } from 'react-native';
6
+
7
+ export const styles = StyleSheet.create({
8
+ languageItem: {
9
+ flexDirection: 'row',
10
+ alignItems: 'center',
11
+ justifyContent: 'space-between',
12
+ padding: 16,
13
+ borderRadius: 12,
14
+ borderWidth: 1,
15
+ marginBottom: 8,
16
+ },
17
+ selectedLanguageItem: {
18
+ borderWidth: 2,
19
+ },
20
+ languageContent: {
21
+ flexDirection: 'row',
22
+ alignItems: 'center',
23
+ flex: 1,
24
+ },
25
+ flag: {
26
+ fontSize: 24,
27
+ marginRight: 16,
28
+ },
29
+ languageText: {
30
+ flex: 1,
31
+ },
32
+ nativeName: {
33
+ fontSize: 16,
34
+ fontWeight: '600',
35
+ marginBottom: 2,
36
+ },
37
+ languageName: {
38
+ fontSize: 14,
39
+ },
40
+ checkIcon: {
41
+ fontSize: 18,
42
+ fontWeight: 'bold',
43
+ },
44
+ });
@@ -17,7 +17,8 @@ import {
17
17
  } from 'react-native';
18
18
  // @ts-ignore - Optional peer dependency
19
19
  import { useAppDesignTokens } from '@umituz/react-native-design-system';
20
- import type { Language } from '../../infrastructure/storage/types/LocalizationState';
20
+ import type { Language } from '../../infrastructure/storage/types/Language';
21
+ import { styles } from './LanguageItem.styles';
21
22
 
22
23
  interface LanguageItemProps {
23
24
  item: Language;
@@ -91,42 +92,3 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
91
92
  </TouchableOpacity>
92
93
  );
93
94
  };
94
-
95
- const styles = StyleSheet.create({
96
- languageItem: {
97
- flexDirection: 'row',
98
- alignItems: 'center',
99
- justifyContent: 'space-between',
100
- padding: 16,
101
- borderRadius: 12,
102
- borderWidth: 1,
103
- marginBottom: 8,
104
- },
105
- selectedLanguageItem: {
106
- borderWidth: 2,
107
- },
108
- languageContent: {
109
- flexDirection: 'row',
110
- alignItems: 'center',
111
- flex: 1,
112
- },
113
- flag: {
114
- fontSize: 24,
115
- marginRight: 16,
116
- },
117
- languageText: {
118
- flex: 1,
119
- },
120
- nativeName: {
121
- fontSize: 16,
122
- fontWeight: '600',
123
- marginBottom: 2,
124
- },
125
- languageName: {
126
- fontSize: 14,
127
- },
128
- checkIcon: {
129
- fontSize: 18,
130
- fontWeight: 'bold',
131
- },
132
- });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Search Input Component Styles
3
+ */
4
+
5
+ import { StyleSheet } from 'react-native';
6
+
7
+ export const styles = StyleSheet.create({
8
+ searchContainer: {
9
+ flexDirection: 'row',
10
+ alignItems: 'center',
11
+ marginHorizontal: 20,
12
+ marginBottom: 24,
13
+ paddingHorizontal: 16,
14
+ paddingVertical: 12,
15
+ borderRadius: 12,
16
+ borderWidth: 1,
17
+ },
18
+ searchIcon: {
19
+ marginRight: 12,
20
+ fontSize: 16,
21
+ },
22
+ searchInput: {
23
+ flex: 1,
24
+ fontSize: 16,
25
+ padding: 0,
26
+ fontWeight: '500',
27
+ },
28
+ clearButton: {
29
+ padding: 4,
30
+ },
31
+ clearIcon: {
32
+ fontSize: 14,
33
+ },
34
+ });
@@ -11,13 +11,13 @@ import {
11
11
  TextInput,
12
12
  TouchableOpacity,
13
13
  Text,
14
- StyleSheet,
15
14
  type StyleProp,
16
15
  type ViewStyle,
17
16
  type TextStyle,
18
17
  } from 'react-native';
19
18
  // @ts-ignore - Optional peer dependency
20
19
  import { useAppDesignTokens } from '@umituz/react-native-design-system';
20
+ import { styles } from './SearchInput.styles';
21
21
 
22
22
  interface SearchInputProps {
23
23
  value: string;
@@ -76,32 +76,3 @@ export const SearchInput: React.FC<SearchInputProps> = ({
76
76
  </View>
77
77
  );
78
78
  };
79
-
80
- const styles = StyleSheet.create({
81
- searchContainer: {
82
- flexDirection: 'row',
83
- alignItems: 'center',
84
- marginHorizontal: 20,
85
- marginBottom: 24,
86
- paddingHorizontal: 16,
87
- paddingVertical: 12,
88
- borderRadius: 12,
89
- borderWidth: 1,
90
- },
91
- searchIcon: {
92
- marginRight: 12,
93
- fontSize: 16,
94
- },
95
- searchInput: {
96
- flex: 1,
97
- fontSize: 16,
98
- padding: 0,
99
- fontWeight: '500',
100
- },
101
- clearButton: {
102
- padding: 4,
103
- },
104
- clearIcon: {
105
- fontSize: 14,
106
- },
107
- });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Language Selection Screen Styles
3
+ */
4
+
5
+ import { StyleSheet } from 'react-native';
6
+
7
+ export const styles = StyleSheet.create({
8
+ container: {
9
+ flex: 1,
10
+ },
11
+ listContent: {
12
+ paddingHorizontal: 20,
13
+ paddingBottom: 32,
14
+ },
15
+ });
@@ -11,7 +11,8 @@ import { useAppDesignTokens } from '@umituz/react-native-design-system';
11
11
  import { useLanguageSelection } from '../../infrastructure/hooks/useLanguageSelection';
12
12
  import { LanguageItem } from '../components/LanguageItem';
13
13
  import { SearchInput } from '../components/SearchInput';
14
- import type { Language } from '../../infrastructure/storage/types/LocalizationState';
14
+ import type { Language } from '../../infrastructure/storage/types/Language';
15
+ import { styles } from './LanguageSelectionScreen.styles';
15
16
 
16
17
  interface LanguageSelectionScreenProps {
17
18
  renderLanguageItem?: (item: Language, isSelected: boolean, onSelect: (code: string) => void) => React.ReactNode;
@@ -105,14 +106,4 @@ export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = (
105
106
  return Container ? <Container>{content}</Container> : content;
106
107
  };
107
108
 
108
- const styles = StyleSheet.create({
109
- container: {
110
- flex: 1,
111
- },
112
- listContent: {
113
- paddingHorizontal: 20,
114
- paddingBottom: 32,
115
- },
116
- });
117
-
118
- export default LanguageSelectionScreen;
109
+ export default LanguageSelectionScreen;