Merge pull request #1152 from danielaskdd/i18n-france-arabic
Add Arabic and French selection to app settings
This commit is contained in:
File diff suppressed because one or more lines are too long
2
lightrag/api/webui/index.html
generated
2
lightrag/api/webui/index.html
generated
@@ -8,7 +8,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="logo.png" />
|
<link rel="icon" type="image/svg+xml" href="logo.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Lightrag</title>
|
<title>Lightrag</title>
|
||||||
<script type="module" crossorigin src="/webui/assets/index-C-CHRwmZ.js"></script>
|
<script type="module" crossorigin src="/webui/assets/index-BItOVH8B.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/webui/assets/index-BViPRMGA.css">
|
<link rel="stylesheet" crossorigin href="/webui/assets/index-BViPRMGA.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@@ -38,11 +38,14 @@ from lightrag.utils import (
|
|||||||
)
|
)
|
||||||
from lightrag.api import __api_version__
|
from lightrag.api import __api_version__
|
||||||
|
|
||||||
|
|
||||||
# Custom exception for retry mechanism
|
# Custom exception for retry mechanism
|
||||||
class InvalidResponseError(Exception):
|
class InvalidResponseError(Exception):
|
||||||
"""Custom exception class for triggering retry mechanism"""
|
"""Custom exception class for triggering retry mechanism"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Core Anthropic completion function with retry
|
# Core Anthropic completion function with retry
|
||||||
@retry(
|
@retry(
|
||||||
stop=stop_after_attempt(3),
|
stop=stop_after_attempt(3),
|
||||||
@@ -96,10 +99,7 @@ async def anthropic_complete_if_cache(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
response = await anthropic_async_client.messages.create(
|
response = await anthropic_async_client.messages.create(
|
||||||
model=model,
|
model=model, messages=messages, stream=True, **kwargs
|
||||||
messages=messages,
|
|
||||||
stream=True,
|
|
||||||
**kwargs
|
|
||||||
)
|
)
|
||||||
except APIConnectionError as e:
|
except APIConnectionError as e:
|
||||||
logger.error(f"Anthropic API Connection Error: {e}")
|
logger.error(f"Anthropic API Connection Error: {e}")
|
||||||
@@ -119,7 +119,11 @@ async def anthropic_complete_if_cache(
|
|||||||
async def stream_response():
|
async def stream_response():
|
||||||
try:
|
try:
|
||||||
async for event in response:
|
async for event in response:
|
||||||
content = event.delta.text if hasattr(event, "delta") and event.delta.text else None
|
content = (
|
||||||
|
event.delta.text
|
||||||
|
if hasattr(event, "delta") and event.delta.text
|
||||||
|
else None
|
||||||
|
)
|
||||||
if content is None:
|
if content is None:
|
||||||
continue
|
continue
|
||||||
if r"\u" in content:
|
if r"\u" in content:
|
||||||
@@ -131,6 +135,7 @@ async def anthropic_complete_if_cache(
|
|||||||
|
|
||||||
return stream_response()
|
return stream_response()
|
||||||
|
|
||||||
|
|
||||||
# Generic Anthropic completion function
|
# Generic Anthropic completion function
|
||||||
async def anthropic_complete(
|
async def anthropic_complete(
|
||||||
prompt: str,
|
prompt: str,
|
||||||
@@ -149,6 +154,7 @@ async def anthropic_complete(
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Claude 3 Opus specific completion
|
# Claude 3 Opus specific completion
|
||||||
async def claude_3_opus_complete(
|
async def claude_3_opus_complete(
|
||||||
prompt: str,
|
prompt: str,
|
||||||
@@ -166,6 +172,7 @@ async def claude_3_opus_complete(
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Claude 3 Sonnet specific completion
|
# Claude 3 Sonnet specific completion
|
||||||
async def claude_3_sonnet_complete(
|
async def claude_3_sonnet_complete(
|
||||||
prompt: str,
|
prompt: str,
|
||||||
@@ -183,6 +190,7 @@ async def claude_3_sonnet_complete(
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Claude 3 Haiku specific completion
|
# Claude 3 Haiku specific completion
|
||||||
async def claude_3_haiku_complete(
|
async def claude_3_haiku_complete(
|
||||||
prompt: str,
|
prompt: str,
|
||||||
@@ -200,6 +208,7 @@ async def claude_3_haiku_complete(
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Embedding function (placeholder, as Anthropic does not provide embeddings)
|
# Embedding function (placeholder, as Anthropic does not provide embeddings)
|
||||||
@retry(
|
@retry(
|
||||||
stop=stop_after_attempt(3),
|
stop=stop_after_attempt(3),
|
||||||
@@ -230,7 +239,9 @@ async def anthropic_embed(
|
|||||||
api_key = os.environ.get("VOYAGE_API_KEY")
|
api_key = os.environ.get("VOYAGE_API_KEY")
|
||||||
if not api_key:
|
if not api_key:
|
||||||
logger.error("VOYAGE_API_KEY environment variable not set")
|
logger.error("VOYAGE_API_KEY environment variable not set")
|
||||||
raise ValueError("VOYAGE_API_KEY environment variable is required for embeddings")
|
raise ValueError(
|
||||||
|
"VOYAGE_API_KEY environment variable is required for embeddings"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Initialize Voyage AI client
|
# Initialize Voyage AI client
|
||||||
@@ -240,7 +251,7 @@ async def anthropic_embed(
|
|||||||
result = voyage_client.embed(
|
result = voyage_client.embed(
|
||||||
texts,
|
texts,
|
||||||
model=model,
|
model=model,
|
||||||
input_type="document" # Assuming document context; could be made configurable
|
input_type="document", # Assuming document context; could be made configurable
|
||||||
)
|
)
|
||||||
|
|
||||||
# Convert list of embeddings to numpy array
|
# Convert list of embeddings to numpy array
|
||||||
@@ -255,17 +266,46 @@ async def anthropic_embed(
|
|||||||
logger.error(f"Voyage AI embedding failed: {str(e)}")
|
logger.error(f"Voyage AI embedding failed: {str(e)}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
# Optional: a helper function to get available embedding models
|
# Optional: a helper function to get available embedding models
|
||||||
def get_available_embedding_models() -> dict[str, dict]:
|
def get_available_embedding_models() -> dict[str, dict]:
|
||||||
"""
|
"""
|
||||||
Returns a dictionary of available Voyage AI embedding models and their properties.
|
Returns a dictionary of available Voyage AI embedding models and their properties.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
"voyage-3-large": {"context_length": 32000, "dimension": 1024, "description": "Best general-purpose and multilingual"},
|
"voyage-3-large": {
|
||||||
"voyage-3": {"context_length": 32000, "dimension": 1024, "description": "General-purpose and multilingual"},
|
"context_length": 32000,
|
||||||
"voyage-3-lite": {"context_length": 32000, "dimension": 512, "description": "Optimized for latency and cost"},
|
"dimension": 1024,
|
||||||
"voyage-code-3": {"context_length": 32000, "dimension": 1024, "description": "Optimized for code"},
|
"description": "Best general-purpose and multilingual",
|
||||||
"voyage-finance-2": {"context_length": 32000, "dimension": 1024, "description": "Optimized for finance"},
|
},
|
||||||
"voyage-law-2": {"context_length": 16000, "dimension": 1024, "description": "Optimized for legal"},
|
"voyage-3": {
|
||||||
"voyage-multimodal-3": {"context_length": 32000, "dimension": 1024, "description": "Multimodal text and images"},
|
"context_length": 32000,
|
||||||
|
"dimension": 1024,
|
||||||
|
"description": "General-purpose and multilingual",
|
||||||
|
},
|
||||||
|
"voyage-3-lite": {
|
||||||
|
"context_length": 32000,
|
||||||
|
"dimension": 512,
|
||||||
|
"description": "Optimized for latency and cost",
|
||||||
|
},
|
||||||
|
"voyage-code-3": {
|
||||||
|
"context_length": 32000,
|
||||||
|
"dimension": 1024,
|
||||||
|
"description": "Optimized for code",
|
||||||
|
},
|
||||||
|
"voyage-finance-2": {
|
||||||
|
"context_length": 32000,
|
||||||
|
"dimension": 1024,
|
||||||
|
"description": "Optimized for finance",
|
||||||
|
},
|
||||||
|
"voyage-law-2": {
|
||||||
|
"context_length": 16000,
|
||||||
|
"dimension": 1024,
|
||||||
|
"description": "Optimized for legal",
|
||||||
|
},
|
||||||
|
"voyage-multimodal-3": {
|
||||||
|
"context_length": 32000,
|
||||||
|
"dimension": 1024,
|
||||||
|
"description": "Multimodal text and images",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ export default function AppSettings({ className }: AppSettingsProps) {
|
|||||||
const setTheme = useSettingsStore.use.setTheme()
|
const setTheme = useSettingsStore.use.setTheme()
|
||||||
|
|
||||||
const handleLanguageChange = useCallback((value: string) => {
|
const handleLanguageChange = useCallback((value: string) => {
|
||||||
setLanguage(value as 'en' | 'zh')
|
setLanguage(value as 'en' | 'zh' | 'fr' | 'ar')
|
||||||
}, [setLanguage])
|
}, [setLanguage])
|
||||||
|
|
||||||
const handleThemeChange = useCallback((value: string) => {
|
const handleThemeChange = useCallback((value: string) => {
|
||||||
@@ -47,6 +47,8 @@ export default function AppSettings({ className }: AppSettingsProps) {
|
|||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="en">English</SelectItem>
|
<SelectItem value="en">English</SelectItem>
|
||||||
<SelectItem value="zh">中文</SelectItem>
|
<SelectItem value="zh">中文</SelectItem>
|
||||||
|
<SelectItem value="fr">Français</SelectItem>
|
||||||
|
<SelectItem value="ar">العربية</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,35 +0,0 @@
|
|||||||
import i18n from "i18next";
|
|
||||||
import { initReactI18next } from "react-i18next";
|
|
||||||
import { useSettingsStore } from "./stores/settings";
|
|
||||||
|
|
||||||
import en from "./locales/en.json";
|
|
||||||
import zh from "./locales/zh.json";
|
|
||||||
|
|
||||||
const getStoredLanguage = () => {
|
|
||||||
try {
|
|
||||||
const settingsString = localStorage.getItem('settings-storage');
|
|
||||||
if (settingsString) {
|
|
||||||
const settings = JSON.parse(settingsString);
|
|
||||||
return settings.state?.language || 'en';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to get stored language:', e);
|
|
||||||
}
|
|
||||||
return 'en';
|
|
||||||
};
|
|
||||||
|
|
||||||
i18n
|
|
||||||
.use(initReactI18next)
|
|
||||||
.init({
|
|
||||||
resources: {
|
|
||||||
en: { translation: en },
|
|
||||||
zh: { translation: zh }
|
|
||||||
},
|
|
||||||
lng: getStoredLanguage(), // 使用存储的语言设置
|
|
||||||
fallbackLng: "en",
|
|
||||||
interpolation: {
|
|
||||||
escapeValue: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default i18n;
|
|
@@ -4,34 +4,44 @@ import { useSettingsStore } from '@/stores/settings'
|
|||||||
|
|
||||||
import en from './locales/en.json'
|
import en from './locales/en.json'
|
||||||
import zh from './locales/zh.json'
|
import zh from './locales/zh.json'
|
||||||
|
import fr from './locales/fr.json'
|
||||||
|
import ar from './locales/ar.json'
|
||||||
|
|
||||||
// Function to sync i18n with store state
|
const getStoredLanguage = () => {
|
||||||
export const initializeI18n = async (): Promise<typeof i18n> => {
|
try {
|
||||||
// Get initial language from store
|
const settingsString = localStorage.getItem('settings-storage')
|
||||||
const initialLanguage = useSettingsStore.getState().language
|
if (settingsString) {
|
||||||
|
const settings = JSON.parse(settingsString)
|
||||||
|
return settings.state?.language || 'en'
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to get stored language:', e)
|
||||||
|
}
|
||||||
|
return 'en'
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize with store language
|
i18n
|
||||||
await i18n.use(initReactI18next).init({
|
.use(initReactI18next)
|
||||||
|
.init({
|
||||||
resources: {
|
resources: {
|
||||||
en: { translation: en },
|
en: { translation: en },
|
||||||
zh: { translation: zh }
|
zh: { translation: zh },
|
||||||
|
fr: { translation: fr },
|
||||||
|
ar: { translation: ar }
|
||||||
},
|
},
|
||||||
lng: initialLanguage,
|
lng: getStoredLanguage(), // 使用存储的语言设置
|
||||||
fallbackLng: 'en',
|
fallbackLng: 'en',
|
||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false
|
escapeValue: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Subscribe to language changes
|
// Subscribe to language changes
|
||||||
useSettingsStore.subscribe((state) => {
|
useSettingsStore.subscribe((state) => {
|
||||||
const currentLanguage = state.language
|
const currentLanguage = state.language
|
||||||
if (i18n.language !== currentLanguage) {
|
if (i18n.language !== currentLanguage) {
|
||||||
i18n.changeLanguage(currentLanguage)
|
i18n.changeLanguage(currentLanguage)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return i18n
|
|
||||||
}
|
|
||||||
|
|
||||||
export default i18n
|
export default i18n
|
||||||
|
@@ -12,11 +12,26 @@
|
|||||||
"retrieval": "الاسترجاع",
|
"retrieval": "الاسترجاع",
|
||||||
"api": "واجهة برمجة التطبيقات",
|
"api": "واجهة برمجة التطبيقات",
|
||||||
"projectRepository": "مستودع المشروع",
|
"projectRepository": "مستودع المشروع",
|
||||||
|
"logout": "تسجيل الخروج",
|
||||||
"themeToggle": {
|
"themeToggle": {
|
||||||
"switchToLight": "التحويل إلى السمة الفاتحة",
|
"switchToLight": "التحويل إلى السمة الفاتحة",
|
||||||
"switchToDark": "التحويل إلى السمة الداكنة"
|
"switchToDark": "التحويل إلى السمة الداكنة"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"description": "الرجاء إدخال حسابك وكلمة المرور لتسجيل الدخول إلى النظام",
|
||||||
|
"username": "اسم المستخدم",
|
||||||
|
"usernamePlaceholder": "الرجاء إدخال اسم المستخدم",
|
||||||
|
"password": "كلمة المرور",
|
||||||
|
"passwordPlaceholder": "الرجاء إدخال كلمة المرور",
|
||||||
|
"loginButton": "تسجيل الدخول",
|
||||||
|
"loggingIn": "جاري تسجيل الدخول...",
|
||||||
|
"successMessage": "تم تسجيل الدخول بنجاح",
|
||||||
|
"errorEmptyFields": "الرجاء إدخال اسم المستخدم وكلمة المرور",
|
||||||
|
"errorInvalidCredentials": "فشل تسجيل الدخول، يرجى التحقق من اسم المستخدم وكلمة المرور",
|
||||||
|
"authDisabled": "تم تعطيل المصادقة. استخدام وضع بدون تسجيل دخول.",
|
||||||
|
"guestMode": "وضع بدون تسجيل دخول"
|
||||||
|
},
|
||||||
"documentPanel": {
|
"documentPanel": {
|
||||||
"clearDocuments": {
|
"clearDocuments": {
|
||||||
"button": "مسح",
|
"button": "مسح",
|
||||||
@@ -96,7 +111,9 @@
|
|||||||
"zoomControl": {
|
"zoomControl": {
|
||||||
"zoomIn": "تكبير",
|
"zoomIn": "تكبير",
|
||||||
"zoomOut": "تصغير",
|
"zoomOut": "تصغير",
|
||||||
"resetZoom": "إعادة تعيين التكبير"
|
"resetZoom": "إعادة تعيين التكبير",
|
||||||
|
"rotateCamera": "تدوير في اتجاه عقارب الساعة",
|
||||||
|
"rotateCameraCounterClockwise": "تدوير عكس اتجاه عقارب الساعة"
|
||||||
},
|
},
|
||||||
"layoutsControl": {
|
"layoutsControl": {
|
||||||
"startAnimation": "بدء حركة التخطيط",
|
"startAnimation": "بدء حركة التخطيط",
|
||||||
@@ -148,6 +165,11 @@
|
|||||||
"degree": "الدرجة",
|
"degree": "الدرجة",
|
||||||
"properties": "الخصائص",
|
"properties": "الخصائص",
|
||||||
"relationships": "العلاقات",
|
"relationships": "العلاقات",
|
||||||
|
"expandNode": "توسيع العقدة",
|
||||||
|
"pruneNode": "تقليم العقدة",
|
||||||
|
"deleteAllNodesError": "رفض حذف جميع العقد في الرسم البياني",
|
||||||
|
"nodesRemoved": "تم إزالة {{count}} عقدة، بما في ذلك العقد اليتيمة",
|
||||||
|
"noNewNodes": "لم يتم العثور على عقد قابلة للتوسيع",
|
||||||
"propertyNames": {
|
"propertyNames": {
|
||||||
"description": "الوصف",
|
"description": "الوصف",
|
||||||
"entity_id": "الاسم",
|
"entity_id": "الاسم",
|
||||||
@@ -174,8 +196,10 @@
|
|||||||
"noLabels": "لم يتم العثور على تسميات",
|
"noLabels": "لم يتم العثور على تسميات",
|
||||||
"label": "التسمية",
|
"label": "التسمية",
|
||||||
"placeholder": "ابحث في التسميات...",
|
"placeholder": "ابحث في التسميات...",
|
||||||
"andOthers": "و {{count}} آخرون"
|
"andOthers": "و {{count}} آخرون",
|
||||||
}
|
"refreshTooltip": "إعادة تحميل بيانات الرسم البياني"
|
||||||
|
},
|
||||||
|
"emptyGraph": "الرسم البياني فارغ"
|
||||||
},
|
},
|
||||||
"retrievePanel": {
|
"retrievePanel": {
|
||||||
"chatMessage": {
|
"chatMessage": {
|
||||||
|
@@ -12,11 +12,26 @@
|
|||||||
"retrieval": "Récupération",
|
"retrieval": "Récupération",
|
||||||
"api": "API",
|
"api": "API",
|
||||||
"projectRepository": "Référentiel du projet",
|
"projectRepository": "Référentiel du projet",
|
||||||
|
"logout": "Déconnexion",
|
||||||
"themeToggle": {
|
"themeToggle": {
|
||||||
"switchToLight": "Passer au thème clair",
|
"switchToLight": "Passer au thème clair",
|
||||||
"switchToDark": "Passer au thème sombre"
|
"switchToDark": "Passer au thème sombre"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"description": "Veuillez entrer votre compte et mot de passe pour vous connecter au système",
|
||||||
|
"username": "Nom d'utilisateur",
|
||||||
|
"usernamePlaceholder": "Veuillez saisir un nom d'utilisateur",
|
||||||
|
"password": "Mot de passe",
|
||||||
|
"passwordPlaceholder": "Veuillez saisir un mot de passe",
|
||||||
|
"loginButton": "Connexion",
|
||||||
|
"loggingIn": "Connexion en cours...",
|
||||||
|
"successMessage": "Connexion réussie",
|
||||||
|
"errorEmptyFields": "Veuillez saisir votre nom d'utilisateur et mot de passe",
|
||||||
|
"errorInvalidCredentials": "Échec de la connexion, veuillez vérifier le nom d'utilisateur et le mot de passe",
|
||||||
|
"authDisabled": "L'authentification est désactivée. Utilisation du mode sans connexion.",
|
||||||
|
"guestMode": "Mode sans connexion"
|
||||||
|
},
|
||||||
"documentPanel": {
|
"documentPanel": {
|
||||||
"clearDocuments": {
|
"clearDocuments": {
|
||||||
"button": "Effacer",
|
"button": "Effacer",
|
||||||
@@ -96,7 +111,9 @@
|
|||||||
"zoomControl": {
|
"zoomControl": {
|
||||||
"zoomIn": "Zoom avant",
|
"zoomIn": "Zoom avant",
|
||||||
"zoomOut": "Zoom arrière",
|
"zoomOut": "Zoom arrière",
|
||||||
"resetZoom": "Réinitialiser le zoom"
|
"resetZoom": "Réinitialiser le zoom",
|
||||||
|
"rotateCamera": "Rotation horaire",
|
||||||
|
"rotateCameraCounterClockwise": "Rotation antihoraire"
|
||||||
},
|
},
|
||||||
"layoutsControl": {
|
"layoutsControl": {
|
||||||
"startAnimation": "Démarrer l'animation de mise en page",
|
"startAnimation": "Démarrer l'animation de mise en page",
|
||||||
@@ -148,6 +165,11 @@
|
|||||||
"degree": "Degré",
|
"degree": "Degré",
|
||||||
"properties": "Propriétés",
|
"properties": "Propriétés",
|
||||||
"relationships": "Relations",
|
"relationships": "Relations",
|
||||||
|
"expandNode": "Développer le nœud",
|
||||||
|
"pruneNode": "Élaguer le nœud",
|
||||||
|
"deleteAllNodesError": "Refus de supprimer tous les nœuds du graphe",
|
||||||
|
"nodesRemoved": "{{count}} nœuds supprimés, y compris les nœuds orphelins",
|
||||||
|
"noNewNodes": "Aucun nœud développable trouvé",
|
||||||
"propertyNames": {
|
"propertyNames": {
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"entity_id": "Nom",
|
"entity_id": "Nom",
|
||||||
@@ -174,8 +196,10 @@
|
|||||||
"noLabels": "Aucune étiquette trouvée",
|
"noLabels": "Aucune étiquette trouvée",
|
||||||
"label": "Étiquette",
|
"label": "Étiquette",
|
||||||
"placeholder": "Rechercher des étiquettes...",
|
"placeholder": "Rechercher des étiquettes...",
|
||||||
"andOthers": "Et {{count}} autres"
|
"andOthers": "Et {{count}} autres",
|
||||||
}
|
"refreshTooltip": "Recharger les données du graphe"
|
||||||
|
},
|
||||||
|
"emptyGraph": "Le graphe est vide"
|
||||||
},
|
},
|
||||||
"retrievePanel": {
|
"retrievePanel": {
|
||||||
"chatMessage": {
|
"chatMessage": {
|
||||||
|
@@ -2,7 +2,7 @@ import { StrictMode } from 'react'
|
|||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import AppRouter from './AppRouter'
|
import AppRouter from './AppRouter'
|
||||||
import './i18n';
|
import './i18n.ts';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ import { defaultQueryLabel } from '@/lib/constants'
|
|||||||
import { Message, QueryRequest } from '@/api/lightrag'
|
import { Message, QueryRequest } from '@/api/lightrag'
|
||||||
|
|
||||||
type Theme = 'dark' | 'light' | 'system'
|
type Theme = 'dark' | 'light' | 'system'
|
||||||
type Language = 'en' | 'zh'
|
type Language = 'en' | 'zh' | 'fr' | 'ar'
|
||||||
type Tab = 'documents' | 'knowledge-graph' | 'retrieval' | 'api'
|
type Tab = 'documents' | 'knowledge-graph' | 'retrieval' | 'api'
|
||||||
|
|
||||||
interface SettingsState {
|
interface SettingsState {
|
||||||
|
Reference in New Issue
Block a user