mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
Perf: i18n change and captcha code. (#2625)
* perf: send captcha check * perf: back router * perf: i18n init * perf: ui * i18n * perf: ui duration
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
|
||||
module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: 'zh',
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'zh'],
|
||||
localeDetection: false
|
||||
},
|
||||
localePath:
|
||||
typeof window === 'undefined' ? require('path').resolve('../../packages/web/i18n') : '/i18n',
|
||||
reloadOnPrerender: process.env.NODE_ENV === 'development'
|
||||
}
|
||||
};
|
||||
|
@@ -68,7 +68,6 @@
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
"@types/formidable": "^2.0.5",
|
||||
"@types/js-cookie": "^3.0.3",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/jsonwebtoken": "^9.0.3",
|
||||
"@types/lodash": "^4.14.191",
|
||||
|
@@ -7,9 +7,11 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { getUnreadCount } from '@/web/support/user/inform/api';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useI18nLng } from '@fastgpt/web/hooks/useI18n';
|
||||
|
||||
import Auth from './auth';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import { useMount } from 'ahooks';
|
||||
const Navbar = dynamic(() => import('./navbar'));
|
||||
const NavbarPhone = dynamic(() => import('./navbarPhone'));
|
||||
const UpdateInviteModal = dynamic(() => import('@/components/support/user/team/UpdateInviteModal'));
|
||||
@@ -46,6 +48,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
const { loading, feConfigs, isNotSufficientModal } = useSystemStore();
|
||||
const { isPc } = useSystem();
|
||||
const { userInfo } = useUserStore();
|
||||
const { setUserDefaultLng } = useI18nLng();
|
||||
|
||||
const isChatPage = useMemo(
|
||||
() => router.pathname === '/chat' && Object.values(router.query).join('').length !== 0,
|
||||
@@ -61,6 +64,10 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
||||
|
||||
const isHideNavbar = !!pcUnShowLayoutRoute[router.pathname];
|
||||
|
||||
useMount(() => {
|
||||
setUserDefaultLng();
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box h={'100%'} bg={'myGray.100'}>
|
||||
|
@@ -37,7 +37,7 @@ const SendCodeAuthModal = ({
|
||||
<Skeleton
|
||||
minH="200px"
|
||||
isLoaded={!loading}
|
||||
fadeDuration={2}
|
||||
fadeDuration={1}
|
||||
display={'flex'}
|
||||
justifyContent={'center'}
|
||||
my={1}
|
||||
|
@@ -15,6 +15,7 @@ import NextHead from '@/components/common/NextHead';
|
||||
function App({ Component, pageProps }: AppProps) {
|
||||
const { feConfigs, scripts, title } = useInitApp();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<NextHead
|
||||
|
@@ -7,8 +7,10 @@ import { UserType } from '@fastgpt/global/support/user/type';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
import { langMap, setLngStore } from '@/web/common/utils/i18n';
|
||||
import { langMap } from '@/web/common/utils/i18n';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useI18nLng } from '@fastgpt/web/hooks/useI18n';
|
||||
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import TimezoneSelect from '@fastgpt/web/components/common/MySelect/TimezoneSelect';
|
||||
|
||||
@@ -16,7 +18,7 @@ const Individuation = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { userInfo, updateUserInfo } = useUserStore();
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { onChangeLng } = useI18nLng();
|
||||
|
||||
const { reset } = useForm<UserUpdateParams>({
|
||||
defaultValues: userInfo as UserType
|
||||
@@ -55,14 +57,7 @@ const Individuation = () => {
|
||||
}))}
|
||||
onchange={(val: any) => {
|
||||
const lang = val;
|
||||
setLngStore(lang);
|
||||
router.replace(
|
||||
{
|
||||
query: router.query
|
||||
},
|
||||
router.asPath,
|
||||
{ locale: lang }
|
||||
);
|
||||
onChangeLng(lang);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
@@ -40,14 +40,14 @@ const Account = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
const tabList = [
|
||||
{
|
||||
icon: 'support/user/userLight',
|
||||
label: t('common:user.Personal Information'),
|
||||
label: t('user:personal_information'),
|
||||
value: TabEnum.info
|
||||
},
|
||||
...(feConfigs?.isPlus
|
||||
? [
|
||||
{
|
||||
icon: 'support/usage/usageRecordLight',
|
||||
label: t('common:user.Usage Record'),
|
||||
label: t('user:usage_record'),
|
||||
value: TabEnum.usage
|
||||
}
|
||||
]
|
||||
@@ -57,7 +57,7 @@ const Account = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
? [
|
||||
{
|
||||
icon: 'support/bill/payRecordLight',
|
||||
label: t('common:support.wallet.Bills'),
|
||||
label: t('user:bill_and_invoices'),
|
||||
value: TabEnum.bill
|
||||
}
|
||||
]
|
||||
@@ -67,7 +67,7 @@ const Account = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
? [
|
||||
{
|
||||
icon: 'support/account/promotionLight',
|
||||
label: t('common:user.Promotion Record'),
|
||||
label: t('user:promotion_records'),
|
||||
value: TabEnum.promotion
|
||||
}
|
||||
]
|
||||
@@ -83,14 +83,14 @@ const Account = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
: []),
|
||||
{
|
||||
icon: 'support/user/individuation',
|
||||
label: t('common:support.account.Individuation'),
|
||||
label: t('user:personalization'),
|
||||
value: TabEnum.individuation
|
||||
},
|
||||
...(feConfigs.isPlus
|
||||
? [
|
||||
{
|
||||
icon: 'support/user/informLight',
|
||||
label: t('common:user.Notice'),
|
||||
label: t('user:notice'),
|
||||
value: TabEnum.inform
|
||||
}
|
||||
]
|
||||
@@ -98,7 +98,7 @@ const Account = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
|
||||
{
|
||||
icon: 'support/account/loginoutLight',
|
||||
label: t('common:user.Sign Out'),
|
||||
label: t('user:sign_out'),
|
||||
value: TabEnum.loginout
|
||||
}
|
||||
];
|
||||
|
@@ -125,9 +125,14 @@ const Header = () => {
|
||||
try {
|
||||
localStorage.removeItem(`${appDetail._id}-past`);
|
||||
localStorage.removeItem(`${appDetail._id}-future`);
|
||||
router.back();
|
||||
router.push({
|
||||
pathname: '/app/list',
|
||||
query: {
|
||||
parentId: appDetail.parentId
|
||||
}
|
||||
});
|
||||
} catch (error) {}
|
||||
}, [appDetail._id, router]);
|
||||
}, [appDetail._id, appDetail.parentId, router]);
|
||||
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
|
@@ -125,9 +125,14 @@ const Header = () => {
|
||||
try {
|
||||
localStorage.removeItem(`${appDetail._id}-past`);
|
||||
localStorage.removeItem(`${appDetail._id}-future`);
|
||||
router.back();
|
||||
router.push({
|
||||
pathname: '/app/list',
|
||||
query: {
|
||||
parentId: appDetail.parentId
|
||||
}
|
||||
});
|
||||
} catch (error) {}
|
||||
}, [appDetail._id, router]);
|
||||
}, [appDetail._id, appDetail.parentId, router]);
|
||||
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
|
@@ -272,7 +272,7 @@ function List() {
|
||||
{owner && (
|
||||
<HStack spacing={1}>
|
||||
<Avatar src={owner.avatar} w={'0.875rem'} borderRadius={'50%'} />
|
||||
<Box maxW={'150px'} className="textEllipsis">
|
||||
<Box maxW={'150px'} className="textEllipsis" fontSize={'mini'}>
|
||||
{owner.memberName}
|
||||
</Box>
|
||||
</HStack>
|
||||
@@ -288,7 +288,9 @@ function List() {
|
||||
{isPc && (
|
||||
<HStack spacing={1} className="time">
|
||||
<MyIcon name={'history'} w={'0.85rem'} color={'myGray.400'} />
|
||||
<Box color={'myGray.500'}>{formatTimeToChatTime(dataset.updateTime)}</Box>
|
||||
<Box color={'myGray.500'} fontSize={'mini'}>
|
||||
{formatTimeToChatTime(dataset.updateTime)}
|
||||
</Box>
|
||||
</HStack>
|
||||
)}
|
||||
{dataset.permission.hasWritePer && (
|
||||
|
@@ -43,12 +43,12 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
})
|
||||
);
|
||||
toast({
|
||||
title: t('user:login.success'),
|
||||
title: t('login:login_success'),
|
||||
status: 'success'
|
||||
});
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
title: error.message || t('user:login.error'),
|
||||
title: error.message || t('login:login_failed'),
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
@@ -61,7 +61,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
|
||||
const placeholder = (() => {
|
||||
if (isCommunityVersion) {
|
||||
return t('common:support.user.login.Root login');
|
||||
return t('login:use_root_login');
|
||||
}
|
||||
return [t('common:support.user.login.Username')]
|
||||
.concat(
|
||||
@@ -102,36 +102,36 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
type={'password'}
|
||||
placeholder={
|
||||
isCommunityVersion
|
||||
? t('common:support.user.login.Root password placeholder')
|
||||
? t('login:root_password_placeholder')
|
||||
: t('common:support.user.login.Password')
|
||||
}
|
||||
{...register('password', {
|
||||
required: true,
|
||||
maxLength: {
|
||||
value: 60,
|
||||
message: t('user:login.password_condition')
|
||||
message: t('login:password_condition')
|
||||
}
|
||||
})}
|
||||
></Input>
|
||||
</FormControl>
|
||||
{feConfigs?.docUrl && (
|
||||
<Flex alignItems={'center'} mt={7} fontSize={'sm'}>
|
||||
{t('common:support.user.login.Policy tip')}
|
||||
<Flex alignItems={'center'} mt={7} fontSize={'mini'}>
|
||||
{t('login:policy_tip')}
|
||||
<Link
|
||||
ml={1}
|
||||
href={getDocPath('/docs/agreement/terms/')}
|
||||
target={'_blank'}
|
||||
color={'primary.500'}
|
||||
>
|
||||
{t('common:support.user.login.Terms')}
|
||||
{t('login:terms')}
|
||||
</Link>
|
||||
<Box mx={1}>{t('common:support.user.login.And')}</Box>
|
||||
<Box mx={1}>&</Box>
|
||||
<Link
|
||||
href={getDocPath('/docs/agreement/privacy/')}
|
||||
target={'_blank'}
|
||||
color={'primary.500'}
|
||||
>
|
||||
{t('common:support.user.login.Privacy')}
|
||||
{t('login:privacy')}
|
||||
</Link>
|
||||
</Flex>
|
||||
)}
|
||||
@@ -145,7 +145,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
isLoading={requesting}
|
||||
onClick={handleSubmit(onclickLogin)}
|
||||
>
|
||||
{t('common:Login')}
|
||||
{t('login:Login')}
|
||||
</Button>
|
||||
|
||||
<Flex align={'center'} justifyContent={'flex-end'} color={'primary.700'}>
|
||||
@@ -156,7 +156,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
onClick={() => setPageType('forgetPassword')}
|
||||
fontSize="sm"
|
||||
>
|
||||
{t('common:support.user.login.Forget Password')}
|
||||
{t('login:forget_password')}
|
||||
</Box>
|
||||
)}
|
||||
{feConfigs?.register_method && feConfigs.register_method.length > 0 && (
|
||||
@@ -168,7 +168,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
onClick={() => setPageType('register')}
|
||||
fontSize="sm"
|
||||
>
|
||||
{t('common:support.user.login.Register')}
|
||||
{t('login:register')}
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
|
@@ -129,7 +129,7 @@ const Login = () => {
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
return {
|
||||
props: { ...(await serviceSideProps(context, ['app', 'user'])) }
|
||||
props: { ...(await serviceSideProps(context, ['app', 'user', 'login'])) }
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { I18nNsType } from '@fastgpt/web/types/i18next';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
|
||||
export const LANG_KEY = 'NEXT_LOCALE_LANG';
|
||||
export enum LangEnum {
|
||||
'zh' = 'zh',
|
||||
'en' = 'en'
|
||||
@@ -20,24 +19,3 @@ export const langMap = {
|
||||
export const serviceSideProps = (content: any, ns: I18nNsType = []) => {
|
||||
return serverSideTranslations(content.locale, ['common', 'error', ...ns], null, content.locales);
|
||||
};
|
||||
|
||||
export const getLng = (lng: string) => {
|
||||
return lng.split('-')[0];
|
||||
};
|
||||
export const change2DefaultLng = (currentLng: string) => {
|
||||
if (!navigator || !localStorage) return;
|
||||
if (localStorage.getItem(LANG_KEY)) return;
|
||||
const userLang = navigator.language;
|
||||
|
||||
if (userLang.includes(currentLng)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// currentLng not in userLang
|
||||
return getLng(userLang);
|
||||
};
|
||||
|
||||
export const setLngStore = (lng: string) => {
|
||||
if (!localStorage) return;
|
||||
localStorage.setItem(LANG_KEY, lng);
|
||||
};
|
||||
|
@@ -1,17 +1,14 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { clientInitData } from '@/web/common/system/staticData';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d';
|
||||
import { change2DefaultLng, LangEnum, setLngStore } from '@/web/common/utils/i18n';
|
||||
import { useMemoizedFn, useMount } from 'ahooks';
|
||||
import { TrackEventName } from '../common/system/constants';
|
||||
|
||||
export const useInitApp = () => {
|
||||
const router = useRouter();
|
||||
const { hiId } = router.query as { hiId?: string };
|
||||
const { i18n } = useTranslation();
|
||||
const { loadGitStar, setInitd, feConfigs } = useSystemStore();
|
||||
const [scripts, setScripts] = useState<FastGPTFeConfigsType['scripts']>([]);
|
||||
const [title, setTitle] = useState(process.env.SYSTEM_NAME || 'AI');
|
||||
@@ -38,20 +35,8 @@ export const useInitApp = () => {
|
||||
setInitd();
|
||||
});
|
||||
|
||||
const initUserLanguage = useMemoizedFn(() => {
|
||||
// get default language
|
||||
|
||||
const targetLng =
|
||||
change2DefaultLng(i18n.language) ||
|
||||
(['zh', 'zh-CN'].includes(navigator.language) ? 'zh' : 'en');
|
||||
|
||||
setLngStore(targetLng);
|
||||
router.replace(router.asPath, undefined, { locale: targetLng });
|
||||
});
|
||||
|
||||
useMount(() => {
|
||||
initFetch();
|
||||
initUserLanguage();
|
||||
|
||||
const errorTrack = (event: ErrorEvent) => {
|
||||
window.umami?.track(TrackEventName.windowError, {
|
||||
|
Reference in New Issue
Block a user