korean update

This commit is contained in:
ParkMinsu
2025-09-29 10:24:05 +08:00
committed by fit2cloud-chenyw
parent 0bf4c82859
commit c2531c33f0
13 changed files with 260 additions and 30 deletions
+8 -3
View File
@@ -418,7 +418,7 @@ class LLMService:
full_thinking_text = ''
full_text = ''
if not ignore_auto_select:
if settings.TABLE_EMBEDDING_ENABLED:
if settings.EMBEDDING_ENABLED:
ds = get_ds_embedding(self.session, self.current_user, _ds_list, self.out_ds_instance,
self.chat_question.question, self.current_assistant)
yield {'content': '{"id":' + str(ds.get('id')) + '}'}
@@ -508,7 +508,7 @@ class LLMService:
except Exception as e:
_error = e
if not ignore_auto_select and not settings.TABLE_EMBEDDING_ENABLED:
if not ignore_auto_select and not settings.EMBEDDING_ENABLED:
self.record = save_select_datasource_answer(session=self.session, record_id=self.record.id,
answer=orjson.dumps({'content': full_text}).decode(),
datasource=_datasource,
@@ -1443,6 +1443,11 @@ def process_stream(res: Iterator[BaseMessageChunk],
def get_lang_name(lang: str):
if lang and lang == 'en':
if not lang:
return '简体中文'
normalized = lang.lower()
if normalized.startswith('en'):
return '英文'
if normalized.startswith('ko'):
return '韩语'
return '简体中文'
+1 -2
View File
@@ -13,7 +13,6 @@ from apps.datasource.utils.utils import aes_decrypt
from apps.db.constant import DB
from apps.db.db import get_tables, get_fields, exec_sql, check_connection
from apps.db.engine import get_engine_config, get_engine_conn
from common.core.config import settings
from common.core.deps import SessionDep, CurrentUser, Trans
from common.utils.utils import deepcopy_ignore_extra
from .table import get_tables_by_ds_id
@@ -403,7 +402,7 @@ def get_table_schema(session: SessionDep, current_user: CurrentUser, ds: CoreDat
all_tables.append(t_obj)
# do table embedding
if embedding and tables and settings.TABLE_EMBEDDING_ENABLED:
if embedding and tables:
tables = get_table_embedding(session, current_user, tables, question)
# splice schema
if tables:
+1 -1
View File
@@ -193,7 +193,7 @@ async def batch_del(session: SessionDep, id_list: list[int]):
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
async def langChange(session: SessionDep, current_user: CurrentUser, trans: Trans, language: UserLanguage):
lang = language.language
if lang not in ["zh-CN", "en"]:
if lang not in ["zh-CN", "en", "ko-KR"]:
raise Exception(trans('i18n_user.language_not_support', key = lang))
db_user: UserModel = get_db_user(session=session, user_id=current_user.id)
db_user.language = lang
+3 -3
View File
@@ -31,7 +31,7 @@ class BaseUser(BaseModel):
class BaseUserDTO(BaseUser, BaseCreatorDTO):
language: str = Field(pattern=r"^(zh-CN|en)$", default="zh-CN", description="用户语言")
language: str = Field(pattern=r"^(zh-CN|en|ko-KR)$", default="zh-CN", description="用户语言")
password: str
status: int = 1
@@ -44,8 +44,8 @@ class BaseUserDTO(BaseUser, BaseCreatorDTO):
@field_validator("language")
def validate_language(cls, lang: str) -> str:
if not re.fullmatch(r"^(zh-CN|en)$", lang):
raise ValueError("Language must be 'zh-CN' or 'en'")
if not re.fullmatch(r"^(zh-CN|en|ko-KR)$", lang):
raise ValueError("Language must be 'zh-CN', 'en', or 'ko-KR'")
return lang
-1
View File
@@ -105,7 +105,6 @@ class Settings(BaseSettings):
PG_POOL_RECYCLE: int = 3600
PG_POOL_PRE_PING: bool = True
TABLE_EMBEDDING_ENABLED: bool = False
TABLE_EMBEDDING_COUNT: int = 10
+54
View File
@@ -0,0 +1,54 @@
{
"i18n_default_workspace": "기본 워크스페이스",
"i18n_ds_name_exist": "이미 존재하는 이름입니다",
"i18n_concat_admin": "관리자에게 문의해 주세요!",
"i18n_exist": "{msg}이(가) 이미 존재합니다!",
"i18n_name": "이름",
"i18n_not_exist": "{msg}을(를) 찾을 수 없습니다",
"i18n_error": "{key} 오류!",
"i18n_miss_args": "{key} 매개변수가 없습니다!",
"i18n_format_invalid": "{key} 형식이 올바르지 않습니다!",
"i18n_login": {
"account_pwd_error": "계정 또는 비밀번호가 올바르지 않습니다!",
"no_associated_ws": "연결된 워크스페이스가 없습니다. {msg}",
"user_disable": "계정이 비활성화되었습니다. {msg}"
},
"i18n_user": {
"account": "계정",
"email": "이메일",
"password": "비밀번호",
"language_not_support": "[{key}] 언어는 지원하지 않습니다!",
"ws_miss": "현재 사용자는 워크스페이스 [{ws}]에 속해 있지 않습니다!"
},
"i18n_ws": {
"title": "워크스페이스"
},
"i18n_permission": {
"only_admin": "관리자만 호출할 수 있습니다!",
"no_permission": "{url}{msg}에 접근 권한이 없습니다",
"authenticate_invalid": "인증이 실패했습니다 [{msg}]",
"token_expired": "토큰이 만료되었습니다"
},
"i18n_llm": {
"validate_error": "검증에 실패했습니다 [{msg}]",
"delete_default_error": "기본 모델 [{key}]은 삭제할 수 없습니다!",
"miss_default": "기본 LLM이 아직 설정되지 않았습니다"
},
"i18n_ds_invalid": "데이터 소스가 유효하지 않습니다",
"i18n_embedded": {
"invalid_origin": "도메인 검증에 실패했습니다 [{origin}]"
},
"i18n_terminology": {
"terminology_not_exists": "용어를 찾을 수 없습니다",
"cannot_be_repeated": "용어 이름과 동의어는 중복될 수 없습니다",
"exists_in_db": "용어 이름 또는 동의어가 이미 존재합니다"
},
"i18n_data_training": {
"datasource_cannot_be_none": "데이터 소스를 선택해 주세요",
"data_training_not_exists": "예제가 존재하지 않습니다",
"exists_in_db": "질문이 이미 존재합니다"
},
"i18n_excel_export": {
"data_is_empty": "양식 데이터가 없어 내보낼 수 없습니다"
}
}
@@ -1,21 +1,20 @@
<template>
<el-dropdown trigger="hover" @command="changeLanguage">
<div class="lang-switch">
<span>{{ selectedLanguage === 'zh-CN' ? '中文' : 'English' }}</span>
<span>{{ displayLanguageName }}</span>
<el-icon class="el-icon--right">
<ArrowDown />
</el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="en" :class="{ 'selected-lang': selectedLanguage === 'en' }">
English
</el-dropdown-item>
<el-dropdown-item
command="zh-CN"
:class="{ 'selected-lang': selectedLanguage === 'zh-CN' }"
v-for="option in languageOptions"
:key="option.value"
:command="option.value"
:class="{ 'selected-lang': selectedLanguage === option.value }"
>
中文
{{ option.label }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -29,13 +28,24 @@ import { useUserStore } from '@/stores/user'
import { ArrowDown } from '@element-plus/icons-vue'
import { userApi } from '@/api/auth'
const { locale } = useI18n()
const { t, locale } = useI18n()
const userStore = useUserStore()
const languageOptions = computed(() => [
{ value: 'en', label: t('common.english') },
{ value: 'zh-CN', label: t('common.simplified_chinese') },
{ value: 'ko-KR', label: t('common.korean') },
])
const selectedLanguage = computed(() => {
return userStore.language
})
const displayLanguageName = computed(() => {
const current = languageOptions.value.find((item) => item.value === selectedLanguage.value)
return current?.label ?? t('common.language')
})
const changeLanguage = (lang: string) => {
locale.value = lang
userStore.setLanguage(lang)
@@ -63,4 +73,4 @@ const changeLanguage = (lang: string) => {
.selected-lang {
color: var(--el-color-primary);
}
</style>
</style>
+8 -7
View File
@@ -33,21 +33,22 @@ const currentLanguage = computed(() => userStore.getLanguage)
const isAdmin = computed(() => userStore.isAdmin)
const dialogVisible = ref(false)
const aboutRef = ref()
const languageList = [
const languageList = computed(() => [
{
name: 'English',
name: t('common.english'),
value: 'en',
},
{
name: t('common.simplified_chinese'),
value: 'zh-CN',
} /* ,
},
{
name: t('common.traditional_chinese'),
value: 'zh-CN',
}, */,
]
name: t('common.korean'),
value: 'ko-KR',
},
])
const popoverRef = ref()
const toSystem = () => {
popoverRef.value.hide()
router.push('/system')
+3 -1
View File
@@ -98,9 +98,11 @@
"clear_filter": "Clear conditions",
"reset": "Reset",
"simplified_chinese": "Simplified Chinese",
"korean": "Korean",
"traditional_chinese": "Traditional Chinese",
"help": "Help",
"language": "Language",
"english": "English",
"re_upload": "Re-upload",
"not_exceed_50mb": "Supports XLS, XLSX, CSV formats, file size does not exceed 50MB",
"reset_password": "Reset password",
@@ -690,4 +692,4 @@
"setting_successfully": "Setting Successfully",
"customize_theme_color": "Customize theme color"
}
}
}
+16 -2
View File
@@ -1,9 +1,12 @@
import { createI18n } from 'vue-i18n'
import en from './en.json'
import zhCN from './zh-CN.json'
import koKR from './ko-KR.json'
import elementEnLocale from 'element-plus-secondary/es/locale/lang/en'
import elementZhLocale from 'element-plus-secondary/es/locale/lang/zh-cn'
import { useCache } from '@/utils/useCache'
const elementKoLocale = elementEnLocale
const { wsCache } = useCache()
const getDefaultLocale = () => {
@@ -20,6 +23,10 @@ const messages = {
...zhCN,
el: elementZhLocale,
},
'ko-KR': {
...koKR,
el: elementKoLocale,
},
}
export const i18n = createI18n({
@@ -30,6 +37,13 @@ export const i18n = createI18n({
messages,
})
const elementLocales = {
en: elementEnLocale,
'zh-CN': elementZhLocale,
'ko-KR': elementKoLocale,
} as const
export const getElementLocale = () => {
return i18n.global.locale.value === 'en' ? elementEnLocale : elementZhLocale
}
const locale = i18n.global.locale.value as keyof typeof elementLocales
return elementLocales[locale] ?? elementEnLocale
}
+140
View File
@@ -0,0 +1,140 @@
{
"menu": {
"add_interface_credentials": "인터페이스 자격 증명을 추가해 주세요",
"Data Q&A": "데이터 Q&A",
"Data Connections": "데이터 연결",
"Dashboard": "대시보드",
"AI Model Configuration": "AI 모델 설정"
},
"common": {
"language": "언어",
"english": "영어",
"simplified_chinese": "중국어(간체)",
"korean": "한국어",
"help": "도움말",
"logout": "로그아웃",
"confirm": "확인",
"cancel": "취소",
"search": "검색",
"save": "저장",
"save_success": "저장 완료",
"update_success": "업데이트 완료",
"refresh": "새로고침",
"back": "뒤로",
"next": "다음",
"login": "로그인",
"login_": "로그인",
"please_input": "{msg}을(를) 입력해 주세요",
"input_content": "내용을 입력해 주세요",
"system_manage": "시스템 관리",
"help_document": "도움말 문서",
"re_upload": "다시 업로드",
"not_exceed_50mb": "XLS, XLSX, CSV 포맷 지원, 50MB 이하",
"reset_password": "비밀번호 재설정",
"password_reset_successful": "비밀번호가 재설정되었습니다"
},
"login": {
"title": "SQLBot에 다시 오신 것을 환영합니다",
"account": "계정 혹은 이메일",
"password": "비밀번호",
"login": "로그인",
"forget_password": "비밀번호를 잊으셨나요?",
"login_tips": "계정과 비밀번호는 대·소문자를 구분합니다"
},
"chat": {
"new_conversation": "새 대화",
"send": "전송",
"stop_replying": "응답 중지",
"show_sql": "SQL 보기",
"add_to_dashboard": "대시보드에 추가",
"export_to": "내보내기",
"excel": "엑셀",
"picture": "이미지",
"chart_type": {
"table": "상세 테이블",
"bar": "막대",
"column": "세로 막대",
"line": "라인",
"pie": "원형"
},
"type": "차트 종류",
"data_analysis": "데이터 분석",
"data_predict": "데이터 예측",
"thinking": "생각 중",
"show_error_detail": "오류 정보 보기",
"no_data": "데이터가 없습니다"
},
"dashboard": {
"open_dashboard": "대시보드 열기",
"add_view": "차트 추가",
"rename_dashboard": "대시보드 이름 변경",
"delete_dashboard_warn": "대시보드 {0}을(를) 삭제하시겠습니까?",
"no_dashboard": "등록된 대시보드가 없습니다",
"no_data": "관련 내용이 없습니다"
},
"datasource": {
"data_source": "데이터 소스",
"create_datasource": "데이터 소스 생성",
"edit_datasource": "데이터 소스 수정",
"test_connection": "연결 테스트",
"connect_success": "연결 성공",
"connect_failed": "연결 실패",
"host": "호스트",
"port": "포트",
"username": "사용자명",
"password": "비밀번호",
"database": "데이터베이스",
"schema": "스키마",
"description": "설명"
},
"user": {
"change_password": "비밀번호 변경",
"user_management": "사용자 관리",
"workspace": "워크스페이스",
"role": "역할",
"status": "상태",
"create_user": "사용자 생성",
"edit_user": "사용자 수정"
},
"workspace": {
"set": "워크스페이스 설정",
"member_management": "멤버 관리",
"permission_configuration": "권한 설정"
},
"system": {
"system_settings": "시스템 설정",
"appearance_settings": "테마 설정",
"platform_display_theme": "플랫폼 테마",
"default_turquoise": "기본(터키석)",
"tech_blue": "테크 블루",
"custom": "사용자 정의",
"platform_login_settings": "로그인 화면 설정",
"save_and_apply": "저장 후 적용",
"setting_successfully": "설정이 적용되었습니다"
},
"assistant": {
"embedded_management": "임베디드 관리",
"assistant_management": "어시스턴트 관리"
},
"professional": {
"professional_terminology": "전문 용어 설정",
"term_name": "용어명",
"term_description": "설명",
"create_new_term": "새 용어 만들기",
"search_term": "용어 검색"
},
"training": {
"data_training": "데이터 학습",
"add_training_data": "샘플 추가",
"training_data_details": "샘플 상세",
"sample_sql": "샘플 SQL"
},
"about": {
"title": "정보",
"auth_to": "라이선스 대상",
"version": "버전",
"support": "지원",
"update_license": "라이선스 업데이트",
"update_success": "업데이트 성공"
}
}
+2
View File
@@ -98,9 +98,11 @@
"clear_filter": "清空条件",
"reset": "重置",
"simplified_chinese": "简体中文",
"korean": "韩语",
"traditional_chinese": "繁體中文",
"help": "帮助",
"language": "语言",
"english": "英语",
"re_upload": "重新上传",
"not_exceed_50mb": "支持 XLS、XLSX、CSV 格式,文件大小不超过 50MB",
"reset_password": "重置密码",
+5 -1
View File
@@ -127,8 +127,12 @@ export const UserStore = defineStore('user', {
this.oid = oid
},
setLanguage(language: string) {
if (!language || language === 'zh_CN') {
if (!language) {
language = 'zh-CN'
} else if (language === 'zh_CN') {
language = 'zh-CN'
} else if (language === 'ko_KR') {
language = 'ko-KR'
}
wsCache.set('user.language', language)
this.language = language