mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-25 18:03:29 +08:00
### What problem does this PR solve? - Add `web/src/locales/ko.ts` with full Korean translation (~3100 keys) - Register `Ko = 'ko'` in `LanguageAbbreviation` enum (`common.ts`) - Add `[LanguageAbbreviation.Ko]: '한국어'` to `LanguageAbbreviationMap` - Add lazy-load entry in `web/src/locales/config.ts` - Add `korean` key to all existing locale files (`ja`, `id`, `es`, `pt-br`, `vi`, `zh-traditional`) - Fix duplicate enum value `FileMimeType.Mdx` (`'text/markdown'` → `'text/mdx'`) ### Type of change - [x] New Feature (non-breaking change which adds functionality) - [x] Other (please describe): Korean (한국어) i18n translation + fix duplicate FileMimeType.Mdx enum value
124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
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 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'),
|
|
[LanguageAbbreviation.ZhTraditional]: () => import('./zh-traditional'),
|
|
[LanguageAbbreviation.Id]: () => import('./id'),
|
|
[LanguageAbbreviation.Ja]: () => import('./ja'),
|
|
[LanguageAbbreviation.Es]: () => import('./es'),
|
|
[LanguageAbbreviation.Vi]: () => import('./vi'),
|
|
[LanguageAbbreviation.Ru]: () => import('./ru'),
|
|
[LanguageAbbreviation.PtBr]: () => import('./pt-br'),
|
|
[LanguageAbbreviation.De]: () => import('./de'),
|
|
[LanguageAbbreviation.Fr]: () => import('./fr'),
|
|
[LanguageAbbreviation.It]: () => import('./it'),
|
|
[LanguageAbbreviation.Bg]: () => import('./bg'),
|
|
[LanguageAbbreviation.Ar]: () => import('./ar'),
|
|
[LanguageAbbreviation.Tr]: () => import('./tr'),
|
|
[LanguageAbbreviation.Ko]: () => import('./ko'),
|
|
};
|
|
|
|
const supportedLanguageCodes: Intl.UnicodeBCP47LocaleIdentifier[] =
|
|
Object.keys(languageImports);
|
|
|
|
export const supportedLanguages = supportedLanguageCodes.map((code) => {
|
|
const locale = new Intl.Locale(code);
|
|
|
|
return {
|
|
code,
|
|
locale,
|
|
displayName: upperFirst(
|
|
new Intl.DisplayNames(locale, { type: 'language' }).of(code)!,
|
|
),
|
|
};
|
|
});
|
|
|
|
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,
|
|
fallbackLng: DEFAULT_LANGUAGE_CODE,
|
|
interpolation: {
|
|
escapeValue: false,
|
|
},
|
|
});
|
|
|
|
export const loadLanguageAsync = async (lng: string): Promise<void> => {
|
|
const normalizedLng = lng;
|
|
|
|
if (i18n.hasResourceBundle(normalizedLng, 'translation')) {
|
|
return;
|
|
}
|
|
|
|
const importFn = languageImports[normalizedLng];
|
|
if (!importFn) {
|
|
console.warn(`Language ${lng} is not supported for lazy loading`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const module = await importFn();
|
|
const translationData = module.default?.translation || module.default;
|
|
i18n.addResourceBundle(normalizedLng, 'translation', translationData);
|
|
} catch (error) {
|
|
console.error(`Failed to load language ${lng}:`, error);
|
|
}
|
|
};
|
|
|
|
export const changeLanguageAsync = async (lng: string): Promise<void> => {
|
|
const normalizedLng = lng;
|
|
|
|
if (
|
|
normalizedLng !== LanguageAbbreviation.En &&
|
|
!i18n.hasResourceBundle(normalizedLng, 'translation')
|
|
) {
|
|
await loadLanguageAsync(normalizedLng);
|
|
}
|
|
|
|
storage.setLanguage(lng);
|
|
|
|
updateDocumentLocale(lng);
|
|
|
|
await i18n.changeLanguage(normalizedLng);
|
|
};
|
|
|
|
export const initLanguage = async (): Promise<void> => {
|
|
const currentLng = storage.getLanguage() || DEFAULT_LANGUAGE_CODE;
|
|
|
|
await changeLanguageAsync(currentLng);
|
|
};
|
|
|
|
export default i18n;
|