3 次代碼提交 1798cc8287 ... 71db97e9a0

作者 SHA1 備註 提交日期
  kuns 71db97e9a0 feat: 登陆注册页面国际化配置 1 月之前
  kuns 2c683ef51d perf: 登陆页国际化配置 1 月之前
  kuns ab5b038eea perf: 修复样式乱的问题以及用户协议多语言配置 1 月之前

+ 31 - 20
component/accountPages/userTermsPageComponent.tsx

@@ -4,6 +4,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
 import { router } from 'expo-router';
 import { CrossLogoSvg, RightArrowIconSvg } from '../global/SVG';
 import NormalButton from '../global/normal_button';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 type TermsSectionProps = {
   title: string| undefined;
@@ -23,6 +24,8 @@ const TermsSection: React.FC<TermsSectionProps> = ({ title, clauses }) => (
   </View>
 );
 const UserTermsPageComponent: React.FC = () => {
+  const { getCurrentLanguageConfig } = useTranslation()
+  const curren = getCurrentLanguageConfig()
   const sectionsZh = [
     {
       clauses: [
@@ -193,26 +196,34 @@ const UserTermsPageComponent: React.FC = () => {
     <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
     <View style={styles.container}>
       <ScrollView contentContainerStyle={styles.scrollContainer}>
-        <Text style={styles.header}>Crazy Charge 用戶條款及細則</Text>
-        <View style={styles.section}>
-          {sectionsZh.map((section, index) => (
-            <TermsSection 
-              key={index}
-              title={section.title}
-              clauses={section.clauses}
-            />
-          ))}
-        </View>
-        <Text style={styles.header}>Crazy Charge Users’ Terms and Conditions</Text>
-        <View style={styles.section}>
-          {sectionsEn.map((section, index) => (
-            <TermsSection 
-              key={index}
-              title={section.title}
-              clauses={section.clauses}
-            />
-          ))}
-        </View>
+        {curren?.value?
+        <View>
+          <Text style={styles.header}>Crazy Charge 用戶條款及細則</Text>
+            <View style={styles.section}>
+              {sectionsZh.map((section, index) => (
+                <TermsSection 
+                  key={index}
+                  title={section.title}
+                  clauses={section.clauses}
+                />
+              ))}
+            </View>
+          </View>
+          :
+          <View>
+            <Text style={styles.header}>Crazy Charge Users’ Terms and Conditions</Text>
+            <View style={styles.section}>
+              {sectionsEn.map((section, index) => (
+                <TermsSection 
+                  key={index}
+                  title={section.title}
+                  clauses={section.clauses}
+                />
+              ))}
+            </View>
+          </View>
+        }
+
       </ScrollView>
       <NormalButton
         extendedStyle={styles.agreeButton}

+ 9 - 6
component/bindingMultiStepForm/formComponent/form.tsx

@@ -6,13 +6,15 @@ import { router } from 'expo-router';
 import BindingPhoneNumberPage from './formPages/bindingPhoneNumberPage';
 import BindingPhoneNumberPageStepTwo from './formPages/bindingPhoneNumberPageStepTwo';
 import BindingFinishPage from './formPages/bindingFinishPage';
+import { useTranslation } from '../../../util/hooks/useTranslation';
 
 const BindingPhoneNumberForm = ({ bindingFormData, setBindingFormData }: any) => {
+    const { t } = useTranslation(); // 使用翻译钩子
     const [screen, setScreen] = useState<number>(0);
-    const FormTitle = ['舊用戶手機號碼綁定 (1/2)', '舊用戶手機號碼綁定 (2/2)'];
-    // const goToPreviousPage = () => {
-    //         router.back();
-    // };
+    const FormTitle = [
+        t('binding.old_user_phone_binding_step1'), 
+        t('binding.old_user_phone_binding_step2')
+    ];
 
     const goToPreviousPage = () => {
         if (screen == 1) {
@@ -46,6 +48,7 @@ const BindingPhoneNumberForm = ({ bindingFormData, setBindingFormData }: any) =>
                 return <></>;
         }
     };
+    
     return (
         <>
             <KeyboardAwareScrollView
@@ -67,7 +70,7 @@ const BindingPhoneNumberForm = ({ bindingFormData, setBindingFormData }: any) =>
                                         fontSize: 18,
                                         paddingLeft: 25
                                     }}
-                                >{`<  上一步`}</Text>
+                                >{t('common.previous')}</Text>
                             </Pressable>
                             <PaginationIndicator totalPages={2} currentPage={0} />
                             <View className="flex-1" />
@@ -106,4 +109,4 @@ const styles = StyleSheet.create({
     text: { fontSize: 24, fontWeight: '300' }
 });
 
-export default BindingPhoneNumberForm;
+export default BindingPhoneNumberForm;

+ 11 - 94
component/bindingMultiStepForm/formComponent/formPages/bindingPhoneNumberPage.tsx

@@ -1,99 +1,17 @@
 import { View, Text, StyleSheet, Pressable, Alert } from 'react-native';
 import { useState } from 'react';
 import { Ionicons } from '@expo/vector-icons';
-import NumberInput from '../../../global/number_input';
 import NormalButton from '../../../global/normal_button';
 import NormalInput from '../../../global/normal_input';
 import { authenticationService } from '../../../../service/authService';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 const BindingPhoneNumberPage = ({ bindingFormData, setBindingFormData, setScreen }: any) => {
-    const [authError, setAuthError] = useState('');
+    const { t } = useTranslation(); // 使用翻译钩子
     const [error, setError] = useState('');
-    const [canSendOtp, setCanSendOtp] = useState(true);
-    const [lockEmailInput, setLockEmailInput] = useState(false);
-    const [data, setData] = useState('');
     const [isLoading, setIsLoading] = useState(false);
-    const [isLoading2, setIsLoading2] = useState(false);
     const [showPassword, setShowPassword] = useState(false);
-    // const handleVerification = async () => {
-    //     setIsLoading(true);
-    //     if (!forgetPasswordFormData.otp && !forgetPasswordFormData.email) {
-    //         setAuthError('請確保所有資料都已填寫');
-    //     } else if (!forgetPasswordFormData.otp) {
-    //         setAuthError('請輸入OTP驗證碼');
-    //     } else {
-    //         setAuthError('');
-    //         try {
-    //             const result = await authenticationService.verifyingOtpForgetPassword(
-    //                 forgetPasswordFormData.email.toLowerCase(),
-    //                 forgetPasswordFormData.otp,
-    //                 setForgetPasswordFormData,
-    //                 setData
-    //             );
-    //             if (result === false) {
-    //                 setAuthError('驗證OTP時發生錯誤,請稍後再試');
-    //             }
-    //         } catch (error) {
-    //             console.error('Error verifying OTP:', error);
-    //             setAuthError('驗證OTP時發生錯誤,請稍後再試');
-    //         }
-    //     }
-    //     setIsLoading(false);
-    // };
-
-    // const handleFormDataChange: HandleForgetPasswordFormDataChange = (field, value) => {
-    //     setForgetPasswordFormData((prevFormData) => ({
-    //         ...prevFormData,
-    //         [field]: value
-    //     }));
-    // };
-
-    // const handleSubmitOtp = () => {
-    //     if (forgetPasswordFormData.email) {
-    //         if (canSendOtp) {
-    //             const lowerCaseEmail = forgetPasswordFormData.email.toLowerCase();
-    //             setCanSendOtp(false);
-    //             setLockEmailInput(true);
-    //             authenticationService.sendForgetPasswordOtp(lowerCaseEmail);
-    //             //can only request otp every 60 seconds
-    //             setTimeout(() => {
-    //                 setCanSendOtp(true);
-    //                 setLockEmailInput(false);
-    //             }, 60000);
-    //             setAuthError('');
-    //         } else {
-    //             setAuthError('請等待一分鐘後再重新發送。');
-    //         }
-    //     } else {
-    //         setAuthError('請確保所有資料都已填寫。');
-    //     }
-    // };
-
-    // const handleFinishResetPassword = async () => {
-    //     if (forgetPasswordFormData.newPassword !== forgetPasswordFormData.confirmedNewPassword) {
-    //         setError('請確保新密碼和確認密碼相同');
-    //     } else {
-    //         setError('');
-    //         setIsLoading2(true);
-    //         try {
-    //             const success = await authenticationService.changePassword(
-    //                 forgetPasswordFormData.confirmedNewPassword,
-    //                 data
-    //             );
-    //             if (success) {
-    //                 setScreen(1);
-    //             } else {
-    //                 setError('密碼重置失敗,請稍後再試');
-    //             }
-    //         } catch (error) {
-    //             console.error('Error changing password:', error);
-    //             setError('發生錯誤,請稍後再試');
-    //         } finally {
-    //             setIsLoading2(false);
-    //         }
-    //     }
-    // };
-
+    
     const handleVerification = async () => {
         setIsLoading(true);
         try {
@@ -107,21 +25,23 @@ const BindingPhoneNumberPage = ({ bindingFormData, setBindingFormData, setScreen
             if (response == true) {
                 setScreen(1);
             } else {
-                Alert.alert('登入失敗,請檢查您輸入的帳號密碼並再試一次');
+                Alert.alert(t('binding.one.login_failed'));
             }
         } catch (error) {
+            console.error('Login error:', error);
         } finally {
             setIsLoading(false);
         }
     };
+    
     return (
         <>
             <View style={styles.container}>
                 <View style={styles.bottomContainer}>
-                    <Text style={styles.text}>請輸入現有電子郵件</Text>
+                    <Text style={styles.text}>{t('binding.one.enter_existing_email')}</Text>
                     <View className="pb-2">
                         <NormalInput
-                            placeholder="請填寫您的電子郵件"
+                            placeholder={t('binding.one.enter_your_email')}
                             onChangeText={(email) =>
                                 setBindingFormData({
                                     ...bindingFormData,
@@ -136,7 +56,7 @@ const BindingPhoneNumberPage = ({ bindingFormData, setBindingFormData, setScreen
                     </View>
                     <View className="pb-2">
                         <NormalInput
-                            placeholder="請填寫您的密碼"
+                            placeholder={t('binding.one.enter_your_password')}
                             onChangeText={(password) =>
                                 setBindingFormData({
                                     ...bindingFormData,
@@ -160,11 +80,8 @@ const BindingPhoneNumberPage = ({ bindingFormData, setBindingFormData, setScreen
                         </Pressable>
                     </View>
                     <NormalButton
-                        title={<Text style={{ color: '#fff' }}>{isLoading ? '處理中...' : '下一步'}</Text>}
+                        title={<Text style={{ color: '#fff' }}>{isLoading ? t('binding.one.processing') : t('common.next')}</Text>}
                         onPress={handleVerification}
-                        // extendedStyle={
-                        //     forgetPasswordFormData.otpAuthCompleted == true ? { backgroundColor: '#70787C' } : {}
-                        // }
                     />
 
                     {error && <Text style={styles.errorMessage}>{error}</Text>}
@@ -218,4 +135,4 @@ const styles = StyleSheet.create({
     footer: { color: '#02677D', fontSize: 16, paddingVertical: 10 }
 });
 
-export default BindingPhoneNumberPage;
+export default BindingPhoneNumberPage;

+ 18 - 183
component/bindingMultiStepForm/formComponent/formPages/bindingPhoneNumberPageStepTwo.tsx

@@ -8,17 +8,16 @@ import { authenticationService } from '../../../../service/authService';
 import PhoneInput from '../../../global/phone_input';
 import * as SecureStore from 'expo-secure-store';
 import { usePushNotifications } from '../../../../app/hooks/usePushNotifications';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, setScreen }: any) => {
-    const [authError, setAuthError] = useState('');
+    const { t } = useTranslation(); // 使用翻译钩子
     const [error, setError] = useState('');
-    const [canSendOtp, setCanSendOtp] = useState(true);
     const [lockEmailInput, setLockEmailInput] = useState(false);
-    const [data, setData] = useState('');
-    const [isLoading, setIsLoading] = useState(false);
     const [isLoading2, setIsLoading2] = useState(false);
     const [countdown, setCountdown] = useState(0);
     const { expoPushToken } = usePushNotifications();
+    
     useEffect(() => {
         let timer: NodeJS.Timeout;
         if (countdown > 0) {
@@ -32,93 +31,7 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
             if (timer) clearInterval(timer);
         };
     }, [countdown]);
-    // const handleVerification = async () => {
-    //     setIsLoading(true);
-    //     if (!forgetPasswordFormData.otp && !forgetPasswordFormData.email) {
-    //         setAuthError('請確保所有資料都已填寫');
-    //     } else if (!forgetPasswordFormData.otp) {
-    //         setAuthError('請輸入OTP驗證碼');
-    //     } else {
-    //         setAuthError('');
-    //         try {
-    //             const result =
-    //                 await authenticationService.verifyingOtpForgetPassword(
-    //                     forgetPasswordFormData.email.toLowerCase(),
-    //                     forgetPasswordFormData.otp,
-    //                     setForgetPasswordFormData,
-    //                     setData
-    //                 );
-    //             if (result === false) {
-    //                 setAuthError('驗證OTP時發生錯誤,請稍後再試');
-    //             }
-    //         } catch (error) {
-    //             console.error('Error verifying OTP:', error);
-    //             setAuthError('驗證OTP時發生錯誤,請稍後再試');
-    //         }
-    //     }
-    //     setIsLoading(false);
-    // };
-
-    // const handleFormDataChange: HandleForgetPasswordFormDataChange = (
-    //     field,
-    //     value
-    // ) => {
-    //     setForgetPasswordFormData((prevFormData) => ({
-    //         ...prevFormData,
-    //         [field]: value
-    //     }));
-    // };
-
-    // const handleSubmitOtp = () => {
-    //     if (forgetPasswordFormData.email) {
-    //         if (canSendOtp) {
-    //             const lowerCaseEmail =
-    //                 forgetPasswordFormData.email.toLowerCase();
-    //             setCanSendOtp(false);
-    //             setLockEmailInput(true);
-    //             authenticationService.sendForgetPasswordOtp(lowerCaseEmail);
-    //             //can only request otp every 60 seconds
-    //             setTimeout(() => {
-    //                 setCanSendOtp(true);
-    //                 setLockEmailInput(false);
-    //             }, 60000);
-    //             setAuthError('');
-    //         } else {
-    //             setAuthError('請等待一分鐘後再重新發送。');
-    //         }
-    //     } else {
-    //         setAuthError('請確保所有資料都已填寫。');
-    //     }
-    // };
-
-    // const handleFinishResetPassword = async () => {
-    //     if (
-    //         forgetPasswordFormData.newPassword !==
-    //         forgetPasswordFormData.confirmedNewPassword
-    //     ) {
-    //         setError('請確保新密碼和確認密碼相同');
-    //     } else {
-    //         setError('');
-    //         setIsLoading2(true);
-    //         try {
-    //             const success = await authenticationService.changePassword(
-    //                 forgetPasswordFormData.confirmedNewPassword,
-    //                 data
-    //             );
-    //             if (success) {
-    //                 setScreen(1);
-    //             } else {
-    //                 setError('密碼重置失敗,請稍後再試');
-    //             }
-    //         } catch (error) {
-    //             console.error('Error changing password:', error);
-    //             setError('發生錯誤,請稍後再試');
-    //         } finally {
-    //             setIsLoading2(false);
-    //         }
-    //     }
-    // };
-
+    
     const handleConfirmBindingPhone = async () => {
         setIsLoading2(true);
         try {
@@ -132,23 +45,24 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
             if (result.status == 200) {
                 setScreen(2);
             } else {
-                setError('綁定手機號碼失敗,請檢查您輸入的OTP並再試一次');
+                setError(t('binding.two.phone_binding_failed'));
             }
         } catch (error) {
-            Alert.alert('綁定手機號碼失敗,請檢查您輸入的OTP並再試一次');
+            Alert.alert(t('binding.two.phone_binding_failed'));
         } finally {
             setIsLoading2(false);
         }
     };
+    
     const handleRequestOtp = async () => {
         try {
             //this check if phone same,
             const checkPhoneSame = await authenticationService.checkPhoneSame(bindingFormData.phoneNumber);
             if (checkPhoneSame?.status == 422) {
                 //this means phone not same
-                Alert.alert('確認您的手機號碼', '您以後將使用現在輸入的號碼進行登入。請按下確認表示您已知悉。', [
+                Alert.alert(t('binding.two.confirm_phone_number'), t('binding.two.phone_usage_notice'), [
                     {
-                        text: '確認並發出驗證碼',
+                        text: t('binding.two.confirm_and_send_otp'),
                         onPress: async () => {
                             try {
                                 const token = await SecureStore.getItemAsync('accessToken');
@@ -169,12 +83,12 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
                                             setLockEmailInput(true);
                                             setCountdown(60);
                                         } else {
-                                            setError('發送OTP失敗,請聯絡工作人員');
+                                            setError(t('binding.two.send_otp_failed'));
                                         }
                                     } catch (error) {}
                                 } else {
                                     //this means change phone failed
-                                    Alert.alert('修改手機號碼失敗,請稍後再試');
+                                    Alert.alert(t('binding.two.change_phone_failed'));
                                 }
                             } catch (error) {}
                         }
@@ -187,7 +101,7 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
                     setLockEmailInput(true);
                     setCountdown(60); // Start 60 second countdown
                 } else {
-                    setError('發送OTP失敗,請稍後再試');
+                    setError(t('binding.two.send_otp_failed'));
                 }
             }
         } catch (error) {}
@@ -197,7 +111,7 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
         <>
             <View style={styles.container}>
                 <View style={styles.bottomContainer}>
-                    <Text style={styles.text}>請輸入手機號碼,此手機號碼將用作登入用途</Text>
+                    <Text style={styles.text}>{t('binding.two.enter_phone_for_login')}</Text>
                     <PhoneInput
                         value={bindingFormData?.phoneNumber || ''}
                         onChangeText={(phoneNumber) => {
@@ -206,21 +120,10 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
                                 phoneNumber: phoneNumber
                             });
                         }}
-                        placeholder="請輸入手機號碼"
+                        placeholder={t('binding.two.enter_phone_number')}
                         editable={!lockEmailInput}
                         extendedStyle={{ opacity: !lockEmailInput ? 1 : 0.5 }}
                     />
-                    {/* <NormalInput
-                        placeholder="請輸入手機號碼"
-                        onChangeText={(phoneNumber) =>
-                            setBindingFormData({
-                                ...bindingFormData,
-                                phoneNumber: phoneNumber
-                            })
-                        }
-                        // editable={!lockEmailInput}
-                        // extendedStyle={{ opacity: !lockEmailInput ? 1 : 0.5 }}
-                    /> */}
                     <View
                         style={{
                             display: 'flex',
@@ -230,18 +133,16 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
                         }}
                     >
                         <NumberInput
-                            placeholder="OTP驗證碼"
+                            placeholder={t('binding.two.otp_verification_code')}
                             onChangeText={(t) => setBindingFormData({ ...bindingFormData, otp: t })}
-                            // editable={!forgetPasswordFormData.otpAuthCompleted}
                             extendedStyle={{
                                 flex: 1
-                                // opacity: !forgetPasswordFormData.otpAuthCompleted ? 1 : 0.5
                             }}
                         />
                         <NormalButton
                             title={
                                 <Text style={{ color: '#fff' }}>
-                                    {lockEmailInput ? `已發送 (${countdown}s)` : '發送'}
+                                    {lockEmailInput ? `${t('binding.two.sent')} (${countdown}s)` : t('binding.two.send')}
                                 </Text>
                             }
                             onPress={handleRequestOtp}
@@ -250,75 +151,9 @@ const BindingPhoneNumberPageStepTwo = ({ bindingFormData, setBindingFormData, se
                         />
                     </View>
                     <NormalButton
-                        title={<Text style={{ color: '#fff' }}>{isLoading2 ? '處理中...' : '確認'}</Text>}
+                        title={<Text style={{ color: '#fff' }}>{isLoading2 ? t('binding.two.processing') : t('binding.two.confirm')}</Text>}
                         onPress={handleConfirmBindingPhone}
-                        // extendedStyle={
-                        //     forgetPasswordFormData.otpAuthCompleted == true ? { backgroundColor: '#70787C' } : {}
-                        // }
                     />
-                    {/* {lockEmailInput && (
-                        <Pressable
-                            // disabled={forgetPasswordFormData.otpAuthCompleted}
-                            onPress={() => setLockEmailInput(false)}
-                        >
-                            <Text
-                                style={[
-                                    styles.footer
-                                    // forgetPasswordFormData.otpAuthCompleted && {
-                                    //     opacity: 0.5
-                                    // }
-                                ]}
-                            >
-                                重新整理
-                            </Text>
-                        </Pressable>
-                    )} */}
-
-                    {/* {authError && <Text style={styles.errorMessage}>{authError}</Text>}
-                    {lockEmailInput && (
-                        <Pressable
-                            disabled={forgetPasswordFormData.otpAuthCompleted}
-                            onPress={() => setLockEmailInput(false)}
-                        >
-                            <Text
-                                style={[
-                                    styles.footer,
-                                    forgetPasswordFormData.otpAuthCompleted && {
-                                        opacity: 0.5
-                                    }
-                                ]}
-                            >
-                                修改電子郵件
-                            </Text>
-                        </Pressable>
-                    )}
-
-                    {forgetPasswordFormData.otpAuthCompleted && (
-                        <View
-                            style={[
-                                styles.hiddenPasswordFields,
-                                forgetPasswordFormData.otpAuthCompleted ? styles.opacityFull : styles.opacityZero
-                            ]}
-                        >
-                            <NormalInput
-                                placeholder="新密碼"
-                                onChangeText={(t) => handleFormDataChange('newPassword', t)}
-                                secureTextEntry={true}
-                                textContentType={'oneTimeCode'}
-                            />
-                            <NormalInput
-                                placeholder="確認密碼"
-                                onChangeText={(t) => handleFormDataChange('confirmedNewPassword', t)}
-                                secureTextEntry={true}
-                                textContentType={'oneTimeCode'}
-                            />
-                            <NormalButton
-                                title={<Text style={{ color: '#fff' }}>{isLoading ? '重置中...' : '重置'}</Text>}
-                                onPress={handleFinishResetPassword}
-                                extendedStyle={{}}
-                            />
-                        </View>
-                    )} */}
 
                     {error && <Text style={styles.errorMessage}>{error}</Text>}
                 </View>
@@ -371,4 +206,4 @@ const styles = StyleSheet.create({
     footer: { color: '#02677D', fontSize: 16, paddingVertical: 10 }
 });
 
-export default BindingPhoneNumberPageStepTwo;
+export default BindingPhoneNumberPageStepTwo;

+ 8 - 8
component/forgetPasswordMultiStepForm/formComponent/form.tsx

@@ -1,28 +1,26 @@
 import { useState } from 'react';
 import { View, Text, StyleSheet, TouchableWithoutFeedback, Keyboard, Pressable } from 'react-native';
-
 import ResetSuccessful from './formPages/resetSuccessful';
 import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
 import ForgetPasswordPage from './formPages/forgetPasswordPage';
 import { forgetPasswordFormData } from '../../../types/signup';
 import PaginationIndicator from '../../global/PaginationIndicator';
 import { router } from 'expo-router';
+import { useTranslation } from '../../../util/hooks/useTranslation';
 
 type ForgetPasswordFormProps = {
     forgetPasswordFormData: forgetPasswordFormData;
     setForgetPasswordFormData: React.Dispatch<React.SetStateAction<forgetPasswordFormData>>;
 };
+
 const ForgetPasswordForm: React.FC<ForgetPasswordFormProps> = ({
     forgetPasswordFormData,
     setForgetPasswordFormData
 }) => {
+    const { t } = useTranslation(); // 使用翻译钩子
     const [screen, setScreen] = useState<number>(0);
-    const FormTitle = ['忘記密碼 - 電話驗證'];
-    // const goToPreviousPage = () => {
-
-    //         router.back();
+    const FormTitle = [t('forgotPassword.phone_verification')];
 
-    // };
     const goToPreviousPage = () => {
         if (router.canGoBack()) {
             router.back();
@@ -30,6 +28,7 @@ const ForgetPasswordForm: React.FC<ForgetPasswordFormProps> = ({
             router.replace('/(public)/login');
         }
     };
+
     const ScreenDisplay = () => {
         switch (screen) {
             case 0:
@@ -47,6 +46,7 @@ const ForgetPasswordForm: React.FC<ForgetPasswordFormProps> = ({
                 return <></>;
         }
     };
+
     return (
         <>
             <KeyboardAwareScrollView
@@ -68,7 +68,7 @@ const ForgetPasswordForm: React.FC<ForgetPasswordFormProps> = ({
                                         fontSize: 18,
                                         paddingLeft: 25
                                     }}
-                                >{`<  上一步`}</Text>
+                                >{t('common.previous')}</Text>
                             </Pressable>
                             <PaginationIndicator totalPages={2} currentPage={0} />
                             <View className="flex-1" />
@@ -107,4 +107,4 @@ const styles = StyleSheet.create({
     text: { fontSize: 24, fontWeight: '300' }
 });
 
-export default ForgetPasswordForm;
+export default ForgetPasswordForm;

+ 23 - 21
component/forgetPasswordMultiStepForm/formComponent/formPages/forgetPasswordPage.tsx

@@ -5,6 +5,7 @@ import NumberInput from '../../../global/number_input';
 import NormalButton from '../../../global/normal_button';
 import NormalInput from '../../../global/normal_input';
 import { authenticationService } from '../../../../service/authService';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 type ForgetPasswordPageProps = {
     forgetPasswordFormData: forgetPasswordFormData;
@@ -17,6 +18,7 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
     setForgetPasswordFormData,
     setScreen
 }) => {
+    const { t } = useTranslation(); // 使用翻译钩子
     const [authError, setAuthError] = useState('');
     const [error, setError] = useState('');
     const [canSendOtp, setCanSendOtp] = useState(true);
@@ -28,9 +30,9 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
     const handleVerification = async () => {
         setIsLoading(true);
         if (!forgetPasswordFormData.otp && !forgetPasswordFormData.email) {
-            setAuthError('請確保所有資料都已填寫');
+            setAuthError(t('forgotPassword.one.ensure_all_fields_filled'));
         } else if (!forgetPasswordFormData.otp) {
-            setAuthError('請輸入OTP驗證碼');
+            setAuthError(t('forgotPassword.one.enter_otp_code'));
         } else {
             setAuthError('');
             try {
@@ -41,11 +43,11 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                     setData
                 );
                 if (result === false) {
-                    setAuthError('驗證OTP時發生錯誤,請稍後再試');
+                    setAuthError(t('forgotPassword.one.error_verifying_otp'));
                 }
             } catch (error) {
                 console.error('Error verifying OTP:', error);
-                setAuthError('驗證OTP時發生錯誤,請稍後再試');
+                setAuthError(t('forgotPassword.one.error_verifying_otp'));
             }
         }
         setIsLoading(false);
@@ -72,16 +74,16 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                 }, 60000);
                 setAuthError('');
             } else {
-                setAuthError('請等待一分鐘後再重新發送。');
+                setAuthError(t('forgotPassword.one.wait_one_minute'));
             }
         } else {
-            setAuthError('請確保所有資料都已填寫。');
+            setAuthError(t('forgotPassword.one.ensure_all_fields_filled'));
         }
     };
 
     const handleFinishResetPassword = async () => {
         if (forgetPasswordFormData.newPassword !== forgetPasswordFormData.confirmedNewPassword) {
-            setError('請確保新密碼和確認密碼相同');
+            setError(t('forgotPassword.one.passwords_do_not_match'));
         } else {
             setError('');
             setIsLoading2(true);
@@ -93,11 +95,11 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                 if (success) {
                     setScreen(1);
                 } else {
-                    setError('密碼重置失敗,請稍後再試');
+                    setError(t('forgotPassword.one.password_reset_failed'));
                 }
             } catch (error) {
                 console.error('Error changing password:', error);
-                setError('發生錯誤,請稍後再試');
+                setError(t('forgotPassword.one.error_occurred'));
             } finally {
                 setIsLoading2(false);
             }
@@ -108,10 +110,10 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
         <>
             <View style={styles.container}>
                 <View style={styles.bottomContainer}>
-                    <Text style={styles.text}>驗證電子郵件後即可重置密碼</Text>
+                    <Text style={styles.text}>{t('forgotPassword.one.verify_email_to_reset')}</Text>
 
                     <NormalInput
-                        placeholder="請填寫您的電子郵件"
+                        placeholder={t('forgotPassword.one.enter_your_email')}
                         onChangeText={(email) =>
                             setForgetPasswordFormData({
                                 ...forgetPasswordFormData,
@@ -131,7 +133,7 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                         }}
                     >
                         <NumberInput
-                            placeholder="OTP驗證碼"
+                            placeholder={t('forgotPassword.one.otp_verification_code')}
                             onChangeText={(t) => handleFormDataChange('otp', t)}
                             editable={!forgetPasswordFormData.otpAuthCompleted}
                             extendedStyle={{
@@ -140,7 +142,7 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                             }}
                         />
                         <NormalButton
-                            title={<Text style={{ color: '#fff' }}>{lockEmailInput ? '已發送' : '發送'}</Text>}
+                            title={<Text style={{ color: '#fff' }}>{lockEmailInput ? t('forgotPassword.one.sent') : t('forgotPassword.one.send')}</Text>}
                             onPress={handleSubmitOtp}
                             extendedStyle={{ flex: 1 / 2 }}
                         />
@@ -149,10 +151,10 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                         title={
                             <Text style={{ color: '#fff' }}>
                                 {isLoading
-                                    ? '驗證中...'
+                                    ? t('forgotPassword.one.verifying')
                                     : forgetPasswordFormData.otpAuthCompleted == true
-                                    ? '已驗證'
-                                    : '驗證'}
+                                    ? t('forgotPassword.one.verified')
+                                    : t('forgotPassword.one.verify')}
                             </Text>
                         }
                         onPress={handleVerification}
@@ -175,7 +177,7 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                                     }
                                 ]}
                             >
-                                修改電子郵件
+                                {t('forgotPassword.one.modify_email')}
                             </Text>
                         </Pressable>
                     )}
@@ -188,21 +190,21 @@ const ForgetPasswordPage: React.FC<ForgetPasswordPageProps> = ({
                             ]}
                         >
                             <NormalInput
-                                placeholder="新密碼"
+                                placeholder={t('forgotPassword.one.new_password')}
                                 onChangeText={(t) => handleFormDataChange('newPassword', t)}
                                 secureTextEntry={true}
                                 textContentType={'oneTimeCode'}
                                 autoCapitalize="none"
                             />
                             <NormalInput
-                                placeholder="確認密碼"
+                                placeholder={t('forgotPassword.one.confirm_password')}
                                 onChangeText={(t) => handleFormDataChange('confirmedNewPassword', t)}
                                 secureTextEntry={true}
                                 textContentType={'oneTimeCode'}
                                 autoCapitalize="none"
                             />
                             <NormalButton
-                                title={<Text style={{ color: '#fff' }}>{isLoading ? '重置中...' : '重置'}</Text>}
+                                title={<Text style={{ color: '#fff' }}>{isLoading ? t('forgotPassword.one.resetting') : t('forgotPassword.one.reset')}</Text>}
                                 onPress={handleFinishResetPassword}
                                 extendedStyle={{}}
                             />
@@ -260,4 +262,4 @@ const styles = StyleSheet.create({
     footer: { color: '#02677D', fontSize: 16, paddingVertical: 10 }
 });
 
-export default ForgetPasswordPage;
+export default ForgetPasswordPage;

+ 10 - 5
component/forgetPasswordMultiStepForm/formComponent/formPages/resetSuccessful.tsx

@@ -2,15 +2,18 @@ import { View, Text, StyleSheet, Image } from 'react-native';
 import { router } from 'expo-router';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import NormalButton from '../../../global/normal_button';
+import { useTranslation } from 'react-i18next'; // 添加国际化支持
 
 const ResetSuccessful = ({}) => {
+    const { t } = useTranslation(); // 使用翻译钩子
+    
     return (
         <SafeAreaView className="flex-1">
             <View className="flex-1 justify-center">
                 <View className="items-center space-y-6">
-                    <Text style={styles.titleText}>重置密碼成功</Text>
-                    <Text style={styles.text}>歡迎使用 Crazy Charge</Text>
-                    <Text style={styles.text}>祝你一路順“瘋“</Text>
+                    <Text style={styles.titleText}>{t('forgotPassword.two.success_title')}</Text>
+                    <Text style={styles.text}>{t('forgotPassword.two.welcome_message')}</Text>
+                    <Text style={styles.text}>{t('forgotPassword.two.good_luck')}</Text>
                 </View>
                 <Image
                     style={{
@@ -21,17 +24,19 @@ const ResetSuccessful = ({}) => {
                 <View className="mx-[5%]">
                     <NormalButton
                         onPress={() => router.replace('login')}
-                        title={<Text className="text-white">完成</Text>}
+                        title={<Text className="text-white">{t('forgotPassword.two.finish')}</Text>}
                     />
                 </View>
             </View>
         </SafeAreaView>
     );
 };
+
 const styles = StyleSheet.create({
     titleText: { fontSize: 32, fontWeight: '400' },
     text: {
         fontSize: 18
     }
 });
-export default ResetSuccessful;
+
+export default ResetSuccessful;

+ 43 - 40
component/registrationMultiStepForm/formComponent/form.tsx

@@ -12,15 +12,21 @@ import ChooseCarBrand from './formPages/chooseCarPage/carBrand';
 import ChooseCarSeries from './formPages/chooseCarPage/carSeries';
 import ChooseCarModel from './formPages/chooseCarPage/carModel';
 import ForgetPasswordForm from '../../forgetPasswordMultiStepForm/forgetPasswordForm';
-import SetVehiclesOne from '../../../app/(auth)/(tabs)/(home)/(vehicle)/setVehiclesOne';
-import SetVehiclesTwo from '../../../app/(auth)/(tabs)/(home)/(vehicle)/setVehiclesTwo';
 
 import BindingMultiStepForm from '../../bindingMultiStepForm/bindingMultiStepForm';
+import { useTranslation } from '../../../util/hooks/useTranslation';
 
 type FormProps = {};
 const Form: React.FC<FormProps> = ({}) => {
+    const { t } = useTranslation(); // 使用翻译钩子
     const [screen, setScreen] = useState<number>(0);
-    const FormTitle = ['', '註冊 - 電話驗證', '註冊 - 基本資料', '註冊 - 基本資料', '註冊 - 設立銀包'];
+    const FormTitle = [
+        '', 
+        t('register.phone_verification'), 
+        t('register.basic_info'), 
+        t('register.basic_info'), 
+        t('register.create_wallet')
+    ];
 
     const ScreenDisplay = () => {
         switch (screen) {
@@ -36,10 +42,6 @@ const Form: React.FC<FormProps> = ({}) => {
                 return <Verification setScreen={setScreen} />;
             case 2:
                 return <BasicInformation goToNextPage={goToNextPage} />;
-            // case 3:
-            //     return <UberDriver goToNextPage={goToNextPage} />;
-            // case 3:
-            //     return <CarInformation goToNextPage={goToNextPage} goToChooseCarPage={goToChooseCarBrandPage} />;
             case 3:
                 return <CreateWallet goToNextPage={goToNextPage} />;
             case 4:
@@ -95,6 +97,7 @@ const Form: React.FC<FormProps> = ({}) => {
             }
         });
     };
+    
     const goToChooseCarBrandPage = () => {
         setScreen((prevState) => {
             return 6;
@@ -106,6 +109,7 @@ const Form: React.FC<FormProps> = ({}) => {
             return 7;
         });
     };
+    
     const goToChooseCarModelPage = () => {
         setScreen((prevState) => {
             return 8;
@@ -129,41 +133,40 @@ const Form: React.FC<FormProps> = ({}) => {
             return 11;
         });
     };
+    
     return (
-        <>
-            <KeyboardAwareScrollView
-                enableOnAndroid={true}
-                // resetScrollToCoords={{ x: 0, y: 0 }}
-            >
-                {/* not showing title and pagination on the first and last page */}
-                {screen == 0 ||
-                    (screen < 4 && (
-                        //dismiss keyboard when user click outside of the input field to improve user experience
-                        <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
-                            <View style={styles.topContainer}>
-                                <Text style={styles.text}>{FormTitle[screen]}</Text>
-                                <View style={styles.breakline} />
-                                <View style={styles.previouspageAndPaginationWrapper}>
-                                    <Pressable onPress={goToPreviousPage}>
-                                        <Text style={{ color: '#888888' }}>{`<  上一步`}</Text>
-                                    </Pressable>
-                                    <PaginationIndicator totalPages={FormTitle.length} currentPage={screen} />
-                                    <Pressable disabled={true} onPress={goToNextPage}>
-                                        <Text
-                                            style={{
-                                                color: '#888888',
-                                                opacity: 0
-                                            }}
-                                        >{`下一步  >`}</Text>
-                                    </Pressable>
-                                </View>
+        <KeyboardAwareScrollView
+            enableOnAndroid={true}
+            // resetScrollToCoords={{ x: 0, y: 0 }}
+        >
+            {/* not showing title and pagination on the first and last page */}
+            {screen == 0 ||
+                (screen < 4 && (
+                    //dismiss keyboard when user click outside of the input field to improve user experience
+                    <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
+                        <View style={styles.topContainer}>
+                            <Text style={styles.text}>{FormTitle[screen]}</Text>
+                            <View style={styles.breakline} />
+                            <View style={styles.previouspageAndPaginationWrapper}>
+                                <Pressable onPress={goToPreviousPage}>
+                                    <Text style={{ color: '#888888' }}>{t('common.previous')}</Text>
+                                </Pressable>
+                                <PaginationIndicator totalPages={FormTitle.length} currentPage={screen} />
+                                <Pressable disabled={true} onPress={goToNextPage}>
+                                    <Text
+                                        style={{
+                                            color: '#888888',
+                                            opacity: 0
+                                        }}
+                                    >{t('common.next')}</Text>
+                                </Pressable>
                             </View>
-                        </TouchableWithoutFeedback>
-                    ))}
+                        </View>
+                    </TouchableWithoutFeedback>
+                ))}
 
-                <View style={styles.bottomContainer}>{ScreenDisplay()}</View>
-            </KeyboardAwareScrollView>
-        </>
+            <View style={styles.bottomContainer}>{ScreenDisplay()}</View>
+        </KeyboardAwareScrollView>
     );
 };
 
@@ -193,4 +196,4 @@ const styles = StyleSheet.create({
     text: { fontSize: 24, fontWeight: '300' }
 });
 
-export default Form;
+export default Form;

+ 11 - 31
component/registrationMultiStepForm/formComponent/formPages/basicInformation.tsx

@@ -5,6 +5,7 @@ import DateModal from '../../../global/date_input';
 import NormalButton from '../../../global/normal_button';
 import useSignUpStore from '../../../../providers/signup_form_store';
 import DropdownSelect from '../../../global/dropdown_select';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 type basicInformationProps = {
     goToNextPage: () => void;
@@ -17,6 +18,8 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
     const [selectedDay, setSelectedDay] = useState('');
     const [birthDate, setBirthDate] = useState('');
     const [error, setError] = useState('');
+    const { t, ready, currentLanguage } = useTranslation();
+    
     const handleNext = () => {
         setSignUpFormData({
             ...signUpFormData,
@@ -28,14 +31,14 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
             signUpFormData.birthDateMonth === '' ||
             signUpFormData.birthDateDay === ''
         ) {
-            setError('請確保所有資料都已填寫。');
+            setError(t("register.three.error1"));
         } else {
             setError('');
             goToNextPage();
         }
     };
 
-    const nameFieldPlaceholder = signUpFormData.nickName ? signUpFormData.nickName : '暱稱';
+    const nameFieldPlaceholder = signUpFormData.nickName ? signUpFormData.nickName : t("register.three.name");
 
     const birthMonthOptions = Array.from({ length: 12 }, (_, i) => {
         const month = i + 1;
@@ -72,7 +75,7 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
     return (
         <>
             <View style={styles.container}>
-                <Text style={styles.text}>請填妥以下資料</Text>
+                <Text style={styles.text}>{t("register.three.label")}</Text>
                 <View
                     className=""
                     style={{
@@ -92,29 +95,7 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
                         }}
                     />
 
-                    {/* <NormalInput
-                        placeholder="帳戶密碼"
-                        onChangeText={(text) => {
-                            setSignUpFormData({
-                                ...signUpFormData,
-                                password: text
-                            });
-                        }}
-                        secureTextEntry={true}
-                    /> */}
-
                     <View className="">
-                        {/* <TestingDropDownSelect
-                            dropdownOptions={genderDropdownOptions}
-                            onSelect={(value) => {
-                                setSignUpFormData({
-                                    ...signUpFormData,
-                                    gender: value
-                                });
-                            }}
-                            placeholder={'性別'}
-                            extendedStyle={{ paddingLeft: 10, paddingVertical: 13 }}
-                        /> */}
                         <DropdownSelect
                             onSelect={(value) => {
                                 setSignUpFormData({
@@ -126,8 +107,8 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
                             placeholder={
                                 signUpFormData.gender
                                     ? genderDropdownOptions.find((option) => option.value === signUpFormData.gender)
-                                          ?.label || '性別'
-                                    : '性別'
+                                          ?.label || t("register.three.sex")
+                                    : t("register.three.sex")
                             }
                             extendedStyle={{ paddingLeft: 10, paddingVertical: 18 }}
                         />
@@ -141,11 +122,10 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
                                 });
                             }}
                             dropdownOptions={birthMonthOptions}
-                            // placeholder={'生日月份'}
                             placeholder={`${
                                 signUpFormData.birthDateMonth
                                     ? parseInt(signUpFormData.birthDateMonth).toString()
-                                    : '生日月份'
+                                    : t("register.three.mm")
                             }`}
                             extendedStyle={{ paddingLeft: 10, paddingVertical: 18, marginRight: 6 }}
                         />
@@ -161,13 +141,13 @@ const BasicInformation: React.FC<basicInformationProps> = ({ goToNextPage }) =>
                             placeholder={`${
                                 signUpFormData.birthDateDay
                                     ? parseInt(signUpFormData.birthDateDay).toString()
-                                    : '生日日期'
+                                    : t("register.three.dd")
                             }`}
                             extendedStyle={{ paddingLeft: 10, paddingVertical: 18, marginLeft: 6 }}
                         />
                     </View>
                     <NormalButton
-                        title={<Text style={{ color: '#fff' }}>下一步</Text>}
+                        title={<Text style={{ color: '#fff' }}>{t("register.three.next")}</Text>}
                         onPress={handleNext}
                         extendedStyle={{}}
                     />

+ 13 - 75
component/registrationMultiStepForm/formComponent/formPages/createWallet.tsx

@@ -3,44 +3,30 @@ import NormalInput from '../../../global/normal_input';
 import NormalButton from '../../../global/normal_button';
 import { Ionicons } from '@expo/vector-icons';
 import { useState } from 'react';
-import SingleSelectButtonGroup from '../../../global/select_button';
 import useSignUpStore from '../../../../providers/signup_form_store';
-import PhoneInput from '../../../global/phone_input';
 import { authenticationService } from '../../../../service/authService';
 import { Alert } from 'react-native';
 import useVehicleStore from '../../../../providers/vehicle_store';
 import { usePushNotifications } from '../../../../app/hooks/usePushNotifications';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
+
 type CreateWalletProps = {
     goToNextPage: () => void;
 };
-const creditCard = '信用卡';
-const weChatAliPay = '微信支付/支付寶';
 
 const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
     const { expoPushToken } = usePushNotifications();
-    const options = [{ label: creditCard }, { label: weChatAliPay }];
     const [isLoading, setIsLoading] = useState(false);
-    const [isLoading2, setIsLoading2] = useState(false);
     const { signUpFormData, setSignUpFormData } = useSignUpStore();
-    const phoneFieldPlaceholder = signUpFormData.phone ? signUpFormData.phone : '輸入電話號碼';
     const [error, setError] = useState('');
     const [showPassword1, setShowPassword1] = useState(false);
     const [showPassword2, setShowPassword2] = useState(false);
     const [passwordConfirm, setPasswordConfirm] = useState('');
     const {
-        vehicleBrand,
-        vehicleModel,
         BrandID,
         ModelID,
-        licensePlate,
-        setVehicleBrand,
-        setVehicleModel,
-        setBrandID,
-        setModelID,
-        setLicensePlate
     } = useVehicleStore();
-
-    // console.log('expoPushToken?.data', expoPushToken?.data);
+    const { t, ready, currentLanguage } = useTranslation();
 
     console.log('expoPushToken?.data', expoPushToken?.data);
 
@@ -52,7 +38,7 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
             gender: signUpFormData.gender,
             birthday: signUpFormData.birthDateDay + '/' + signUpFormData.birthDateMonth + '/11',
             address: signUpFormData.address,
-            phone: parseInt(signUpFormData.phone, 10),
+            phone: parseInt(signUpFormData.phone as string, 10),
             isUberDriver: signUpFormData.isUberDriver,
             notify_session_id:
                 expoPushToken?.data ||
@@ -67,39 +53,6 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
         };
     }
 
-    const selectLabelShown = () => {
-        if (signUpFormData.paymentMethod == null) {
-            return null;
-        } else if (signUpFormData.paymentMethod == creditCard) {
-            return creditCard;
-        } else if (signUpFormData.paymentMethod == weChatAliPay) {
-            return weChatAliPay;
-        }
-    };
-
-    const handleSelectedChange = (selectedLabel: string) => {
-        setSignUpFormData({ ...signUpFormData, paymentMethod: selectedLabel });
-        setError('');
-    };
-
-    const handleNextWithSkip = async () => {
-        setIsLoading2(true);
-        try {
-            const result = await authenticationService.signUp(customerData);
-            console.log('handleNextWithSkip in CreateWallet Page, i am sending this customerData', customerData);
-            if (result === true) {
-                goToNextPage();
-            } else {
-                Alert.alert('註冊錯誤', '註冊過程中出現錯誤,請稍後再試');
-            }
-        } catch (error) {
-            console.error('Sign up error:', error);
-            setError('註冊過程中出現錯誤,請稍後再試。');
-        } finally {
-            setIsLoading2(false);
-        }
-    };
-
     const handleNext = async () => {
         if (
             signUpFormData.email === '' ||
@@ -107,9 +60,9 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
             signUpFormData.phone === '' ||
             passwordConfirm === ''
         ) {
-            setError('請確保所有資料都已填寫。');
+            setError(t("register.four.error1"));
         } else if (signUpFormData.password !== passwordConfirm) {
-            Alert.alert('密碼錯誤', '兩次輸入的密碼不一致,請重新輸入。');
+            Alert.alert(t("register.four.alert1"));
         } else {
             setError('');
             setIsLoading(true);
@@ -119,11 +72,10 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
                 if (result) {
                     goToNextPage();
                 } else {
-                    Alert.alert('註冊錯誤', '註冊過程中出現錯誤,請稍後再試');
+                    Alert.alert(t("register.four.alert2"));
                 }
             } catch (error) {
-                setError('註冊過程中出現錯誤,請稍後再試。');
-                console.error('Sign up error:', error);
+                setError(t("register.four.error2"));
             } finally {
                 setIsLoading(false);
             }
@@ -131,9 +83,8 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
     };
 
     return (
-        <>
             <View style={styles.container}>
-                <Text style={styles.text}>請填妥以下資料</Text>
+                <Text style={styles.text}>{t("register.four.label")}</Text>
                 <View
                     style={{
                         display: 'flex',
@@ -142,7 +93,7 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
                     }}
                 >
                     <NormalInput
-                        placeholder="請填寫您的電子郵件"
+                        placeholder={t("register.four.label")}
                         onChangeText={(email) =>
                             setSignUpFormData({
                                 ...signUpFormData,
@@ -153,7 +104,7 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
                     />
 
                     <NormalInput
-                        placeholder="帳戶密碼"
+                        placeholder={t("register.four.password")}
                         onChangeText={(text) => {
                             setSignUpFormData({
                                 ...signUpFormData,
@@ -170,7 +121,7 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
                     </Pressable>
                     <View className="mb-4">
                         <NormalInput
-                            placeholder="請再次輸入帳戶密碼"
+                            placeholder={t("register.four.confirmPassword")}
                             onChangeText={(text) => setPasswordConfirm(text)}
                             secureTextEntry={!showPassword2}
                         />
@@ -185,29 +136,16 @@ const CreateWallet: React.FC<CreateWalletProps> = ({ goToNextPage }) => {
                             />
                         </Pressable>
                     </View>
-                    {/* <SingleSelectButtonGroup
-                        options={options}
-                        onSelectionChange={handleSelectedChange}
-                        selectedOption={selectLabelShown()}
-                    /> */}
                 </View>
                 {error && <Text style={styles.errorMessage}>{error}</Text>}
                 <View>
                     <NormalButton
-                        title={isLoading ? <ActivityIndicator /> : <Text style={{ color: '#fff' }}>完成</Text>}
+                        title={isLoading ? <ActivityIndicator /> : <Text style={{ color: '#fff' }}>{t("register.four.complete")}</Text>}
                         onPress={handleNext}
                         extendedStyle={{}}
                     />
-                    {/* 收起按鈕 */}
-                    {/* <NormalButton
-                        title={isLoading2 ? <ActivityIndicator /> : <Text style={{ color: '#888888' }}>略過</Text>}
-                        onPress={handleNextWithSkip}
-                        extendedStyle={{ backgroundColor: 'transparent' }}
-                        buttonPressedStyle={{ backgroundColor: 'transparent' }}
-                    /> */}
                 </View>
             </View>
-        </>
     );
 };
 

+ 13 - 12
component/registrationMultiStepForm/formComponent/formPages/finishSignUp.tsx

@@ -1,24 +1,25 @@
 import { View, Text, StyleSheet } from 'react-native';
 import NormalButton from '../../../global/normal_button';
 import { router } from 'expo-router';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 type FinishSignUpProps = {};
 
 const FinishSignUp: React.FC<FinishSignUpProps> = ({}) => {
+    const { t, ready, currentLanguage } = useTranslation();
+    
     return (
-        <>
-            <View style={styles.container}>
-                <View style={styles.textContainer}>
-                    <Text style={styles.titleText}>註冊成功</Text>
-                    <Text style={styles.text}>歡迎使用 Crazy Charge</Text>
-                    <Text style={styles.text}>祝你一路順“瘋“</Text>
-                </View>
-                <NormalButton
-                    title={<Text style={{ color: '#fff' }}>下一步</Text>}
-                    onPress={() => router.replace('/')}
-                />
+        <View style={styles.container}>
+            <View style={styles.textContainer}>
+                <Text style={styles.titleText}>{t('register.five.label')}</Text>
+                <Text style={styles.text}>{t('register.five.welcome')}</Text>
+                <Text style={styles.text}>{t('register.five.content')}</Text>
             </View>
-        </>
+            <NormalButton
+                title={<Text style={{ color: '#fff' }}>{t('register.five.next')}</Text>}
+                onPress={() => router.replace('/')}
+            />
+        </View>
     );
 };
 

+ 16 - 17
component/registrationMultiStepForm/formComponent/formPages/loginPage.tsx

@@ -16,7 +16,6 @@ import NormalButton from '../../../global/normal_button';
 import NormalInput from '../../../global/normal_input';
 import { useEffect, useState } from 'react';
 import { useAuth } from '../../../../context/AuthProvider';
-import { useSafeAreaInsets } from 'react-native-safe-area-context';
 import AsyncStorage from '@react-native-async-storage/async-storage';
 import Checkbox from 'expo-checkbox';
 import { router } from 'expo-router';
@@ -67,11 +66,11 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
     const _login = async (username: string, password: string) => {
         setIsLoading(true);
         if (username === '' || password === '') {
-            Alert.alert('請輸入資料', '請輸入電話號碼和密碼');
+            Alert.alert(t('login.alert.pleaseEnter'));
         } else if (username.includes('@')) {
-            Alert.alert('請綁定您的手機號碼', '客戶現在起只能使用已經綁定的手機號碼進行登入', [
-                { text: '我要進行綁定', onPress: () => goToBindingPhoneNumberPage() },
-                { text: '我已綁定,帶我回登入頁面', onPress: () => router.replace('/login') }
+            Alert.alert(t('login.alert.binding'), t('login.alert.binding1'), [
+                { text: t('login.alert.binding2'), onPress: () => goToBindingPhoneNumberPage() },
+                { text: t('login.alert.binding3'), onPress: () => router.replace('/login') }
             ]);
         } else {
             if (userTerms) {
@@ -87,10 +86,10 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                         await AsyncStorage.removeItem('savedPassword');
                     }
                 } else {
-                    Alert.alert('登入失敗', `原因: ${response}`);
+                    Alert.alert(t('login.alert.error'), `${t('login.alert.reason')}: ${response}`);
                 }
             } else {
-                Alert.alert('請先同意用戶條款');
+                Alert.alert(t('login.alert.agree'));
 
             }
             
@@ -129,18 +128,18 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                     className="mx-[5%] mt-4"
                 >
                     <Text className="text-lg text-center text-[#888888] font-[500]">
-                        {t('login.tip1')}<Text className="font-bold">必須</Text>綁定手機號碼才能登入
+                        {t('login.tip1')}<Text className="font-bold"> {t('login.tip2')} </Text>{t('login.tip3')}
                     </Text>
                     <Pressable onPress={goToBindingPhoneNumberPage}>
                         <Text className="text-xl text-center text-[#02677D] font-[800] underline">
-                            立即按我前往綁定頁面
+                            {t('login.binding')}
                         </Text>
                     </Pressable>
 
                     <PhoneInput
                         value={loginPhone}
                         onChangeText={(phone) => setLoginPhone(phone)}
-                        placeholder="輸入電話號碼"
+                        placeholder={t('login.phone')}
                         extendedStyle={{ borderRadius: 12, padding: 20 }}
                         textContentType="telephoneNumber"
                         autoComplete="tel"
@@ -150,7 +149,7 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                     <View className="relative">
                         <NormalInput
                             value={loginPassword}
-                            placeholder="密碼"
+                            placeholder={t('login.password')}
                             onChangeText={(password) => setLoginPassword(password)}
                             secureTextEntry={!showPassword}
                             extendedStyle={{ borderRadius: 12, padding: 20, paddingRight: 50 }}
@@ -179,7 +178,7 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                             }}
                         />
 
-                        <Text style={styles.text}>記住我的電話號碼</Text>
+                        <Text style={styles.text}>{t('login.rememberPhone')}</Text>
                         
                     </View>
                     <View className="flex flex-row items-center">
@@ -192,8 +191,8 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                             }}
                         />
 
-                        <Text style={styles.text}>登入即同意
-                            <Text style={styles.userTerms} onPress={goToUserTermsPage}>用戶條款</Text>
+                        <Text style={styles.text}>{t('login.termsofService')}
+                            <Text style={styles.userTerms} onPress={goToUserTermsPage}>{t('login.termsofService1')}</Text>
                         </Text>
                     </View>
 
@@ -219,17 +218,17 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                                         color: '#fff'
                                     }}
                                 >
-                                    登入
+                                    {t('login.signIn')}
                                 </Text>
                             )
                         }
                     />
                     <View className="flex flex-row justify-between relative">
                         <Pressable className="self-start" onPress={goToNextPage}>
-                            <Text style={styles.text}>註冊會員</Text>
+                            <Text style={styles.text}>{t('login.register')}</Text>
                         </Pressable>
                         <Pressable className="self-start" onPress={() => goToForgetPassWordPage()}>
-                            <Text style={styles.text}>忘記密碼</Text>
+                            <Text style={styles.text}>{t('login.forgotPassword')}</Text>
                         </Pressable>
                     </View>
                 </View>

+ 47 - 68
component/registrationMultiStepForm/formComponent/formPages/verification.tsx

@@ -6,6 +6,7 @@ import NormalButton from '../../../global/normal_button';
 import useSignUpStore from '../../../../providers/signup_form_store';
 import { authenticationService } from '../../../../service/authService';
 import { usePushNotifications } from '../../../../app/hooks/usePushNotifications';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 type VerificationProps = {
     setScreen: React.Dispatch<React.SetStateAction<number>>;
@@ -20,11 +21,12 @@ const Verification: React.FC<VerificationProps> = ({ setScreen }) => {
     const [countdown, setCountdown] = useState(0);
     const [loading, setLoading] = useState(false);
     const { expoPushToken } = usePushNotifications();
-    const notify_session_id = expoPushToken?.data || '';
+    const { t, ready, currentLanguage } = useTranslation();
+    
     const handleVerification = async () => {
         setLoading(true);
         if (signUpFormData.phone === '' || otp === '') {
-            setError('請確保所有資料都已填寫。');
+            setError(t("register.two.error1"));
         } else {
             setError('');
             console.log('signUpFormData.phone', signUpFormData.phone);
@@ -32,18 +34,18 @@ const Verification: React.FC<VerificationProps> = ({ setScreen }) => {
             console.log('notifysession id in handleVerification', expoPushToken?.data);
             try {
                 const result = await authenticationService.verifyPhoneOtp(
-                    signUpFormData.phone,
+                    signUpFormData.phone as string,
                     otp,
-                    expoPushToken?.data
+                    expoPushToken?.data as string
                 );
                 if (result.status === 200) {
                     setScreen(2);
                 } else {
-                    setError('OTP驗證失敗,請重新輸入');
+                    setError(t("register.two.error2"));
                 }
             } catch (error) {
                 console.log('error', error);
-                setError('OTP驗證失敗,請重新輸入');
+                setError(t("register.two.error2"));
             } finally {
                 setLoading(false);
             }
@@ -73,7 +75,7 @@ const Verification: React.FC<VerificationProps> = ({ setScreen }) => {
                     setError('');
                 } catch (error) {
                     console.log(error);
-                    setError('發送OTP失敗,請聯絡工作人員');
+                    setError(t("register.two.error3"));
                     setCanSendOtp(true); // Reset canSendOtp if there's an error
                     setLockPhoneInput(false); // Unlock phone input if there's an error
                 }
@@ -83,80 +85,57 @@ const Verification: React.FC<VerificationProps> = ({ setScreen }) => {
                 }, 60000);
                 // setError('');
             } else {
-                setError('請等待一分鐘後再重新發送。');
+                setError(t("register.two.error4"));
             }
         } else {
-            setError('請確保所有資料都已填寫。');
+            setError(t("register.two.error5"));
         }
     };
 
-    const handleChangePhoneNumber = () => {
-        setLockPhoneInput(false);
-    };
-
     const otpButtonText = lockPhoneInput ? (
-        <Text style={{ color: '#fff' }}>已發送 ({countdown}s)</Text>
+        <Text style={{ color: '#fff' }}>{t("register.two.spending")} ({countdown}s)</Text>
     ) : (
-        <Text style={{ color: '#fff' }}>發送</Text>
+        <Text style={{ color: '#fff' }}>{t("register.two.spend")}</Text>
     );
 
     return (
-        <>
-            <View style={styles.container}>
-                <Text style={styles.text}>請驗證您的手機號碼</Text>
-                <PhoneInput
-                    value={signUpFormData?.phone || ''}
-                    onChangeText={(phone: any) =>
-                        setSignUpFormData({
-                            ...signUpFormData,
-                            phone: phone
-                        })
-                    }
-                    placeholder="請輸入手機號碼"
-                    editable={!lockPhoneInput}
-                    extendedStyle={{ opacity: !lockPhoneInput ? 1 : 0.5 }}
-                />
-                {/* <NormalInput
-                    placeholder="請填寫您的手機號碼"
-                    onChangeText={(phone) =>
-                        setSignUpFormData({
-                            ...signUpFormData,
-                            phone: phone
-                        })
-                    }
-                    editable={!lockPhoneInput}
-                    extendedStyle={{ opacity: !lockPhoneInput ? 1 : 0.5 }}
-                    autoCapitalize="none"
-                /> */}
-                <View
-                    style={{
-                        display: 'flex',
-                        flexDirection: 'row',
-                        paddingVertical: 10,
-                        gap: 10
-                    }}
-                >
-                    <NumberInput placeholder="OTP驗證碼" onChangeText={setOtp} extendedStyle={{ flex: 1 }} />
-                    <NormalButton
-                        title={otpButtonText}
-                        onPress={handleSubmitOtp}
-                        extendedStyle={{ flex: 1 / 2, opacity: !lockPhoneInput ? 1 : 0.5 }}
-                    />
-                </View>
+        <View style={styles.container}>
+            <Text style={styles.text}>{t('register.two.label')}</Text>
+            <PhoneInput
+                value={signUpFormData?.phone || ''}
+                onChangeText={(phone: any) =>
+                    setSignUpFormData({
+                        ...signUpFormData,
+                        phone: phone
+                    })
+                }
+                placeholder={t('register.two.phone')}
+                editable={!lockPhoneInput}
+                extendedStyle={{ opacity: !lockPhoneInput ? 1 : 0.5 }}
+            />
+            <View
+                style={{
+                    display: 'flex',
+                    flexDirection: 'row',
+                    paddingVertical: 10,
+                    gap: 10
+                }}
+            >
+                <NumberInput placeholder={t('register.two.code')} onChangeText={setOtp} extendedStyle={{ flex: 1 }} />
                 <NormalButton
-                    title={<Text style={{ color: '#fff' }}>{loading ? '驗證中...' : '驗證'}</Text>}
-                    onPress={() => {
-                        handleVerification();
-                    }}
-                    extendedStyle={{}}
+                    title={otpButtonText}
+                    onPress={handleSubmitOtp}
+                    extendedStyle={{ flex: 1 / 2, opacity: !lockPhoneInput ? 1 : 0.5 }}
                 />
-                {error && <Text style={styles.errorMessage}>{error}</Text>}
-
-                {/* <Pressable onPress={handleChangePhoneNumber}>
-                    <Text style={[styles.footer, { opacity: lockPhoneInput ? 1 : 0 }]}>修改手機號碼</Text>
-                </Pressable> */}
             </View>
-        </>
+            <NormalButton
+                title={<Text style={{ color: '#fff' }}>{loading ? t('register.two.verifying') : t('register.two.verify')}</Text>}
+                onPress={() => {
+                    handleVerification();
+                }}
+            />
+            {error && <Text style={styles.errorMessage}>{error}</Text>}
+        </View>
     );
 };
 

+ 2 - 2
component/resultDetailPage/resultDetailPageComponent.tsx

@@ -351,14 +351,14 @@ const styles = StyleSheet.create({
         color: '#000000'
     },
     leftLable: {
-        width: 160,
+        width: '65%',
         fontSize: 17,
         color:'#000000',
         textAlign: 'center'
     },
     rightLable: {
         fontSize: 17,
-        width: 100,
+        width: '30%',
         textAlign: 'center',
         borderLeftWidth: 1,
         paddingLeft: 0,

+ 124 - 1
i18n/locales/en/translation.json

@@ -3,9 +3,132 @@
     "tip1": "Tip: Old users",
     "tip2": "Must",
     "tip3": "Bind your phone number to log in",
-    "binding": "Press me now to go to the binding page"
+    "binding": "Press me now to go to the binding page",
+    "phone": "Enter phone number",
+    "password": "Password",
+    "rememberPhone": "Remember my phone number",
+    "termsofService": "By logging in, you agree to",
+    "termsofService1": "Terms of Service",
+    "signIn": "Sign In",
+    "register": "Register",
+    "forgotPassword": "Forgot Password",
+    "alert": {
+      "pleaseEnter": "Please enter phone number and password",
+      "binding": "Please bind your phone number",
+      "binding1": "Customers can now only log in using bound phone numbers",
+      "binding2": "I want to bind now",
+      "binding3": "I have bound, take me back to login page",
+      "error": "Login failed",
+      "reason": "Reason",
+      "agree": "Please agree to the terms of service first"
+    }
+  },
+  "register": {
+    "phone_verification": "Sign Up - Phone Verification",
+    "basic_info": "Sign Up - Basic Information",
+    "create_wallet": "Sign Up - Create Wallet",
+    "two": {
+      "label": "Please verify your phone number",
+      "phone": "Please enter phone number",
+      "code": "OTP verification code",
+      "spend": "Send",
+      "spending": "Sent",
+      "verify": "Verify",
+      "verifying": "Verifying...",
+      "error1": "Please ensure all fields are filled.",
+      "error2": "OTP verification failed, please re-enter",
+      "error3": "Failed to send OTP, please contact support",
+      "error4": "Please wait one minute before sending again.",
+      "error5": "Please ensure all fields are filled."
+    },
+    "three": {
+      "label": "Please fill in the following information",
+      "name": "Nickname",
+      "sex": "Gender",
+      "mm": "Birth month",
+      "dd": "Birth date",
+      "next": "Next step",
+      "error1": "Please ensure all fields are filled."
+    },
+    "four": {
+      "label": "Please enter your email",
+      "password": "Account password",
+      "confirmPassword": "Please enter account password again",
+      "complete": "Complete",
+      "error1": "Please ensure all fields are filled.",
+      "error2": "Error occurred during registration, please try again later.",
+      "alert1": "Password error", 
+      "alert2": "Registration error", 
+      "alert3": "The two passwords entered do not match, please re-enter.",
+      "alert4": "Error occurred during registration, please try again later."
+    },
+    "five": {
+      "label": "Registration successful",
+      "welcome": "Welcome to Crazy Charge",
+      "content": "Have a smooth journey",
+      "next": "Next step"
+    }
+  },
+  "forgotPassword": {
+    "phone_verification": "Forgot Password - Phone Verification",
+    "one": {
+      "verify_email_to_reset": "Verify your email to reset password",
+      "enter_your_email": "Please enter your email",
+      "otp_verification_code": "OTP verification code",
+      "sent": "Sent",
+      "send": "Send",
+      "verifying": "Verifying...",
+      "verified": "Verified",
+      "verify": "Verify",
+      "modify_email": "Modify email",
+      "new_password": "New password",
+      "confirm_password": "Confirm password",
+      "resetting": "Resetting...",
+      "reset": "Reset",
+      "ensure_all_fields_filled": "Please ensure all fields are filled",
+      "enter_otp_code": "Please enter OTP code",
+      "error_verifying_otp": "Error verifying OTP, please try again later",
+      "wait_one_minute": "Please wait one minute before sending again",
+      "passwords_do_not_match": "Please ensure new password and confirm password match",
+      "password_reset_failed": "Password reset failed, please try again later",
+      "error_occurred": "An error occurred, please try again later"
+    },
+    "two": {
+      "success_title": "Password Reset Successful",
+      "welcome_message": "Welcome to Crazy Charge",
+      "good_luck": "Have a smooth journey",
+      "finish": "Finish"
+    }
+  },
+  "binding": {
+    "old_user_phone_binding_step1": "Old User Phone Binding (1/2)",
+    "old_user_phone_binding_step2": "Old User Phone Binding (2/2)",
+    "one": {
+      "enter_existing_email": "Please enter existing email",
+      "enter_your_email": "Please enter your email",
+      "enter_your_password": "Please enter your password",
+      "processing": "Processing...",
+      "login_failed": "Login failed, please check your credentials and try again"
+    },
+    "two": {
+      "enter_phone_for_login": "Please enter your phone number, which will be used for login",
+      "enter_phone_number": "Please enter phone number",
+      "otp_verification_code": "OTP verification code",
+      "sent": "Sent",
+      "send": "Send",
+      "confirm": "Confirm",
+      "processing": "Processing...",
+      "phone_binding_failed": "Phone number binding failed, please check your OTP and try again",
+      "confirm_phone_number": "Confirm your phone number",
+      "phone_usage_notice": "You will use this number for future logins. Please confirm that you are aware.",
+      "confirm_and_send_otp": "Confirm and send verification code",
+      "send_otp_failed": "Failed to send OTP, please contact support",
+      "change_phone_failed": "Failed to change phone number, please try again later"
+    }
   },
   "common": {
+    "previous": "< Previous step",
+    "next": "Next step >",
     "confirm": "Confirm",
     "cancel": "Cancel",
     "title": ""

+ 122 - 1
i18n/locales/zh-TW/translation.json

@@ -3,9 +3,130 @@
     "tip1": "提示: 舊用戶",
     "tip2": "必須",
     "tip3": "綁定手機號碼才能登入",
-    "binding": "立即按我前往綁定頁面"
+    "binding": "立即按我前往綁定頁面",
+    "phone": "輸入電話號碼",
+    "password": "密碼",
+    "rememberPhone": "記住我的電話號碼",
+    "termsofService": "登入即同意",
+    "termsofService1": "用戶條款",
+    "signIn": "登入",
+    "register": "註冊會員",
+    "forgotPassword": "忘記密碼",
+    "alert": {
+      "pleaseEnter": "請輸入電話號碼和密碼",
+      "binding": "請綁定您的手機號碼",
+      "binding1": "客戶現在起只能使用已經綁定的手機號碼進行登入",
+      "binding2": "我要進行綁定",
+      "binding3": "我已綁定,帶我回登入頁面",
+      "error": "登入失敗",
+      "reason": "原因",
+      "agree": "請先同意用戶條款"
+    }
+  },
+  "register": {
+    "phone_verification": "註冊 - 電話驗證",
+    "basic_info": "註冊 - 基本資料",
+    "create_wallet": "註冊 - 設立銀包",
+    "two": {
+      "label": "請驗證您的手機號碼",
+      "phone": "請輸入手機號碼",
+      "code": "OTP驗證碼",
+      "spend": "發送",
+      "spending": "已發送",
+      "verify": "驗證",
+      "verifying": "驗證中...",
+      "error1": "請確保所有資料都已填寫。",
+      "error2": "OTP驗證失敗,請重新輸入",
+      "error3": "發送OTP失敗,請聯絡工作人員",
+      "error4": "請等待一分鐘後再重新發送。",
+      "error5": "請確保所有資料都已填寫。"
+    },
+    "three": {
+      "label": "請填妥以下資料",
+      "name": "暱稱",
+      "sex": "性別",
+      "mm": "生日月份",
+      "dd": "生日日期",
+      "next": "下一步",
+      "error1": "請確保所有資料都已填寫。"
+    },
+    "four": {
+      "label": "請填寫您的電子郵件",
+      "password": "帳戶密碼",
+      "confirmPassword": "請再次輸入帳戶密碼",
+      "complete": "完成",
+      "error1": "請確保所有資料都已填寫。",
+      "error2": "註冊過程中出現錯誤,請稍後再試。",
+      "alert1": "密碼錯誤', '兩次輸入的密碼不一致,請重新輸入。",
+      "alert2": "註冊錯誤', '註冊過程中出現錯誤,請稍後再試"
+    },
+    "five": {
+      "label": "註冊成功",
+      "welcome": "歡迎使用Crazy Charge",
+      "content": "祝你一路順“瘋“",
+      "next": "下一步"
+    }
+  },
+  "forgotPassword": {
+    "phone_verification": "忘記密碼 - 電話驗證" ,
+    "one": {
+      "verify_email_to_reset": "驗證電子郵件後即可重置密碼",
+      "enter_your_email": "請填寫您的電子郵件",
+      "otp_verification_code": "OTP驗證碼",
+      "sent": "已發送",
+      "send": "發送",
+      "verifying": "驗證中...",
+      "verified": "已驗證",
+      "verify": "驗證",
+      "modify_email": "修改電子郵件",
+      "new_password": "新密碼",
+      "confirm_password": "確認密碼",
+      "resetting": "重置中...",
+      "reset": "重置",
+      "ensure_all_fields_filled": "請確保所有資料都已填寫",
+      "enter_otp_code": "請輸入OTP驗證碼",
+      "error_verifying_otp": "驗證OTP時發生錯誤,請稍後再試",
+      "wait_one_minute": "請等待一分鐘後再重新發送。",
+      "passwords_do_not_match": "請確保新密碼和確認密碼相同",
+      "password_reset_failed": "密碼重置失敗,請稍後再試",
+      "error_occurred": "發生錯誤,請稍後再試"
+    },
+    "two": {
+      "success_title": "重置密碼成功",
+      "welcome_message": "歡迎使用 Crazy Charge",
+      "good_luck": "祝你一路順“瘋“",
+      "finish": "完成"
+    }
+  },
+  "binding": {
+    "old_user_phone_binding_step1": "舊用戶手機號碼綁定 (1/2)",
+    "old_user_phone_binding_step2": "舊用戶手機號碼綁定 (2/2)",
+    "one": {
+      "enter_existing_email": "請輸入現有電子郵件",
+      "enter_your_email": "請填寫您的電子郵件",
+      "enter_your_password": "請填寫您的密碼",
+      "processing": "處理中...",
+      "login_failed": "登入失敗,請檢查您輸入的帳號密碼並再試一次"
+    },
+    "two": {
+      "enter_phone_for_login": "請輸入手機號碼,此手機號碼將用作登入用途",
+      "enter_phone_number": "請輸入手機號碼",
+      "otp_verification_code": "OTP驗證碼",
+      "sent": "已發送",
+      "send": "發送",
+      "confirm": "確認",
+      "processing": "處理中...",
+      "phone_binding_failed": "綁定手機號碼失敗,請檢查您輸入的OTP並再試一次",
+      "confirm_phone_number": "確認您的手機號碼",
+      "phone_usage_notice": "您以後將使用現在輸入的號碼進行登入。請按下確認表示您已知悉。",
+      "confirm_and_send_otp": "確認並發出驗證碼",
+      "send_otp_failed": "發送OTP失敗,請聯絡工作人員",
+      "change_phone_failed": "修改手機號碼失敗,請稍後再試"
+    }
   },
   "common": {
+    "previous": "< 上一步",
+    "next": "下一步 >",
     "confirm": "確認",
     "cancel": "取消",
     "title": ""