- Login timeout
- Please input your password
+ {t('loginAction.LoginTimeout')}
+ {t('loginAction.LoginTimeoutTip')}
- setPassword(e.target.value)}
onPressEnter={() => onSubmit()}
addonBefore={login.username} />
onSubmit()}
- >Submit
-
+ >{t('common.Submit')}
+
Reservation },
- { key: "invoice", label: Invoice },
- { key: "feedback", label: Feedback },
+ { key: "reservation", label: {t('menu.Reservation')} },
+ { key: "invoice", label: {t('menu.Invoice')} },
+ { key: "feedback", label: {t('menu.Feedback')} },
// { key: "report", label: Report },
{
key: "notice",
label: (
- Notice
+ {t('menu.Notice')}
{noticeUnRead ? : ""}
),
@@ -188,7 +192,7 @@ function App() {
{authStore.login.travelAgencyName}
-
+
+
+
+
{
+ const { t, i18n } = useTranslation();
+ const [selectedKeys, setSelectedKeys] = useState([i18n.language]);
+ // 切换语言事件
+ const handleChangeLanguage = ({ key }) => {
+ setSelectedKeys([key]);
+ i18n.changeLanguage(key);
+ };
+
+ const langSupports = ['en', 'zh'].map((lang) => ({ label: t(`lang.${lang}`), key: lang }));
+
+ /* 🌏🌐 */
+ return (
+
+ 🌐{t(`lang.${i18n.language}`)}
+
+ );
+};
+
+export default Language;
diff --git a/src/views/Login.jsx b/src/views/Login.jsx
index 1dff00b..ce148d4 100644
--- a/src/views/Login.jsx
+++ b/src/views/Login.jsx
@@ -2,9 +2,10 @@ import { useNavigate, useLocation } from "react-router-dom";
import { useEffect } from 'react';
import { Button, Checkbox, Form, Input, Row, App } from 'antd';
import { useStore } from '@/stores/StoreContext.js';
-
+import { useTranslation } from 'react-i18next';
function Login() {
+ const { t, i18n } = useTranslation();
const { authStore, noticeStore } = useStore();
const { notification } = App.useApp();
@@ -13,7 +14,7 @@ function Login() {
const [form] = Form.useForm();
useEffect (() => {
- if (location.search === '?out') {
+ if (location.search === '?out') {
authStore.logout();
navigate('/login');
}
@@ -49,7 +50,7 @@ function Login() {
});
});
};
-
+
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
@@ -78,7 +79,7 @@ function Login() {
autoComplete="off"
>
- Login
+ {t('common.Login')}
@@ -116,4 +117,4 @@ function Login() {
);
}
-export default Login;
\ No newline at end of file
+export default Login;
diff --git a/src/views/Standlone.jsx b/src/views/Standlone.jsx
index 93333f7..f4a12ba 100644
--- a/src/views/Standlone.jsx
+++ b/src/views/Standlone.jsx
@@ -6,6 +6,7 @@ import { DownOutlined } from "@ant-design/icons";
import "antd/dist/reset.css";
import AppLogo from "@/assets/logo-gh.png";
import { useStore } from "@/stores/StoreContext.js";
+import Language from "./Language";
const { Title } = Typography;
const { Header, Content, Footer } = Layout;
@@ -35,7 +36,10 @@ function Standlone() {
- Global Highlights Hub
+ Global Highlights Hub
+
+
+
);
}
-
+
function attachmentRender(text, confirm) {
return (
<>
@@ -60,10 +62,10 @@ function Detail() {
>
);
}
-
+
function confirmRender(text, confirm) {
return (
- showConfirmModal(confirm)}>Confirm
+ showConfirmModal(confirm)}>{t('common.Confirm')}
);
}
@@ -78,18 +80,18 @@ function Detail() {
const { authStore, reservationStore } = useStore();
const { reservationDetail, confirmationList } = reservationStore;
const { login } = authStore;
- const officeWebViewerUrl =
+ const officeWebViewerUrl =
'https://view.officeapps.live.com/op/embed.aspx?wdPrint=1&wdHideGridlines=0&wdHideComments=1&wdEmbedCode=0&src=';
// 测试文档:https://www.chinahighlights.com/public/reservationW220420009.doc
- const reservationUrl =
+ const reservationUrl =
`https://p9axztuwd7x8a7.mycht.cn/service-fileServer/DownloadPlanDoc?GRI_SN=${reservationId}&VEI_SN=${login.travelAgencyId}&token=${login.token}&FileType=1`;
- const nameCardUrl =
+ const nameCardUrl =
`https://p9axztuwd7x8a7.mycht.cn/service-fileServer/DownloadPlanDoc?GRI_SN=${reservationId}&VEI_SN=${login.travelAgencyId}&token=${login.token}&FileType=2`;
const reservationPreviewUrl = officeWebViewerUrl + encodeURIComponent(reservationUrl);
const nameCardPreviewUrl = officeWebViewerUrl + encodeURIComponent(nameCardUrl);
- const showConfirmModal = (confirm) => {
+ const showConfirmModal = (confirm) => {
setIsModalOpen(true);
const formattedText = confirm.PCI_ConfirmText;//.replace(/\;/g, "\n——————————————————————\n");
setConfirmText(formattedText);
@@ -153,31 +155,31 @@ function Detail() {
- Reference Number: {reservationDetail.referenceNumber}; Arrival date: {reservationDetail.arrivalDate};
+ {t('group.RefNo')}: {reservationDetail.referenceNumber}; {t('group.ArrivalDate')}: {reservationDetail.arrivalDate};
- navigate('/reservation/newest?back')}>Back
+ navigate('/reservation/newest?back')}>{t('common.Back')}
- Download Itinerary
+ {t('common.Download')} Itinerary
- Download Name Card
+ {t('common.Download')} Name Card
-
-
+
diff --git a/src/views/reservation/Newest.jsx b/src/views/reservation/Newest.jsx
index 57d471f..83c6196 100644
--- a/src/views/reservation/Newest.jsx
+++ b/src/views/reservation/Newest.jsx
@@ -7,13 +7,17 @@ import dayjs from "dayjs";
import { useStore } from '@/stores/StoreContext.js';
import { DATE_PRESETS } from "@/config";
import { formatDate, isEmpty } from "@/utils/commons";
+import { useTranslation } from 'react-i18next';
+import usePresets from '@/hooks/usePresets';
const { Title } = Typography;
function Newest() {
+ const { t } = useTranslation();
+ const presets = usePresets();
const reservationListColumns = [
{
- title: 'Reference number',
+ title: t('group.RefNo'),
dataIndex: 'referenceNumber',
key: 'Reference number',
render: (text, record) => {
@@ -28,47 +32,47 @@ function Newest() {
},
},
{
- title: 'Arrival date',
+ title: t('group.ArrivalDate'),
dataIndex: 'arrivalDate',
key: 'Arrival date',
render: (text, record) => (isEmpty(text) ? '' : dayjs(text).format('YYYY-MM-DD')),
},
{
- title: 'Pax',
+ title: t('group.Pax'),
key: 'Pax',
dataIndex: 'pax'
},
{
- title: 'Status',
+ title: t('group.Status'),
key: 'Status',
dataIndex: 'status'
},
{
- title: 'Res. sending date',
+ title: t('group.ResSendingDate'),
key: 'Reservation date',
dataIndex: 'reservationDate',
render: (text, record) => (isEmpty(text) ? '' : dayjs(text).format('YYYY-MM-DD')),
},
{
- title: 'Guide',
+ title: t('group.Guide'),
key: 'Guide',
dataIndex: 'guide',
render: guideRender
},
];
-
+
function guideRender(text, reservation) {
if (reservation.guide === '') {
return (
- showCityGuideModal(reservation)}>Add
+ showCityGuideModal(reservation)}>{t('common.Add')}
);
} else {
return (
{reservation.guide}
- showCityGuideModal(reservation)}>Edit
+ showCityGuideModal(reservation)}>{t('common.Edit')}
);
}
@@ -110,7 +114,7 @@ function Newest() {
useEffect (() => {
if (location.search !== '?back') {
- // 第一页,未确认计划
+ // 第一页,未确认计划
onSearchClick(1, 1);
}
reservationStore.fetchAllGuideList()
@@ -129,7 +133,7 @@ function Newest() {
}, []);
const showCityGuideModal = (reservation) => {
- setDataLoading(true);
+ setDataLoading(true);
setIsModalOpen(true);
reservationStore.editReservation(reservation);
reservationStore.fetchCityList(reservation.reservationId)
@@ -156,7 +160,7 @@ function Newest() {
setIsModalOpen(false);
setDataLoading(false);
};
-
+
// 默认重新搜索第一页,所有状态的计划
const onSearchClick = (current=1, status=null) => {
setDataLoading(true);
@@ -189,12 +193,12 @@ function Newest() {
pagination={false}
columns={[
{
- title: 'City',
+ title: t('group.City'),
dataIndex: 'cityName',
key: 'cityName'
},
{
- title: 'Tour Guide',
+ title: t('group.Guide'),
dataIndex: 'tourGuide',
key: 'tourGuide',
render: cityGuideRender,
@@ -210,32 +214,32 @@ function Newest() {
- { reservationStore.updatePropertyValue('referenceNo', e.target.value)} } />
+ { reservationStore.updatePropertyValue('referenceNo', e.target.value)} } />
- Arrival Date
+ {t('group.ArrivalDate')}
{
+ onChange={(dateRange) => {
reservationStore.updatePropertyValue('arrivalDateRange', dateRange == null ? [] : dateRange)
}}
/>
- onSearchClick()} loading={dataLoading}>Search
+ onSearchClick()} loading={dataLoading}>{t('common.Search')}
'Reservations without the tour guide information will be highlighted in red if the arrival date is within 3 days.'}
+ title={() => t('group.3DGuideTip')}
bordered
loading={dataLoading}
pagination={{
@@ -255,4 +259,4 @@ function Newest() {
);
}
-export default observer(Newest);
\ No newline at end of file
+export default observer(Newest);