mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
Feat: Place the language configuration in web/.env for easy user configuration. (#13920)
### What problem does this PR solve? Feat: Place the language configuration in web/.env for easy user configuration. ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
3
web/.env
3
web/.env
@@ -1,2 +1,3 @@
|
||||
PORT=9222
|
||||
DID_YOU_KNOW=none
|
||||
DID_YOU_KNOW=none
|
||||
VITE_DEFAULT_LANGUAGE_CODE=en # en', 'zh-Hans', 'zh-Hant', 'ru', 'id', 'ja', 'es', 'vi', 'pt-BR', 'de', 'fr', 'it', 'bg', 'ar', 'tr'
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Toaster as Sonner } from '@/components/ui/sonner';
|
||||
import { Toaster } from '@/components/ui/toaster';
|
||||
import i18n, { changeLanguageAsync } from '@/locales/config';
|
||||
import { changeLanguageAsync } from '@/locales/config';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { configResponsive } from 'ahooks';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -64,25 +64,6 @@ const queryClient = new QueryClient({
|
||||
});
|
||||
|
||||
function Root({ children }: React.PropsWithChildren) {
|
||||
const updateDocumentLocale = (lng: string) => {
|
||||
document.documentElement.lang = lng;
|
||||
document.documentElement.dir = 'ltr';
|
||||
dayjs.locale(lng === 'zh' ? 'zh-cn' : lng);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleLanguageChanged = (lng: string) => {
|
||||
storage.setLanguage(lng);
|
||||
updateDocumentLocale(lng);
|
||||
};
|
||||
|
||||
updateDocumentLocale(storage.getLanguage() || i18n.language || 'en');
|
||||
i18n.on('languageChanged', handleLanguageChanged);
|
||||
|
||||
return () => {
|
||||
i18n.off('languageChanged', handleLanguageChanged);
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useTranslate } from './common-hooks';
|
||||
import { useSetPaginationParams } from './route-hook';
|
||||
@@ -51,15 +50,15 @@ export const useSetSelectedRecord = <T = IKnowledgeFile>() => {
|
||||
};
|
||||
|
||||
export const useChangeLanguage = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const { saveSetting } = useSaveSetting();
|
||||
|
||||
const changeLanguage = (lng: string) => {
|
||||
// const targetLng = LanguageTranslationMap[lng as keyof typeof LanguageTranslationMap];
|
||||
|
||||
changeLanguageAsync(lng);
|
||||
saveSetting({ language: lng });
|
||||
};
|
||||
const changeLanguage = useCallback(
|
||||
(lng: string) => {
|
||||
changeLanguageAsync(lng);
|
||||
saveSetting({ language: lng });
|
||||
},
|
||||
[saveSetting],
|
||||
);
|
||||
|
||||
return changeLanguage;
|
||||
};
|
||||
|
||||
@@ -4,9 +4,14 @@ import userService, {
|
||||
getLoginChannels,
|
||||
loginWithChannel,
|
||||
} from '@/services/user-service';
|
||||
import authorizationUtil, { redirectToLogin } from '@/utils/authorization-util';
|
||||
import {
|
||||
default as authorizationUtil,
|
||||
redirectToLogin,
|
||||
default as storage,
|
||||
} from '@/utils/authorization-util';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSaveSetting } from './use-user-setting-request';
|
||||
|
||||
export interface ILoginRequestBody {
|
||||
email: string;
|
||||
@@ -48,6 +53,7 @@ export const useLoginWithChannel = () => {
|
||||
};
|
||||
|
||||
export const useLogin = () => {
|
||||
const { saveSetting } = useSaveSetting(true);
|
||||
const {
|
||||
data,
|
||||
isPending: loading,
|
||||
@@ -57,6 +63,10 @@ export const useLogin = () => {
|
||||
mutationFn: async (params: { email: string; password: string }) => {
|
||||
const { data: res = {}, response } = await userService.login(params);
|
||||
if (res.code === 0) {
|
||||
// The language is based on the .lng stored in the client's local storage.
|
||||
// The language stored in the database is for agent template resources,
|
||||
// since the agent template resources are stored on the server.
|
||||
saveSetting({ language: storage.getLanguage() });
|
||||
const { data } = res;
|
||||
const authorization = response.headers.get(Authorization);
|
||||
const token = data.access_token;
|
||||
|
||||
@@ -11,11 +11,7 @@ import {
|
||||
IUserInfo,
|
||||
} from '@/interfaces/database/user-setting';
|
||||
import { ISetLangfuseConfigRequestBody } from '@/interfaces/request/system';
|
||||
import {
|
||||
changeLanguageAsync,
|
||||
DEFAULT_LANGUAGE_CODE,
|
||||
supportedLanguages,
|
||||
} from '@/locales/config';
|
||||
import { DEFAULT_LANGUAGE_CODE, supportedLanguages } from '@/locales/config';
|
||||
import { Routes } from '@/routes';
|
||||
import userService, {
|
||||
addTenantUser,
|
||||
@@ -62,10 +58,6 @@ export const useFetchUserInfo = (): ResponseGetType<IUserInfo> => {
|
||||
supportedLanguages.find((lang) => lang.code === data.data.language)
|
||||
?.code ?? DEFAULT_LANGUAGE_CODE;
|
||||
|
||||
if (targetLng) {
|
||||
await changeLanguageAsync(targetLng);
|
||||
}
|
||||
|
||||
return Object.assign({}, data.data, {
|
||||
language: targetLng,
|
||||
});
|
||||
@@ -132,7 +124,7 @@ export const useSelectParserList = (): Array<{
|
||||
label: string;
|
||||
}> => {
|
||||
const { data: tenantInfo } = useFetchTenantInfo(true);
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const defaultParsers = useMemo(
|
||||
() => [
|
||||
@@ -163,7 +155,7 @@ export const useSelectParserList = (): Array<{
|
||||
{ value: 'email', label: t('knowledgeConfiguration.parserLabel.email') },
|
||||
{ value: 'tag', label: t('knowledgeConfiguration.parserLabel.tag') },
|
||||
],
|
||||
[i18n.language, t],
|
||||
[t],
|
||||
);
|
||||
|
||||
const parserList = useMemo(() => {
|
||||
@@ -183,7 +175,7 @@ export const useSelectParserList = (): Array<{
|
||||
return parserList;
|
||||
};
|
||||
|
||||
export const useSaveSetting = () => {
|
||||
export const useSaveSetting = (silent = false) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
@@ -197,7 +189,9 @@ export const useSaveSetting = () => {
|
||||
) => {
|
||||
const { data } = await userService.setting(userInfo);
|
||||
if (data.code === 0) {
|
||||
message.success(t('message.modified'));
|
||||
if (!silent) {
|
||||
message.success(t('message.modified'));
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['userInfo'] });
|
||||
}
|
||||
return data?.code;
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { LanguageAbbreviation } from '@/constants/common';
|
||||
import storage from '@/utils/authorization-util';
|
||||
import dayjs from 'dayjs';
|
||||
import i18n from 'i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { upperFirst } from 'lodash';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import { LanguageAbbreviation } from '@/constants/common';
|
||||
|
||||
import translation_en from './en';
|
||||
|
||||
//The language is based on the .ng file stored in the client's local storage.
|
||||
// The language stored in the database is for agent template resources, as these resources reside on the server.
|
||||
// When a user logs in from a different machine, the login page language is the language configured by VITE_DEFAULT_LANGUAGE_CODE.
|
||||
|
||||
const languageImports: Record<string, () => Promise<{ default: any }>> = {
|
||||
[LanguageAbbreviation.En]: () => import('./en'),
|
||||
[LanguageAbbreviation.Zh]: () => import('./zh'),
|
||||
@@ -40,18 +44,27 @@ export const supportedLanguages = supportedLanguageCodes.map((code) => {
|
||||
};
|
||||
});
|
||||
|
||||
export const DEFAULT_LANGUAGE_CODE = LanguageAbbreviation.En;
|
||||
export const DEFAULT_LANGUAGE_CODE =
|
||||
import.meta.env.VITE_DEFAULT_LANGUAGE_CODE || LanguageAbbreviation.En;
|
||||
|
||||
const resources = {
|
||||
[LanguageAbbreviation.En]: translation_en,
|
||||
};
|
||||
|
||||
const updateDocumentLocale = (lng: string) => {
|
||||
document.documentElement.lang = lng;
|
||||
document.documentElement.dir = 'ltr';
|
||||
dayjs.locale(lng === 'zh' ? 'zh-cn' : lng);
|
||||
};
|
||||
|
||||
i18n
|
||||
.use(initReactI18next)
|
||||
.use(LanguageDetector)
|
||||
.init({
|
||||
detection: {
|
||||
lookupLocalStorage: 'lng',
|
||||
order: ['localStorage'],
|
||||
caches: [],
|
||||
},
|
||||
supportedLngs: supportedLanguageCodes,
|
||||
resources,
|
||||
@@ -62,7 +75,6 @@ i18n
|
||||
});
|
||||
|
||||
export const loadLanguageAsync = async (lng: string): Promise<void> => {
|
||||
// const normalizedLng = normalizeLanguageCode(lng);
|
||||
const normalizedLng = lng;
|
||||
|
||||
if (i18n.hasResourceBundle(normalizedLng, 'translation')) {
|
||||
@@ -85,7 +97,6 @@ export const loadLanguageAsync = async (lng: string): Promise<void> => {
|
||||
};
|
||||
|
||||
export const changeLanguageAsync = async (lng: string): Promise<void> => {
|
||||
// const normalizedLng = normalizeLanguageCode(lng);
|
||||
const normalizedLng = lng;
|
||||
|
||||
if (
|
||||
@@ -94,16 +105,16 @@ export const changeLanguageAsync = async (lng: string): Promise<void> => {
|
||||
) {
|
||||
await loadLanguageAsync(normalizedLng);
|
||||
}
|
||||
|
||||
storage.setLanguage(lng);
|
||||
|
||||
updateDocumentLocale(lng);
|
||||
|
||||
await i18n.changeLanguage(normalizedLng);
|
||||
};
|
||||
|
||||
export const initLanguage = async (): Promise<void> => {
|
||||
// const currentLng = normalizeLanguageCode(
|
||||
// i18n.language || localStorage.getItem('lng') || LanguageAbbreviation.En,
|
||||
// );
|
||||
|
||||
const currentLng =
|
||||
i18n.language || localStorage.getItem('lng') || DEFAULT_LANGUAGE_CODE;
|
||||
const currentLng = storage.getLanguage() || DEFAULT_LANGUAGE_CODE;
|
||||
|
||||
await changeLanguageAsync(currentLng);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user