@fadyshawky/react-native-magic 2.0.5 → 2.0.7
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 +1 -1
- package/template/App.tsx +21 -16
- package/template/ios/reactnativemagic/AppDelegate.mm +5 -0
- package/template/src/common/ImageResources.g.ts +1 -33
- package/template/src/common/components/Background.tsx +7 -7
- package/template/src/common/components/Container.tsx +7 -10
- package/template/src/common/localization/LocalizationProvider.tsx +14 -17
- package/template/src/common/localization/RTLInitializer.tsx +90 -0
- package/template/src/common/localization/intlFormatter.ts +37 -0
- package/template/src/common/localization/localization.ts +1 -3
- package/template/src/common/localization/translations/commonLocalization.ts +11 -81
- package/template/src/common/localization/translations/emptyLocalization.ts +6 -2
- package/template/src/common/localization/translations/errorsLocalization.ts +33 -13
- package/template/src/common/localization/translations/homeLocalization.ts +4 -24
- package/template/src/common/localization/translations/loginLocalization.ts +26 -29
- package/template/src/common/localization/translations/mainNavigationLocalization.ts +2 -2
- package/template/src/common/localization/translations/onboardingLocalization.ts +40 -9
- package/template/src/common/localization/translations/otpLocalization.ts +8 -8
- package/template/src/common/localization/translations/pagesLocalization.ts +13 -1
- package/template/src/common/localization/translations/passwordLocalization.ts +3 -3
- package/template/src/common/localization/translations/profileLocalization.ts +4 -4
- package/template/src/core/store/app/appSlice.ts +2 -2
- package/template/src/core/store/app/appState.ts +1 -1
- package/template/src/core/theme/colors.ts +106 -70
- package/template/src/core/theme/commonConsts.ts +1 -1
- package/template/src/core/theme/commonSizes.ts +119 -94
- package/template/src/core/theme/commonStyles.ts +22 -22
- package/template/src/core/theme/fonts.ts +13 -14
- package/template/src/core/theme/shadows.ts +135 -0
- package/template/src/core/theme/themes.ts +386 -75
- package/template/src/core/theme/types.ts +201 -15
- package/template/src/navigation/HeaderComponents.tsx +6 -30
- package/template/src/navigation/MainNavigation.tsx +2 -3
- package/template/src/navigation/MainStack.tsx +6 -97
- package/template/src/screens/Login/Login.tsx +5 -7
- package/template/src/screens/OTP/OTPScreen.tsx +12 -13
- package/template/src/screens/home/HomeScreen.tsx +2 -295
- package/template/src/screens/profile/Profile.tsx +2 -290
- package/template/src/common/localization/translations/posLocalization.ts +0 -196
- package/template/src/components/PrinterExample.js +0 -226
- package/template/src/core/store/Categories/categoryActions.ts +0 -33
- package/template/src/core/store/Categories/categorySlice.ts +0 -75
- package/template/src/core/store/Categories/categoryState.ts +0 -41
- package/template/src/core/store/Providers/providersActions.ts +0 -102
- package/template/src/core/store/Providers/providersSlice.ts +0 -136
- package/template/src/core/store/Providers/providersState.ts +0 -37
- package/template/src/core/store/Services/servicesActions.ts +0 -191
- package/template/src/core/store/Services/servicesSlice.ts +0 -205
- package/template/src/core/store/Services/servicesState.ts +0 -466
- package/template/src/modules/SunmiCard.js +0 -212
- package/template/src/modules/SunmiPrepaid.ts +0 -122
- package/template/src/screens/Categories/Categories.tsx +0 -141
- package/template/src/screens/Categories/hooks/useCategoriesData.ts +0 -33
- package/template/src/screens/Categories/types.ts +0 -7
- package/template/src/screens/Favorites/Favorites.tsx +0 -130
- package/template/src/screens/ForceChangePassword/ForceChangePasswordScreen.tsx +0 -155
- package/template/src/screens/History/History.tsx +0 -430
- package/template/src/screens/History/hooks/useHistoryData.ts +0 -49
- package/template/src/screens/History/types.ts +0 -7
- package/template/src/screens/InquiredBill/InquiredBill.tsx +0 -443
- package/template/src/screens/InquiredBill/hooks/useInquiredData.ts +0 -91
- package/template/src/screens/PaymentConfirmation/PaymentConfirmation.tsx +0 -326
- package/template/src/screens/Providers/Providers.tsx +0 -166
- package/template/src/screens/Providers/hooks/useProvidersData.ts +0 -33
- package/template/src/screens/Providers/types.ts +0 -7
- package/template/src/screens/ReceiptScreen/ReceiptScreen.tsx +0 -181
- package/template/src/screens/ReceiptScreen/hooks/useReceiptData.ts +0 -46
- package/template/src/screens/ReceiptScreen/utils/utils.tsx +0 -156
- package/template/src/screens/Services/Services.tsx +0 -144
- package/template/src/screens/Services/hooks/useServicesData.ts +0 -41
- package/template/src/screens/SingleService/Components/FawryInputs.tsx +0 -446
- package/template/src/screens/SingleService/SingleService.tsx +0 -229
- package/template/src/screens/SingleService/hooks/useServiceData.ts +0 -164
- package/template/src/services/SunmiPrinterInternal.js +0 -268
- package/template/src/types/sunmiPrepaid.d.ts +0 -20
- package/template/src/utils/SunmiPrinter.ts +0 -442
- package/template/src/utils/feesCalculator.ts +0 -92
package/package.json
CHANGED
package/template/App.tsx
CHANGED
|
@@ -11,7 +11,8 @@ import {SafeAreaProvider} from 'react-native-safe-area-context';
|
|
|
11
11
|
import {Provider} from 'react-redux';
|
|
12
12
|
import {PersistGate} from 'redux-persist/integration/react';
|
|
13
13
|
import {LocalizationProvider} from './src/common/localization/LocalizationProvider';
|
|
14
|
-
import {
|
|
14
|
+
import {RTLInitializer} from './src/common/localization/RTLInitializer';
|
|
15
|
+
import {useAppSelector} from './src/core/store/reduxHelpers';
|
|
15
16
|
import {persistor, store} from './src/core/store/store';
|
|
16
17
|
import {ThemeProvider, useTheme} from './src/core/theme/ThemeProvider';
|
|
17
18
|
import AppNavigator from './src/navigation/MainNavigation';
|
|
@@ -20,17 +21,23 @@ LogBox.ignoreAllLogs();
|
|
|
20
21
|
|
|
21
22
|
const ThemedApp = () => {
|
|
22
23
|
const {theme} = useTheme();
|
|
24
|
+
const {language} = useAppSelector(state => state.app);
|
|
25
|
+
|
|
23
26
|
return (
|
|
24
|
-
<
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
<RTLInitializer>
|
|
28
|
+
<LocalizationProvider initialLanguage={language}>
|
|
29
|
+
<SafeAreaProvider>
|
|
30
|
+
<SafeAreaView style={{position: 'absolute'}} />
|
|
31
|
+
<StatusBar
|
|
32
|
+
barStyle={theme.mode === 'dark' ? 'light-content' : 'dark-content'}
|
|
33
|
+
backgroundColor={theme.colors.background_2}
|
|
34
|
+
/>
|
|
35
|
+
<SheetProvider>
|
|
36
|
+
<AppNavigator />
|
|
37
|
+
</SheetProvider>
|
|
38
|
+
</SafeAreaProvider>
|
|
39
|
+
</LocalizationProvider>
|
|
40
|
+
</RTLInitializer>
|
|
34
41
|
);
|
|
35
42
|
};
|
|
36
43
|
|
|
@@ -38,11 +45,9 @@ function App(): React.JSX.Element {
|
|
|
38
45
|
return (
|
|
39
46
|
<Provider store={store}>
|
|
40
47
|
<PersistGate loading={null} persistor={persistor}>
|
|
41
|
-
<
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
</ThemeProvider>
|
|
45
|
-
</LocalizationProvider>
|
|
48
|
+
<ThemeProvider initialTheme="dark">
|
|
49
|
+
<ThemedApp />
|
|
50
|
+
</ThemeProvider>
|
|
46
51
|
</PersistGate>
|
|
47
52
|
</Provider>
|
|
48
53
|
);
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
#import "AppDelegate.h"
|
|
2
2
|
|
|
3
3
|
#import <React/RCTBundleURLProvider.h>
|
|
4
|
+
#import <React/RCTI18nUtil.h>
|
|
4
5
|
|
|
5
6
|
@implementation AppDelegate
|
|
6
7
|
|
|
7
8
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
|
8
9
|
{
|
|
10
|
+
|
|
11
|
+
[[RCTI18nUtil sharedInstance] allowRTL:YES];
|
|
12
|
+
[[RCTI18nUtil sharedInstance] forceRTL:YES];
|
|
13
|
+
|
|
9
14
|
self.moduleName = @"reactnativemagic";
|
|
10
15
|
// You can add your custom initial props in the dictionary below.
|
|
11
16
|
// They will be passed down to the ViewController used by React Native.
|
|
@@ -9,36 +9,4 @@ import {ImageURISource} from 'react-native';
|
|
|
9
9
|
* https://github.com/svbutko/react-native-image-resource-generator
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
export class ImageResources {
|
|
13
|
-
static readonly account: ImageURISource = require('../../resources/images/Account.png');
|
|
14
|
-
static readonly arrows: ImageURISource = require('../../resources/images/Arrows.png');
|
|
15
|
-
static readonly background_2: ImageURISource = require('../../resources/images/Background_2.png');
|
|
16
|
-
static readonly balance: ImageURISource = require('../../resources/images/Balance.png');
|
|
17
|
-
static readonly commission: ImageURISource = require('../../resources/images/Commission.png');
|
|
18
|
-
static readonly display: ImageURISource = require('../../resources/images/Display.png');
|
|
19
|
-
static readonly en: ImageURISource = require('../../resources/images/EN.png');
|
|
20
|
-
static readonly favourite_active: ImageURISource = require('../../resources/images/Favourite_Active.png');
|
|
21
|
-
static readonly favourite_inactive: ImageURISource = require('../../resources/images/Favourite_Inactive.png');
|
|
22
|
-
static readonly favourites: ImageURISource = require('../../resources/images/Favourites.png');
|
|
23
|
-
static readonly financials: ImageURISource = require('../../resources/images/Financials.png');
|
|
24
|
-
static readonly language: ImageURISource = require('../../resources/images/Language.png');
|
|
25
|
-
static readonly neo_pay_plus_logo: ImageURISource = require('../../resources/images/Neo_Pay_Plus_Logo.png');
|
|
26
|
-
static readonly services: ImageURISource = require('../../resources/images/Services.png');
|
|
27
|
-
static readonly splash_screen: ImageURISource = require('../../resources/images/Splash_Screen.png');
|
|
28
|
-
static readonly ar: ImageURISource = require('../../resources/images/ar.png');
|
|
29
|
-
static readonly arrow_left: ImageURISource = require('../../resources/images/arrow_left.png');
|
|
30
|
-
static readonly arrow_right: ImageURISource = require('../../resources/images/arrow_right.png');
|
|
31
|
-
static readonly dark: ImageURISource = require('../../resources/images/dark.png');
|
|
32
|
-
static readonly dark_background_1: ImageURISource = require('../../resources/images/dark_background_1.png');
|
|
33
|
-
static readonly dark_splash_logo: ImageURISource = require('../../resources/images/dark_splash_logo.png');
|
|
34
|
-
static readonly full_ammount: ImageURISource = require('../../resources/images/full_ammount.png');
|
|
35
|
-
static readonly header_logo: ImageURISource = require('../../resources/images/header_logo.png');
|
|
36
|
-
static readonly light: ImageURISource = require('../../resources/images/light.png');
|
|
37
|
-
static readonly light_background_1: ImageURISource = require('../../resources/images/light_background_1.png');
|
|
38
|
-
static readonly light_header_logo: ImageURISource = require('../../resources/images/light_header_logo.png');
|
|
39
|
-
static readonly light_splash_logo: ImageURISource = require('../../resources/images/light_splash_logo.png');
|
|
40
|
-
static readonly partial_ammount: ImageURISource = require('../../resources/images/partial_ammount.png');
|
|
41
|
-
static readonly receipt_logo: ImageURISource = require('../../resources/images/receipt_logo.png');
|
|
42
|
-
static readonly receipt_logo_transparent: ImageURISource = require('../../resources/images/receipt_logo_transparent.png');
|
|
43
|
-
static readonly repeat: ImageURISource = require('../../resources/images/repeat.png');
|
|
44
|
-
}
|
|
12
|
+
export class ImageResources {}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React, {FC, memo} from 'react';
|
|
2
2
|
import {ImageBackground, StyleSheet, View, ViewStyle} from 'react-native';
|
|
3
|
+
import {KeyboardAwareScrollViewProps} from 'react-native-keyboard-aware-scroll-view';
|
|
3
4
|
import {useTheme} from '../../core/theme/ThemeProvider';
|
|
4
|
-
import {ImageResources} from '../ImageResources.g';
|
|
5
5
|
import {Container} from './Container';
|
|
6
|
-
import {KeyboardAwareScrollViewProps} from 'react-native-keyboard-aware-scroll-view';
|
|
7
6
|
|
|
8
7
|
interface BackgroundProps
|
|
9
8
|
extends Omit<KeyboardAwareScrollViewProps, 'contentContainerStyle'> {
|
|
@@ -46,7 +45,7 @@ export const Background: FC<BackgroundProps> = memo(
|
|
|
46
45
|
<View
|
|
47
46
|
style={[
|
|
48
47
|
styles.container,
|
|
49
|
-
{backgroundColor: theme.colors.
|
|
48
|
+
{backgroundColor: theme.colors.background_2},
|
|
50
49
|
]}>
|
|
51
50
|
{content}
|
|
52
51
|
</View>
|
|
@@ -55,10 +54,11 @@ export const Background: FC<BackgroundProps> = memo(
|
|
|
55
54
|
|
|
56
55
|
return (
|
|
57
56
|
<View
|
|
58
|
-
style={[
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
style={[
|
|
58
|
+
styles.container,
|
|
59
|
+
{backgroundColor: theme.colors.background_2},
|
|
60
|
+
]}>
|
|
61
|
+
<ImageBackground source={0} style={styles.container}>
|
|
62
62
|
{content}
|
|
63
63
|
</ImageBackground>
|
|
64
64
|
</View>
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import React, {forwardRef} from 'react';
|
|
2
2
|
import {
|
|
3
|
-
StyleSheet,
|
|
4
|
-
ViewStyle,
|
|
5
|
-
Platform,
|
|
6
|
-
KeyboardAvoidingView,
|
|
7
|
-
ScrollView,
|
|
8
|
-
View,
|
|
9
3
|
ImageBackground,
|
|
10
4
|
ImageSourcePropType,
|
|
5
|
+
KeyboardAvoidingView,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
View,
|
|
8
|
+
ViewStyle,
|
|
11
9
|
} from 'react-native';
|
|
12
10
|
import {
|
|
13
11
|
KeyboardAwareScrollView,
|
|
14
12
|
KeyboardAwareScrollViewProps,
|
|
15
13
|
} from 'react-native-keyboard-aware-scroll-view';
|
|
16
|
-
import {useTheme} from '../../core/theme/ThemeProvider';
|
|
17
14
|
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
18
|
-
import {
|
|
15
|
+
import {useTheme} from '../../core/theme/ThemeProvider';
|
|
19
16
|
|
|
20
17
|
interface ContainerProps extends Partial<KeyboardAwareScrollViewProps> {
|
|
21
18
|
children: React.ReactNode;
|
|
@@ -41,7 +38,7 @@ export const Container = forwardRef<KeyboardAwareScrollView, ContainerProps>(
|
|
|
41
38
|
withoutScroll = false,
|
|
42
39
|
backgroundColor,
|
|
43
40
|
withoutBackgroundImage = false,
|
|
44
|
-
backgroundImage =
|
|
41
|
+
backgroundImage = 0,
|
|
45
42
|
extendedBackground = false,
|
|
46
43
|
...scrollViewProps
|
|
47
44
|
},
|
|
@@ -50,7 +47,7 @@ export const Container = forwardRef<KeyboardAwareScrollView, ContainerProps>(
|
|
|
50
47
|
const {theme} = useTheme();
|
|
51
48
|
const insets = useSafeAreaInsets();
|
|
52
49
|
const Wrapper = useSafeArea ? SafeAreaView : View;
|
|
53
|
-
const bgColor = backgroundColor || theme.colors.
|
|
50
|
+
const bgColor = backgroundColor || theme.colors.background_2;
|
|
54
51
|
|
|
55
52
|
const content = (
|
|
56
53
|
<Wrapper
|
|
@@ -46,41 +46,42 @@ export const LocalizationProvider: React.FC<LocalizationProviderProps> = ({
|
|
|
46
46
|
storedIsRTL !== undefined ? storedIsRTL : currentLanguage === Languages.ar,
|
|
47
47
|
);
|
|
48
48
|
|
|
49
|
+
// Update RTL state when stored values change
|
|
49
50
|
useEffect(() => {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if (storedIsRTL !== undefined) {
|
|
52
|
+
setIsRTL(storedIsRTL);
|
|
53
|
+
} else if (storedLanguage) {
|
|
54
|
+
setIsRTL(storedLanguage === Languages.ar);
|
|
55
|
+
}
|
|
56
|
+
}, [storedLanguage, storedIsRTL]);
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
I18nManager.allowRTL(shouldBeRTL);
|
|
58
|
-
I18nManager.forceRTL(shouldBeRTL);
|
|
59
|
-
}
|
|
58
|
+
// Set language utility when currentLanguage changes
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (currentLanguage) {
|
|
61
|
+
setLanguageUtil(currentLanguage);
|
|
60
62
|
}
|
|
61
63
|
}, [currentLanguage]);
|
|
62
64
|
|
|
63
65
|
const changeLanguage = (language: Languages) => {
|
|
64
|
-
// Only restart if the language is actually changing
|
|
65
66
|
if (language !== currentLanguage) {
|
|
67
|
+
console.log('Changing language from', currentLanguage, 'to', language);
|
|
68
|
+
|
|
66
69
|
setCurrentLanguage(language);
|
|
67
70
|
dispatch(setLanguageAction(language));
|
|
68
71
|
|
|
69
72
|
// Set RTL configuration before restart
|
|
70
73
|
const shouldBeRTL = language === Languages.ar;
|
|
71
74
|
if (I18nManager.isRTL !== shouldBeRTL) {
|
|
75
|
+
console.log('Language change requires RTL update:', shouldBeRTL);
|
|
72
76
|
I18nManager.allowRTL(shouldBeRTL);
|
|
73
77
|
I18nManager.forceRTL(shouldBeRTL);
|
|
74
78
|
|
|
75
79
|
// Restart the app to apply RTL/LTR changes properly
|
|
76
|
-
// Small delay to ensure settings are applied
|
|
77
80
|
setTimeout(() => {
|
|
78
81
|
try {
|
|
79
|
-
// Check if RNRestart is available
|
|
80
82
|
if (RNRestart && typeof RNRestart.restart === 'function') {
|
|
81
83
|
RNRestart.restart();
|
|
82
84
|
} else if (Platform.OS === 'android') {
|
|
83
|
-
// Fallback for Android using DevSettings
|
|
84
85
|
const DevSettings = NativeModules.DevSettings;
|
|
85
86
|
if (DevSettings && DevSettings.reload) {
|
|
86
87
|
DevSettings.reload();
|
|
@@ -103,7 +104,6 @@ export const LocalizationProvider: React.FC<LocalizationProviderProps> = ({
|
|
|
103
104
|
const keys = key.split('.');
|
|
104
105
|
let result: any = localization[section];
|
|
105
106
|
|
|
106
|
-
// If the key has dot notation (e.g., 'registration.title'), navigate through the object
|
|
107
107
|
if (keys.length > 1) {
|
|
108
108
|
for (const k of keys) {
|
|
109
109
|
result = result[k];
|
|
@@ -111,7 +111,6 @@ export const LocalizationProvider: React.FC<LocalizationProviderProps> = ({
|
|
|
111
111
|
return result || key;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
// Simple key
|
|
115
114
|
return result[key] || key;
|
|
116
115
|
} catch (error) {
|
|
117
116
|
console.warn(
|
|
@@ -139,13 +138,11 @@ export const useLocalization = () => {
|
|
|
139
138
|
return context;
|
|
140
139
|
};
|
|
141
140
|
|
|
142
|
-
// Shorthand hook for translations
|
|
143
141
|
export const useTranslation = () => {
|
|
144
142
|
const {t} = useLocalization();
|
|
145
143
|
return t;
|
|
146
144
|
};
|
|
147
145
|
|
|
148
|
-
// Hook to get RTL status
|
|
149
146
|
export const useRTL = () => {
|
|
150
147
|
const {isRTL} = useLocalization();
|
|
151
148
|
return isRTL;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, {useEffect, useState} from 'react';
|
|
2
|
+
import {I18nManager, Platform, NativeModules} from 'react-native';
|
|
3
|
+
import {useAppSelector} from '../../core/store/reduxHelpers';
|
|
4
|
+
import {Languages} from './localization';
|
|
5
|
+
|
|
6
|
+
interface RTLInitializerProps {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const RTLInitializer: React.FC<RTLInitializerProps> = ({children}) => {
|
|
11
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
12
|
+
const {language, isRTL} = useAppSelector(state => state.app);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const initializeRTL = () => {
|
|
16
|
+
console.log('=== RTL Initializer - Starting initialization ===');
|
|
17
|
+
console.log('Stored language:', language);
|
|
18
|
+
console.log('Stored isRTL:', isRTL);
|
|
19
|
+
console.log('Current I18nManager.isRTL:', I18nManager.isRTL);
|
|
20
|
+
console.log('Current I18nManager.forceRTL:', I18nManager.forceRTL);
|
|
21
|
+
|
|
22
|
+
// Determine the correct RTL setting with better logic
|
|
23
|
+
let shouldBeRTL: boolean;
|
|
24
|
+
|
|
25
|
+
if (isRTL !== undefined) {
|
|
26
|
+
// Use stored RTL setting if available (highest priority)
|
|
27
|
+
shouldBeRTL = isRTL;
|
|
28
|
+
console.log('✅ Using stored isRTL setting:', shouldBeRTL);
|
|
29
|
+
} else if (language) {
|
|
30
|
+
// Use stored language to determine RTL
|
|
31
|
+
shouldBeRTL = language === Languages.ar;
|
|
32
|
+
console.log('✅ Using language-based RTL setting:', shouldBeRTL);
|
|
33
|
+
} else {
|
|
34
|
+
// Fall back to default (Arabic/RTL)
|
|
35
|
+
shouldBeRTL = true;
|
|
36
|
+
console.log('✅ Using default RTL setting:', shouldBeRTL);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Apply RTL setting if it differs from current
|
|
40
|
+
if (I18nManager.isRTL !== shouldBeRTL) {
|
|
41
|
+
console.log(
|
|
42
|
+
'🔄 Updating I18nManager RTL from',
|
|
43
|
+
I18nManager.isRTL,
|
|
44
|
+
'to',
|
|
45
|
+
shouldBeRTL,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Force the RTL setting
|
|
49
|
+
I18nManager.allowRTL(shouldBeRTL);
|
|
50
|
+
I18nManager.forceRTL(shouldBeRTL);
|
|
51
|
+
|
|
52
|
+
// Double-check the setting was applied
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
console.log(
|
|
55
|
+
' Verification - I18nManager.isRTL after update:',
|
|
56
|
+
I18nManager.isRTL,
|
|
57
|
+
);
|
|
58
|
+
if (I18nManager.isRTL !== shouldBeRTL) {
|
|
59
|
+
console.warn('⚠️ RTL setting was not applied correctly!');
|
|
60
|
+
} else {
|
|
61
|
+
console.log('✅ RTL setting applied successfully');
|
|
62
|
+
}
|
|
63
|
+
}, 100);
|
|
64
|
+
} else {
|
|
65
|
+
console.log(
|
|
66
|
+
'✅ I18nManager RTL setting is already correct:',
|
|
67
|
+
I18nManager.isRTL,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Mark as initialized
|
|
72
|
+
setIsInitialized(true);
|
|
73
|
+
console.log('=== RTL Initializer - Initialization complete ===');
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Wait longer to ensure Redux state is fully hydrated
|
|
77
|
+
// Increased timeout to handle slower devices
|
|
78
|
+
const timer = setTimeout(initializeRTL, 800);
|
|
79
|
+
return () => clearTimeout(timer);
|
|
80
|
+
}, [language, isRTL]);
|
|
81
|
+
|
|
82
|
+
// Don't render children until RTL is initialized
|
|
83
|
+
if (!isInitialized) {
|
|
84
|
+
console.log('⏳ RTL Initializer: Waiting for initialization...');
|
|
85
|
+
return null; // or a loading screen
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log('🚀 RTL Initializer: Rendering children');
|
|
89
|
+
return <>{children}</>;
|
|
90
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Intl from 'intl';
|
|
2
|
+
import {getLanguage} from './localization';
|
|
3
|
+
// eslint-disable-next-line import/no-unassigned-import
|
|
4
|
+
import 'intl/locale-data/jsonp/en';
|
|
5
|
+
|
|
6
|
+
export function formatPercent(percent: number | string): string {
|
|
7
|
+
const formatter = new Intl.NumberFormat(getLanguage(), {
|
|
8
|
+
style: 'percent',
|
|
9
|
+
minimumFractionDigits: 0,
|
|
10
|
+
maximumFractionDigits: 2,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return formatter.format(Number(percent) / 100);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function formatCurrency(
|
|
17
|
+
price: number | string,
|
|
18
|
+
currency?: string,
|
|
19
|
+
): string {
|
|
20
|
+
const formatter = new Intl.NumberFormat(getLanguage(), {
|
|
21
|
+
style: 'currency',
|
|
22
|
+
minimumFractionDigits: 0,
|
|
23
|
+
maximumFractionDigits: 2,
|
|
24
|
+
currency: currency || 'USD',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return formatter.format(Number(price));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function formatDecimal(value: number | string): string {
|
|
31
|
+
const formatter = new Intl.NumberFormat(getLanguage(), {
|
|
32
|
+
style: 'decimal',
|
|
33
|
+
minimumFractionDigits: 0,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return formatter.format(Number(value));
|
|
37
|
+
}
|
|
@@ -8,12 +8,11 @@ import {setDateLocale} from './dateFormatter';
|
|
|
8
8
|
import {loginLocalization} from './translations/loginLocalization';
|
|
9
9
|
import {homeLocalization} from './translations/homeLocalization';
|
|
10
10
|
import {profileLocalization} from './translations/profileLocalization';
|
|
11
|
+
import {I18nManager} from 'react-native';
|
|
11
12
|
import {otpLocalization} from './translations/otpLocalization';
|
|
12
13
|
import {passwordLocalization} from './translations/passwordLocalization';
|
|
13
14
|
import {navigationLocalization} from './translations/navigationLocalization';
|
|
14
15
|
import {mainNavigationLocalization} from './translations/mainNavigationLocalization';
|
|
15
|
-
import {I18nManager} from 'react-native';
|
|
16
|
-
import {posLocalization} from './translations/posLocalization';
|
|
17
16
|
|
|
18
17
|
export enum Languages {
|
|
19
18
|
en = 'en',
|
|
@@ -33,7 +32,6 @@ export const localization = {
|
|
|
33
32
|
password: new LocalizedStrings(passwordLocalization),
|
|
34
33
|
navigation: new LocalizedStrings(navigationLocalization),
|
|
35
34
|
mainNavigation: new LocalizedStrings(mainNavigationLocalization),
|
|
36
|
-
pos: new LocalizedStrings(posLocalization),
|
|
37
35
|
};
|
|
38
36
|
|
|
39
37
|
export function getLanguage(): string {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
export const commonLocalization = {
|
|
2
2
|
en: {
|
|
3
3
|
search: 'Search',
|
|
4
|
-
selectPhoto: 'Select
|
|
5
|
-
takePhoto: 'Take
|
|
6
|
-
chooseFromLibrary: 'Choose from
|
|
4
|
+
selectPhoto: 'Select Photo',
|
|
5
|
+
takePhoto: 'Take Photo',
|
|
6
|
+
chooseFromLibrary: 'Choose from Library',
|
|
7
7
|
cancel: 'Cancel',
|
|
8
8
|
reject: 'Reject',
|
|
9
9
|
delete: 'Delete',
|
|
10
10
|
back: 'Back',
|
|
11
11
|
next: 'Next',
|
|
12
12
|
done: 'Done',
|
|
13
|
-
ok: '
|
|
13
|
+
ok: 'OK',
|
|
14
14
|
continue: 'Continue',
|
|
15
15
|
save: 'Save',
|
|
16
|
-
loading: 'Loading',
|
|
16
|
+
loading: 'Loading...',
|
|
17
17
|
photo: 'Photo',
|
|
18
18
|
yes: 'Yes',
|
|
19
19
|
no: 'No',
|
|
@@ -21,50 +21,15 @@ export const commonLocalization = {
|
|
|
21
21
|
warning: 'Warning',
|
|
22
22
|
success: 'Success',
|
|
23
23
|
select: 'Select',
|
|
24
|
-
dataSuccessfullyUpdated: 'Data
|
|
24
|
+
dataSuccessfullyUpdated: 'Data updated successfully',
|
|
25
25
|
settings: 'Settings',
|
|
26
26
|
required: ' (required)',
|
|
27
27
|
optional: ' (optional)',
|
|
28
|
-
currency: 'EGP',
|
|
29
|
-
seeMore: 'See More',
|
|
30
|
-
restartRequired: 'Restart Required',
|
|
31
|
-
restartAppMessage: 'The app needs to restart to apply language changes.',
|
|
32
|
-
restart: 'Restart',
|
|
33
|
-
change: 'Change',
|
|
34
|
-
submit: 'Submit',
|
|
35
|
-
billAmount: 'Bill Amount',
|
|
36
|
-
fullAmount: 'Full Amount',
|
|
37
|
-
partialAmount: 'Other Amount',
|
|
38
|
-
enterAmount: 'Enter Amount',
|
|
39
|
-
paymentDetails: 'Payment Details',
|
|
40
|
-
amount: 'Amount',
|
|
41
|
-
fees: 'Fees',
|
|
42
|
-
total: 'Total',
|
|
43
|
-
favoriteCategories: 'Favorite Categories',
|
|
44
|
-
favoriteProviders: 'Favorite Providers',
|
|
45
|
-
noFavoriteCategories: 'No favorite categories yet',
|
|
46
|
-
noFavoriteProviders: 'No favorite providers yet',
|
|
47
|
-
commission: 'Commission',
|
|
48
|
-
dueDate: 'Due Date',
|
|
49
|
-
issueDate: 'Issue Date',
|
|
50
|
-
print: 'Print',
|
|
51
|
-
allServices: 'All Services',
|
|
52
|
-
totalAfterFees: 'Total after service fees',
|
|
53
|
-
quantity: 'Quantity',
|
|
54
|
-
amountToPay: 'Amount to Pay',
|
|
55
|
-
voucher: 'Voucher',
|
|
56
|
-
invalidAccountNumber: 'Invalid account number',
|
|
57
|
-
otherAmount: 'Other Amount',
|
|
58
|
-
error: 'Error',
|
|
59
|
-
invalid_format: 'Invalid format',
|
|
60
|
-
otherAmountLabel: 'Other Amount',
|
|
61
|
-
backToHome: 'Back to Home',
|
|
62
|
-
confirm: 'Confirm',
|
|
63
28
|
},
|
|
64
29
|
ar: {
|
|
65
30
|
search: 'بحث',
|
|
66
31
|
selectPhoto: 'اختر صورة',
|
|
67
|
-
takePhoto: '
|
|
32
|
+
takePhoto: 'التقاط صورة',
|
|
68
33
|
chooseFromLibrary: 'اختر من المكتبة',
|
|
69
34
|
cancel: 'إلغاء',
|
|
70
35
|
reject: 'رفض',
|
|
@@ -73,54 +38,19 @@ export const commonLocalization = {
|
|
|
73
38
|
next: 'التالي',
|
|
74
39
|
done: 'تم',
|
|
75
40
|
ok: 'موافق',
|
|
76
|
-
continue: '
|
|
41
|
+
continue: 'متابعة',
|
|
77
42
|
save: 'حفظ',
|
|
78
|
-
loading: 'جاري
|
|
43
|
+
loading: 'جاري التحميل...',
|
|
79
44
|
photo: 'صورة',
|
|
80
45
|
yes: 'نعم',
|
|
81
46
|
no: 'لا',
|
|
82
47
|
areYouSure: 'هل أنت متأكد؟',
|
|
83
48
|
warning: 'تحذير',
|
|
84
|
-
success: '
|
|
85
|
-
select: '
|
|
49
|
+
success: 'نجح',
|
|
50
|
+
select: 'اختيار',
|
|
86
51
|
dataSuccessfullyUpdated: 'تم تحديث البيانات بنجاح',
|
|
87
52
|
settings: 'الإعدادات',
|
|
88
53
|
required: ' (مطلوب)',
|
|
89
54
|
optional: ' (اختياري)',
|
|
90
|
-
currency: 'ج.م',
|
|
91
|
-
seeMore: 'عرض المزيد',
|
|
92
|
-
restartRequired: 'إعادة التشغيل مطلوبة',
|
|
93
|
-
restartAppMessage: 'يحتاج التطبيق إلى إعادة التشغيل لتطبيق تغييرات اللغة.',
|
|
94
|
-
restart: 'إعادة تشغيل',
|
|
95
|
-
change: 'تغيير',
|
|
96
|
-
submit: 'إرسال',
|
|
97
|
-
billAmount: 'مبلغ الفاتورة',
|
|
98
|
-
fullAmount: 'المبلغ الكامل',
|
|
99
|
-
partialAmount: 'مبلغ آخر',
|
|
100
|
-
enterAmount: 'أدخل المبلغ',
|
|
101
|
-
paymentDetails: 'تفاصيل الدفع',
|
|
102
|
-
amount: 'المبلغ',
|
|
103
|
-
fees: 'الرسوم',
|
|
104
|
-
total: 'الإجمالي',
|
|
105
|
-
favoriteCategories: 'الفئات المفضلة',
|
|
106
|
-
favoriteProviders: 'مقدمي الخدمات المفضلين',
|
|
107
|
-
noFavoriteCategories: 'لا توجد فئات مفضلة بعد',
|
|
108
|
-
noFavoriteProviders: 'لا يوجد مقدمي خدمات مفضلين بعد',
|
|
109
|
-
commission: 'العمولة',
|
|
110
|
-
dueDate: 'الموعد المستحق',
|
|
111
|
-
issueDate: 'التاريخ الصادر',
|
|
112
|
-
print: 'طباعة',
|
|
113
|
-
allServices: 'جميع الخدمات',
|
|
114
|
-
totalAfterFees: 'بعد رسوم الخدمة',
|
|
115
|
-
quantity: 'الكمية',
|
|
116
|
-
amountToPay: 'قيمة الدفع',
|
|
117
|
-
voucher: 'القسيمة',
|
|
118
|
-
otherAmount: 'مبلغ آخر',
|
|
119
|
-
invalidAccountNumber: 'رقم الحساب غير صالح',
|
|
120
|
-
error: 'خطأ',
|
|
121
|
-
invalid_format: 'صيغة غير صالحة',
|
|
122
|
-
otherAmountLabel: 'مبلغ آخر',
|
|
123
|
-
backToHome: 'العودة للرئيسية',
|
|
124
|
-
confirm: 'تأكيد',
|
|
125
55
|
},
|
|
126
56
|
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export const emptyLocalization = {
|
|
2
2
|
en: {
|
|
3
|
-
noData: 'No data',
|
|
4
|
-
checkThisPageLater: 'Check
|
|
3
|
+
noData: 'No data available',
|
|
4
|
+
checkThisPageLater: 'Check back later',
|
|
5
|
+
},
|
|
6
|
+
ar: {
|
|
7
|
+
noData: 'لا توجد بيانات',
|
|
8
|
+
checkThisPageLater: 'تحقق لاحقاً',
|
|
5
9
|
},
|
|
6
10
|
};
|
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
export const errorsLocalization = {
|
|
2
2
|
en: {
|
|
3
|
-
listErrorTitle: 'Failed to load data
|
|
4
|
-
tryAgain: 'Try again
|
|
5
|
-
thisFieldIsRequired: 'This field is required
|
|
6
|
-
unknownErrorHasOccurred: 'An
|
|
7
|
-
failedToOpenUrl: 'Failed to open URL
|
|
8
|
-
pleaseCheckYourInternetConnection: 'Please check your
|
|
9
|
-
invalidEmail: 'Invalid
|
|
3
|
+
listErrorTitle: 'Failed to load data',
|
|
4
|
+
tryAgain: 'Try again',
|
|
5
|
+
thisFieldIsRequired: 'This field is required',
|
|
6
|
+
unknownErrorHasOccurred: 'An error occurred',
|
|
7
|
+
failedToOpenUrl: 'Failed to open URL',
|
|
8
|
+
pleaseCheckYourInternetConnection: 'Please check your internet connection',
|
|
9
|
+
invalidEmail: 'Invalid email',
|
|
10
10
|
invalidPhoneNumber: 'Invalid phone number',
|
|
11
|
-
invalidFullName: 'Invalid
|
|
11
|
+
invalidFullName: 'Invalid name',
|
|
12
12
|
invalidFromDate: (fromField: string, toField: string) =>
|
|
13
|
-
`${fromField}
|
|
13
|
+
`${fromField} cannot be later than ${toField.toLowerCase()}`,
|
|
14
14
|
invalidToDate: (fromField: string, toField: string) =>
|
|
15
|
-
`${toField}
|
|
15
|
+
`${toField} cannot be earlier than ${fromField.toLowerCase()}`,
|
|
16
16
|
datesCantBeEqual: (fromField: string, toField: string) =>
|
|
17
|
-
`${fromField} and ${toField.toLowerCase()}
|
|
18
|
-
mobileDataIsTurnedOff: 'Mobile
|
|
19
|
-
turnOnMobileData: 'Turn on mobile data or use Wi-Fi
|
|
17
|
+
`${fromField} and ${toField.toLowerCase()} cannot be equal`,
|
|
18
|
+
mobileDataIsTurnedOff: 'Mobile data is turned off',
|
|
19
|
+
turnOnMobileData: 'Turn on mobile data or use Wi-Fi',
|
|
20
20
|
error: 'Error',
|
|
21
21
|
},
|
|
22
|
+
ar: {
|
|
23
|
+
listErrorTitle: 'فشل تحميل البيانات',
|
|
24
|
+
tryAgain: 'حاول مرة أخرى',
|
|
25
|
+
thisFieldIsRequired: 'هذا الحقل مطلوب',
|
|
26
|
+
unknownErrorHasOccurred: 'حدث خطأ',
|
|
27
|
+
failedToOpenUrl: 'فشل فتح الرابط',
|
|
28
|
+
pleaseCheckYourInternetConnection: 'يرجى التحقق من اتصال الإنترنت',
|
|
29
|
+
invalidEmail: 'بريد إلكتروني غير صالح',
|
|
30
|
+
invalidPhoneNumber: 'رقم هاتف غير صالح',
|
|
31
|
+
invalidFullName: 'اسم غير صالح',
|
|
32
|
+
invalidFromDate: (fromField: string, toField: string) =>
|
|
33
|
+
`${fromField} لا يمكن أن يكون بعد ${toField.toLowerCase()}`,
|
|
34
|
+
invalidToDate: (fromField: string, toField: string) =>
|
|
35
|
+
`${toField} لا يمكن أن يكون قبل ${fromField.toLowerCase()}`,
|
|
36
|
+
datesCantBeEqual: (fromField: string, toField: string) =>
|
|
37
|
+
`${fromField} و ${toField.toLowerCase()} لا يمكن أن يكونا متساويين`,
|
|
38
|
+
mobileDataIsTurnedOff: 'بيانات الجوال مغلقة',
|
|
39
|
+
turnOnMobileData: 'قم بتشغيل بيانات الجوال أو استخدم Wi-Fi',
|
|
40
|
+
error: 'خطأ',
|
|
41
|
+
},
|
|
22
42
|
};
|