Merge branch 'main' into feat/workflow

This commit is contained in:
StyleZhang 2024-03-15 11:17:18 +08:00
commit 86d2c1184c
96 changed files with 6016 additions and 295 deletions

3
.gitignore vendored
View File

@ -154,4 +154,5 @@ sdks/python-client/dist
sdks/python-client/dify_client.egg-info
.vscode/*
!.vscode/launch.json
!.vscode/launch.json
pyrightconfig.json

View File

@ -22,19 +22,8 @@
</p>
<p align="center">
<a href="https://discord.com/events/1082486657678311454/1211724120996188220" target="_blank">
Dify.AI Upcoming Meetup Event [👉 Click to Join the Event Here 👈]
</a>
<ul align="center" style="text-decoration: none; list-style: none;">
<li> US EST: 09:00 (9:00 AM)</li>
<li> CET: 15:00 (3:00 PM)</li>
<li> CST: 22:00 (10:00 PM)</li>
</ul>
</p>
<p align="center">
<a href="https://dify.ai/blog/dify-ai-unveils-ai-agent-creating-gpts-and-assistants-with-various-llms" target="_blank">
Dify.AI Unveils AI Agent: Creating GPTs and Assistants with Various LLMs
<a href="https://aws.amazon.com/marketplace/pp/prodview-t22mebxzwjhu6" target="_blank">
📌 Check out Dify Premium on AWS and deploy it to your own AWS VPC with one-click.
</a>
</p>
@ -48,6 +37,9 @@
You can try out [Dify.AI Cloud](https://dify.ai) now. It provides all the capabilities of the self-deployed version, and includes 200 free requests to OpenAI GPT-3.5.
### Looking to purchase via AWS?
Check out [Dify Premium on AWS](https://aws.amazon.com/marketplace/pp/prodview-t22mebxzwjhu6) and deploy it to your own AWS VPC with one-click.
## Dify vs. LangChain vs. Assistants API
| Feature | Dify.AI | Assistants API | LangChain |

View File

@ -90,7 +90,7 @@ class Config:
# ------------------------
# General Configurations.
# ------------------------
self.CURRENT_VERSION = "0.5.8"
self.CURRENT_VERSION = "0.5.9"
self.COMMIT_SHA = get_env('COMMIT_SHA')
self.EDITION = "SELF_HOSTED"
self.DEPLOY_ENV = get_env('DEPLOY_ENV')

View File

@ -2,7 +2,7 @@ import json
from models.model import AppModelConfig
languages = ['en-US', 'zh-Hans', 'pt-BR', 'es-ES', 'fr-FR', 'de-DE', 'ja-JP', 'ko-KR', 'ru-RU', 'it-IT', 'uk-UA']
languages = ['en-US', 'zh-Hans', 'pt-BR', 'es-ES', 'fr-FR', 'de-DE', 'ja-JP', 'ko-KR', 'ru-RU', 'it-IT', 'uk-UA', 'vi-VN']
language_timezone_mapping = {
'en-US': 'America/New_York',
@ -16,6 +16,7 @@ language_timezone_mapping = {
'ru-RU': 'Europe/Moscow',
'it-IT': 'Europe/Rome',
'uk-UA': 'Europe/Kyiv',
'vi-VN': 'Asia/Ho_Chi_Minh',
}
@ -79,6 +80,16 @@ user_input_form_template = {
}
}
],
"vi-VN": [
{
"paragraph": {
"label": "Nội dung truy vấn",
"variable": "default_input",
"required": False,
"default": ""
}
}
],
}
demo_model_templates = {
@ -208,7 +219,6 @@ demo_model_templates = {
)
}
],
'zh-Hans': [
{
'name': '翻译助手',
@ -335,91 +345,92 @@ demo_model_templates = {
)
}
],
'uk-UA': [{
"name": "Помічник перекладу",
"icon": "",
"icon_background": "",
"description": "Багатомовний перекладач, який надає можливості перекладу різними мовами, перекладаючи введені користувачем дані на потрібну мову.",
"mode": "completion",
"model_config": AppModelConfig(
provider="openai",
model_id="gpt-3.5-turbo-instruct",
configs={
"prompt_template": "Будь ласка, перекладіть наступний текст на {{target_language}}:\n",
"prompt_variables": [
{
"key": "target_language",
"name": "Цільова мова",
"description": "Мова, на яку ви хочете перекласти.",
"type": "select",
"default": "Ukrainian",
"options": [
"Chinese",
"English",
"Japanese",
"French",
"Russian",
"German",
"Spanish",
"Korean",
"Italian",
],
'uk-UA': [
{
"name": "Помічник перекладу",
"icon": "",
"icon_background": "",
"description": "Багатомовний перекладач, який надає можливості перекладу різними мовами, перекладаючи введені користувачем дані на потрібну мову.",
"mode": "completion",
"model_config": AppModelConfig(
provider="openai",
model_id="gpt-3.5-turbo-instruct",
configs={
"prompt_template": "Будь ласка, перекладіть наступний текст на {{target_language}}:\n",
"prompt_variables": [
{
"key": "target_language",
"name": "Цільова мова",
"description": "Мова, на яку ви хочете перекласти.",
"type": "select",
"default": "Ukrainian",
"options": [
"Chinese",
"English",
"Japanese",
"French",
"Russian",
"German",
"Spanish",
"Korean",
"Italian",
],
},
],
"completion_params": {
"max_token": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
],
"completion_params": {
"max_token": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
},
opening_statement="",
suggested_questions=None,
pre_prompt="Будь ласка, перекладіть наступний текст на {{target_language}}:\n{{query}}\ntranslate:",
model=json.dumps({
"provider": "openai",
"name": "gpt-3.5-turbo-instruct",
"mode": "completion",
"completion_params": {
"max_tokens": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
}),
user_input_form=json.dumps([
{
"select": {
"label": "Цільова мова",
"variable": "target_language",
"description": "Мова, на яку ви хочете перекласти.",
"default": "Chinese",
"required": True,
'options': [
'Chinese',
'English',
'Japanese',
'French',
'Russian',
'German',
'Spanish',
'Korean',
'Italian',
]
opening_statement="",
suggested_questions=None,
pre_prompt="Будь ласка, перекладіть наступний текст на {{target_language}}:\n{{query}}\ntranslate:",
model=json.dumps({
"provider": "openai",
"name": "gpt-3.5-turbo-instruct",
"mode": "completion",
"completion_params": {
"max_tokens": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1,
},
}),
user_input_form=json.dumps([
{
"select": {
"label": "Цільова мова",
"variable": "target_language",
"description": "Мова, на яку ви хочете перекласти.",
"default": "Chinese",
"required": True,
'options': [
'Chinese',
'English',
'Japanese',
'French',
'Russian',
'German',
'Spanish',
'Korean',
'Italian',
]
}
}, {
"paragraph": {
"label": "Запит",
"variable": "query",
"required": True,
"default": ""
}
}
}, {
"paragraph": {
"label": "Запит",
"variable": "query",
"required": True,
"default": ""
}
}
])
)
},
])
)
},
{
"name": "AI інтерв’юер фронтенду",
"icon": "",
@ -460,5 +471,132 @@ demo_model_templates = {
),
}
],
'vi-VN': [
{
'name': 'Trợ lý dịch thuật',
'icon': '',
'icon_background': '',
'description': 'Trình dịch đa ngôn ngữ cung cấp khả năng dịch bằng nhiều ngôn ngữ, dịch thông tin đầu vào của người dùng sang ngôn ngữ họ cần.',
'mode': 'completion',
'model_config': AppModelConfig(
provider='openai',
model_id='gpt-3.5-turbo-instruct',
configs={
'prompt_template': "Hãy dịch đoạn văn bản sau sang ngôn ngữ {{target_language}}:\n",
'prompt_variables': [
{
"key": "target_language",
"name": "Ngôn ngữ đích",
"description": "Ngôn ngữ bạn muốn dịch sang.",
"type": "select",
"default": "Vietnamese",
'options': [
'Chinese',
'English',
'Japanese',
'French',
'Russian',
'German',
'Spanish',
'Korean',
'Italian',
'Vietnamese',
]
}
],
'completion_params': {
'max_token': 1000,
'temperature': 0,
'top_p': 0,
'presence_penalty': 0.1,
'frequency_penalty': 0.1,
}
},
opening_statement='',
suggested_questions=None,
pre_prompt="Hãy dịch đoạn văn bản sau sang {{target_language}}:\n{{query}}\ndịch:",
model=json.dumps({
"provider": "openai",
"name": "gpt-3.5-turbo-instruct",
"mode": "completion",
"completion_params": {
"max_tokens": 1000,
"temperature": 0,
"top_p": 0,
"presence_penalty": 0.1,
"frequency_penalty": 0.1
}
}),
user_input_form=json.dumps([
{
"select": {
"label": "Ngôn ngữ đích",
"variable": "target_language",
"description": "Ngôn ngữ bạn muốn dịch sang.",
"default": "Vietnamese",
"required": True,
'options': [
'Chinese',
'English',
'Japanese',
'French',
'Russian',
'German',
'Spanish',
'Korean',
'Italian',
'Vietnamese',
]
}
}, {
"paragraph": {
"label": "Query",
"variable": "query",
"required": True,
"default": ""
}
}
])
)
},
{
'name': 'Phỏng vấn front-end AI',
'icon': '',
'icon_background': '',
'description': 'Một người phỏng vấn front-end mô phỏng để kiểm tra mức độ kỹ năng phát triển front-end thông qua việc đặt câu hỏi.',
'mode': 'chat',
'model_config': AppModelConfig(
provider='openai',
model_id='gpt-3.5-turbo',
configs={
'introduction': 'Xin chào, chào mừng đến với cuộc phỏng vấn của chúng tôi. Tôi là người phỏng vấn cho công ty công nghệ này và tôi sẽ kiểm tra kỹ năng phát triển web front-end của bạn. Tiếp theo, tôi sẽ hỏi bạn một số câu hỏi kỹ thuật. Hãy trả lời chúng càng kỹ lưỡng càng tốt. ',
'prompt_template': "Bạn sẽ đóng vai người phỏng vấn cho một công ty công nghệ, kiểm tra kỹ năng phát triển web front-end của người dùng và đặt ra 5-10 câu hỏi kỹ thuật sắc bén.\n\nXin lưu ý:\n- Mỗi lần chỉ hỏi một câu hỏi.\n - Sau khi người dùng trả lời một câu hỏi, hãy hỏi trực tiếp câu hỏi tiếp theo mà không cố gắng sửa bất kỳ lỗi nào mà thí sinh mắc phải.\n- Nếu bạn cho rằng người dùng đã không trả lời đúng cho một số câu hỏi liên tiếp, hãy hỏi ít câu hỏi hơn.\n- Sau đặt câu hỏi cuối cùng, bạn có thể hỏi câu hỏi này: Tại sao bạn lại rời bỏ công việc cuối cùng của mình? Sau khi người dùng trả lời câu hỏi này, vui lòng bày tỏ sự hiểu biết và ủng hộ của bạn.\n",
'prompt_variables': [],
'completion_params': {
'max_token': 300,
'temperature': 0.8,
'top_p': 0.9,
'presence_penalty': 0.1,
'frequency_penalty': 0.1,
}
},
opening_statement='Xin chào, chào mừng đến với cuộc phỏng vấn của chúng tôi. Tôi là người phỏng vấn cho công ty công nghệ này và tôi sẽ kiểm tra kỹ năng phát triển web front-end của bạn. Tiếp theo, tôi sẽ hỏi bạn một số câu hỏi kỹ thuật. Hãy trả lời chúng càng kỹ lưỡng càng tốt. ',
suggested_questions=None,
pre_prompt="Bạn sẽ đóng vai người phỏng vấn cho một công ty công nghệ, kiểm tra kỹ năng phát triển web front-end của người dùng và đặt ra 5-10 câu hỏi kỹ thuật sắc bén.\n\nXin lưu ý:\n- Mỗi lần chỉ hỏi một câu hỏi.\n - Sau khi người dùng trả lời một câu hỏi, hãy hỏi trực tiếp câu hỏi tiếp theo mà không cố gắng sửa bất kỳ lỗi nào mà thí sinh mắc phải.\n- Nếu bạn cho rằng người dùng đã không trả lời đúng cho một số câu hỏi liên tiếp, hãy hỏi ít câu hỏi hơn.\n- Sau đặt câu hỏi cuối cùng, bạn có thể hỏi câu hỏi này: Tại sao bạn lại rời bỏ công việc cuối cùng của mình? Sau khi người dùng trả lời câu hỏi này, vui lòng bày tỏ sự hiểu biết và ủng hộ của bạn.\n",
model=json.dumps({
"provider": "openai",
"name": "gpt-3.5-turbo",
"mode": "chat",
"completion_params": {
"max_tokens": 300,
"temperature": 0.8,
"top_p": 0.9,
"presence_penalty": 0.1,
"frequency_penalty": 0.1
}
}),
user_input_form=None
)
}
],
}

View File

@ -245,29 +245,34 @@ class AppApi(Resource):
agent_mode = model_config.agent_mode_dict
# decrypt agent tool parameters if it's secret-input
for tool in agent_mode.get('tools') or []:
if not isinstance(tool, dict) or len(tool.keys()) <= 3:
continue
agent_tool_entity = AgentToolEntity(**tool)
# get tool
tool_runtime = ToolManager.get_agent_tool_runtime(
tenant_id=current_user.current_tenant_id,
agent_tool=agent_tool_entity,
agent_callback=None
)
manager = ToolParameterConfigurationManager(
tenant_id=current_user.current_tenant_id,
tool_runtime=tool_runtime,
provider_name=agent_tool_entity.provider_id,
provider_type=agent_tool_entity.provider_type,
)
try:
tool_runtime = ToolManager.get_agent_tool_runtime(
tenant_id=current_user.current_tenant_id,
agent_tool=agent_tool_entity,
agent_callback=None
)
manager = ToolParameterConfigurationManager(
tenant_id=current_user.current_tenant_id,
tool_runtime=tool_runtime,
provider_name=agent_tool_entity.provider_id,
provider_type=agent_tool_entity.provider_type,
)
# get decrypted parameters
if agent_tool_entity.tool_parameters:
parameters = manager.decrypt_tool_parameters(agent_tool_entity.tool_parameters or {})
masked_parameter = manager.mask_tool_parameters(parameters or {})
else:
masked_parameter = {}
# get decrypted parameters
if agent_tool_entity.tool_parameters:
parameters = manager.decrypt_tool_parameters(agent_tool_entity.tool_parameters or {})
masked_parameter = manager.mask_tool_parameters(parameters or {})
else:
masked_parameter = {}
# override tool parameters
tool['tool_parameters'] = masked_parameter
# override tool parameters
tool['tool_parameters'] = masked_parameter
except Exception as e:
pass
# override agent mode
model_config.agent_mode = json.dumps(agent_mode)

View File

@ -54,17 +54,20 @@ class ModelConfigResource(Resource):
for tool in agent_mode.get('tools') or []:
agent_tool_entity = AgentToolEntity(**tool)
# get tool
tool_runtime = ToolManager.get_agent_tool_runtime(
tenant_id=current_user.current_tenant_id,
agent_tool=agent_tool_entity,
agent_callback=None
)
manager = ToolParameterConfigurationManager(
tenant_id=current_user.current_tenant_id,
tool_runtime=tool_runtime,
provider_name=agent_tool_entity.provider_id,
provider_type=agent_tool_entity.provider_type,
)
try:
tool_runtime = ToolManager.get_agent_tool_runtime(
tenant_id=current_user.current_tenant_id,
agent_tool=agent_tool_entity,
agent_callback=None
)
manager = ToolParameterConfigurationManager(
tenant_id=current_user.current_tenant_id,
tool_runtime=tool_runtime,
provider_name=agent_tool_entity.provider_id,
provider_type=agent_tool_entity.provider_type,
)
except Exception as e:
continue
# get decrypted parameters
if agent_tool_entity.tool_parameters:
@ -89,11 +92,14 @@ class ModelConfigResource(Resource):
if key in tool_map:
tool_runtime = tool_map[key]
else:
tool_runtime = ToolManager.get_agent_tool_runtime(
tenant_id=current_user.current_tenant_id,
agent_tool=agent_tool_entity,
agent_callback=None
)
try:
tool_runtime = ToolManager.get_agent_tool_runtime(
tenant_id=current_user.current_tenant_id,
agent_tool=agent_tool_entity,
agent_callback=None
)
except Exception as e:
continue
manager = ToolParameterConfigurationManager(
tenant_id=current_user.current_tenant_id,

View File

@ -44,7 +44,7 @@ class AudioApi(Resource):
response = AudioService.transcript_asr(
tenant_id=app_model.tenant_id,
file=file,
end_user=end_user
end_user=end_user.get_id()
)
return response
@ -75,7 +75,7 @@ class AudioApi(Resource):
class TextApi(Resource):
@validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON, required=True))
@validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON))
def post(self, app_model: App, end_user: EndUser):
parser = reqparse.RequestParser()
parser.add_argument('text', type=str, required=True, nullable=False, location='json')
@ -86,8 +86,8 @@ class TextApi(Resource):
response = AudioService.transcript_tts(
tenant_id=app_model.tenant_id,
text=args['text'],
end_user=end_user,
voice=args['voice'] if args['voice'] else app_model.app_model_config.text_to_speech_dict.get('voice'),
end_user=end_user.get_id(),
voice=app_model.app_model_config.text_to_speech_dict.get('voice'),
streaming=args['streaming']
)

View File

@ -3,11 +3,12 @@ import importlib.util
import json
import logging
import os
from collections import OrderedDict
from typing import Any, Optional
from pydantic import BaseModel
from core.utils.position_helper import sort_to_dict_by_position_map
class ExtensionModule(enum.Enum):
MODERATION = 'moderation'
@ -36,7 +37,8 @@ class Extensible:
@classmethod
def scan_extensions(cls):
extensions = {}
extensions: list[ModuleExtension] = []
position_map = {}
# get the path of the current class
current_path = os.path.abspath(cls.__module__.replace(".", os.path.sep) + '.py')
@ -63,6 +65,7 @@ class Extensible:
if os.path.exists(builtin_file_path):
with open(builtin_file_path, encoding='utf-8') as f:
position = int(f.read().strip())
position_map[extension_name] = position
if (extension_name + '.py') not in file_names:
logging.warning(f"Missing {extension_name}.py file in {subdir_path}, Skip.")
@ -96,16 +99,15 @@ class Extensible:
with open(json_path, encoding='utf-8') as f:
json_data = json.load(f)
extensions[extension_name] = ModuleExtension(
extensions.append(ModuleExtension(
extension_class=extension_class,
name=extension_name,
label=json_data.get('label'),
form_schema=json_data.get('form_schema'),
builtin=builtin,
position=position
)
))
sorted_items = sorted(extensions.items(), key=lambda x: (x[1].position is None, x[1].position))
sorted_extensions = OrderedDict(sorted_items)
sorted_extensions = sort_to_dict_by_position_map(position_map, extensions, lambda x: x.name)
return sorted_extensions

View File

@ -416,9 +416,14 @@ class IndexingRunner:
if separator:
separator = separator.replace('\\n', '\n')
if 'chunk_overlap' in segmentation and segmentation['chunk_overlap']:
chunk_overlap = segmentation['chunk_overlap']
else:
chunk_overlap = 0
character_splitter = FixedRecursiveCharacterTextSplitter.from_encoder(
chunk_size=segmentation["max_tokens"],
chunk_overlap=segmentation.get('chunk_overlap', 0),
chunk_overlap=chunk_overlap,
fixed_separator=separator,
separators=["\n\n", "", ".", " ", ""],
embedding_model_instance=embedding_model_instance

View File

@ -133,7 +133,7 @@ class ModelPropertyKey(Enum):
DEFAULT_VOICE = "default_voice"
VOICES = "voices"
WORD_LIMIT = "word_limit"
AUDOI_TYPE = "audio_type"
AUDIO_TYPE = "audio_type"
MAX_WORKERS = "max_workers"

View File

@ -18,6 +18,7 @@ from core.model_runtime.entities.model_entities import (
)
from core.model_runtime.errors.invoke import InvokeAuthorizationError, InvokeError
from core.model_runtime.model_providers.__base.tokenizers.gpt2_tokenzier import GPT2Tokenizer
from core.utils.position_helper import get_position_map, sort_by_position_map
class AIModel(ABC):
@ -148,15 +149,7 @@ class AIModel(ABC):
]
# get _position.yaml file path
position_file_path = os.path.join(provider_model_type_path, '_position.yaml')
# read _position.yaml file
position_map = {}
if os.path.exists(position_file_path):
with open(position_file_path, encoding='utf-8') as f:
positions = yaml.safe_load(f)
# convert list to dict with key as model provider name, value as index
position_map = {position: index for index, position in enumerate(positions)}
position_map = get_position_map(provider_model_type_path)
# traverse all model_schema_yaml_paths
for model_schema_yaml_path in model_schema_yaml_paths:
@ -206,8 +199,7 @@ class AIModel(ABC):
model_schemas.append(model_schema)
# resort model schemas by position
if position_map:
model_schemas.sort(key=lambda x: position_map.get(x.model, 999))
model_schemas = sort_by_position_map(position_map, model_schemas, lambda x: x.model)
# cache model schemas
self.model_schemas = model_schemas

View File

@ -94,8 +94,8 @@ class TTSModel(AIModel):
"""
model_schema = self.get_model_schema(model, credentials)
if model_schema and ModelPropertyKey.AUDOI_TYPE in model_schema.model_properties:
return model_schema.model_properties[ModelPropertyKey.AUDOI_TYPE]
if model_schema and ModelPropertyKey.AUDIO_TYPE in model_schema.model_properties:
return model_schema.model_properties[ModelPropertyKey.AUDIO_TYPE]
def _get_model_word_limit(self, model: str, credentials: dict) -> int:
"""

View File

@ -0,0 +1,37 @@
model: claude-3-haiku-20240307
label:
en_US: claude-3-haiku-20240307
model_type: llm
features:
- agent-thought
- vision
model_properties:
mode: chat
context_size: 200000
parameter_rules:
- name: temperature
use_template: temperature
- name: top_p
use_template: top_p
- name: top_k
label:
zh_Hans: 取样数量
en_US: Top k
type: int
help:
zh_Hans: 仅从每个后续标记的前 K 个选项中采样。
en_US: Only sample from the top K options for each subsequent token.
required: false
- name: max_tokens
use_template: max_tokens
required: true
default: 4096
min: 1
max: 4096
- name: response_format
use_template: response_format
pricing:
input: '0.25'
output: '1.25'
unit: '0.000001'
currency: USD

View File

@ -15,10 +15,11 @@ from core.model_runtime.model_providers.azure_openai._constant import AZURE_OPEN
class _CommonAzureOpenAI:
@staticmethod
def _to_credential_kwargs(credentials: dict) -> dict:
api_version = credentials.get('openai_api_version', AZURE_OPENAI_API_VERSION)
credentials_kwargs = {
"api_key": credentials['openai_api_key'],
"azure_endpoint": credentials['openai_api_base'],
"api_version": AZURE_OPENAI_API_VERSION,
"api_version": api_version,
"timeout": Timeout(315.0, read=300.0, write=10.0, connect=5.0),
"max_retries": 1,
}

View File

@ -14,8 +14,7 @@ from core.model_runtime.entities.model_entities import (
PriceConfig,
)
AZURE_OPENAI_API_VERSION = '2023-12-01-preview'
AZURE_OPENAI_API_VERSION = '2024-02-15-preview'
def _get_max_tokens(default: int, min_val: int, max_val: int) -> ParameterRule:
rule = ParameterRule(
@ -583,3 +582,113 @@ SPEECH2TEXT_BASE_MODELS = [
)
)
]
TTS_BASE_MODELS = [
AzureBaseModel(
base_model_name='tts-1',
entity=AIModelEntity(
model='fake-deployment-name',
label=I18nObject(
en_US='fake-deployment-name-label'
),
fetch_from=FetchFrom.CUSTOMIZABLE_MODEL,
model_type=ModelType.TTS,
model_properties={
ModelPropertyKey.DEFAULT_VOICE: 'alloy',
ModelPropertyKey.VOICES: [
{
'mode': 'alloy',
'name': 'Alloy',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'echo',
'name': 'Echo',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'fable',
'name': 'Fable',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'onyx',
'name': 'Onyx',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'nova',
'name': 'Nova',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'shimmer',
'name': 'Shimmer',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
],
ModelPropertyKey.WORD_LIMIT: 120,
ModelPropertyKey.AUDIO_TYPE: 'mp3',
ModelPropertyKey.MAX_WORKERS: 5
},
pricing=PriceConfig(
input=0.015,
unit=0.001,
currency='USD',
)
)
),
AzureBaseModel(
base_model_name='tts-1-hd',
entity=AIModelEntity(
model='fake-deployment-name',
label=I18nObject(
en_US='fake-deployment-name-label'
),
fetch_from=FetchFrom.CUSTOMIZABLE_MODEL,
model_type=ModelType.TTS,
model_properties={
ModelPropertyKey.DEFAULT_VOICE: 'alloy',
ModelPropertyKey.VOICES: [
{
'mode': 'alloy',
'name': 'Alloy',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'echo',
'name': 'Echo',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'fable',
'name': 'Fable',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'onyx',
'name': 'Onyx',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'nova',
'name': 'Nova',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
{
'mode': 'shimmer',
'name': 'Shimmer',
'language': ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
},
],
ModelPropertyKey.WORD_LIMIT: 120,
ModelPropertyKey.AUDIO_TYPE: 'mp3',
ModelPropertyKey.MAX_WORKERS: 5
},
pricing=PriceConfig(
input=0.03,
unit=0.001,
currency='USD',
)
)
)
]

View File

@ -16,6 +16,7 @@ supported_model_types:
- llm
- text-embedding
- speech2text
- tts
configurate_methods:
- customizable-model
model_credential_schema:
@ -45,6 +46,22 @@ model_credential_schema:
placeholder:
zh_Hans: 在此输入您的 API Key
en_US: Enter your API key here
- variable: openai_api_version
label:
zh_Hans: API 版本
en_US: API Version
type: select
required: true
options:
- label:
en_US: 2024-02-15-preview
value: 2024-02-15-preview
- label:
en_US: 2023-12-01-preview
value: 2023-12-01-preview
placeholder:
zh_Hans: 在此选择您的 API 版本
en_US: Select your API Version here
- variable: base_model_name
label:
en_US: Base Model
@ -118,6 +135,18 @@ model_credential_schema:
show_on:
- variable: __model_type
value: speech2text
- label:
en_US: tts-1
value: tts-1
show_on:
- variable: __model_type
value: tts
- label:
en_US: tts-1-hd
value: tts-1-hd
show_on:
- variable: __model_type
value: tts
placeholder:
zh_Hans: 在此输入您的模型版本
en_US: Enter your model version

View File

@ -0,0 +1,174 @@
import concurrent.futures
import copy
from functools import reduce
from io import BytesIO
from typing import Optional
from flask import Response, stream_with_context
from openai import AzureOpenAI
from pydub import AudioSegment
from core.model_runtime.entities.model_entities import AIModelEntity
from core.model_runtime.errors.invoke import InvokeBadRequestError
from core.model_runtime.errors.validate import CredentialsValidateFailedError
from core.model_runtime.model_providers.__base.tts_model import TTSModel
from core.model_runtime.model_providers.azure_openai._common import _CommonAzureOpenAI
from core.model_runtime.model_providers.azure_openai._constant import TTS_BASE_MODELS, AzureBaseModel
from extensions.ext_storage import storage
class AzureOpenAIText2SpeechModel(_CommonAzureOpenAI, TTSModel):
"""
Model class for OpenAI Speech to text model.
"""
def _invoke(self, model: str, tenant_id: str, credentials: dict,
content_text: str, voice: str, streaming: bool, user: Optional[str] = None) -> any:
"""
_invoke text2speech model
:param model: model name
:param tenant_id: user tenant id
:param credentials: model credentials
:param content_text: text content to be translated
:param voice: model timbre
:param streaming: output is streaming
:param user: unique user id
:return: text translated to audio file
"""
audio_type = self._get_model_audio_type(model, credentials)
if not voice or voice not in [d['value'] for d in self.get_tts_model_voices(model=model, credentials=credentials)]:
voice = self._get_model_default_voice(model, credentials)
if streaming:
return Response(stream_with_context(self._tts_invoke_streaming(model=model,
credentials=credentials,
content_text=content_text,
tenant_id=tenant_id,
voice=voice)),
status=200, mimetype=f'audio/{audio_type}')
else:
return self._tts_invoke(model=model, credentials=credentials, content_text=content_text, voice=voice)
def validate_credentials(self, model: str, credentials: dict, user: Optional[str] = None) -> None:
"""
validate credentials text2speech model
:param model: model name
:param credentials: model credentials
:param user: unique user id
:return: text translated to audio file
"""
try:
self._tts_invoke(
model=model,
credentials=credentials,
content_text='Hello Dify!',
voice=self._get_model_default_voice(model, credentials),
)
except Exception as ex:
raise CredentialsValidateFailedError(str(ex))
def _tts_invoke(self, model: str, credentials: dict, content_text: str, voice: str) -> Response:
"""
_tts_invoke text2speech model
:param model: model name
:param credentials: model credentials
:param content_text: text content to be translated
:param voice: model timbre
:return: text translated to audio file
"""
audio_type = self._get_model_audio_type(model, credentials)
word_limit = self._get_model_word_limit(model, credentials)
max_workers = self._get_model_workers_limit(model, credentials)
try:
sentences = list(self._split_text_into_sentences(text=content_text, limit=word_limit))
audio_bytes_list = list()
# Create a thread pool and map the function to the list of sentences
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(self._process_sentence, sentence=sentence, model=model, voice=voice,
credentials=credentials) for sentence in sentences]
for future in futures:
try:
if future.result():
audio_bytes_list.append(future.result())
except Exception as ex:
raise InvokeBadRequestError(str(ex))
if len(audio_bytes_list) > 0:
audio_segments = [AudioSegment.from_file(BytesIO(audio_bytes), format=audio_type) for audio_bytes in
audio_bytes_list if audio_bytes]
combined_segment = reduce(lambda x, y: x + y, audio_segments)
buffer: BytesIO = BytesIO()
combined_segment.export(buffer, format=audio_type)
buffer.seek(0)
return Response(buffer.read(), status=200, mimetype=f"audio/{audio_type}")
except Exception as ex:
raise InvokeBadRequestError(str(ex))
# Todo: To improve the streaming function
def _tts_invoke_streaming(self, model: str, tenant_id: str, credentials: dict, content_text: str,
voice: str) -> any:
"""
_tts_invoke_streaming text2speech model
:param model: model name
:param tenant_id: user tenant id
:param credentials: model credentials
:param content_text: text content to be translated
:param voice: model timbre
:return: text translated to audio file
"""
# transform credentials to kwargs for model instance
credentials_kwargs = self._to_credential_kwargs(credentials)
if not voice or voice not in self.get_tts_model_voices(model=model, credentials=credentials):
voice = self._get_model_default_voice(model, credentials)
word_limit = self._get_model_word_limit(model, credentials)
audio_type = self._get_model_audio_type(model, credentials)
tts_file_id = self._get_file_name(content_text)
file_path = f'generate_files/audio/{tenant_id}/{tts_file_id}.{audio_type}'
try:
client = AzureOpenAI(**credentials_kwargs)
sentences = list(self._split_text_into_sentences(text=content_text, limit=word_limit))
for sentence in sentences:
response = client.audio.speech.create(model=model, voice=voice, input=sentence.strip())
# response.stream_to_file(file_path)
storage.save(file_path, response.read())
except Exception as ex:
raise InvokeBadRequestError(str(ex))
def _process_sentence(self, sentence: str, model: str,
voice, credentials: dict):
"""
_tts_invoke openai text2speech model api
:param model: model name
:param credentials: model credentials
:param voice: model timbre
:param sentence: text content to be translated
:return: text translated to audio file
"""
# transform credentials to kwargs for model instance
credentials_kwargs = self._to_credential_kwargs(credentials)
client = AzureOpenAI(**credentials_kwargs)
response = client.audio.speech.create(model=model, voice=voice, input=sentence.strip())
if isinstance(response.read(), bytes):
return response.read()
def get_customizable_model_schema(self, model: str, credentials: dict) -> Optional[AIModelEntity]:
ai_model_entity = self._get_ai_model_entity(credentials['base_model_name'], model)
return ai_model_entity.entity
@staticmethod
def _get_ai_model_entity(base_model_name: str, model: str) -> AzureBaseModel:
for ai_model_entity in TTS_BASE_MODELS:
if ai_model_entity.base_model_name == base_model_name:
ai_model_entity_copy = copy.deepcopy(ai_model_entity)
ai_model_entity_copy.entity.model = model
ai_model_entity_copy.entity.label.en_US = model
ai_model_entity_copy.entity.label.zh_Hans = model
return ai_model_entity_copy
return None

View File

@ -472,7 +472,7 @@ class CohereLargeLanguageModel(LargeLanguageModel):
else:
raise ValueError(f"Got unknown type {message}")
if message.name is not None:
if message.name:
message_dict["user_name"] = message.name
return message_dict

View File

@ -24,7 +24,7 @@ parameter_rules:
min: 1
max: 8000
- name: safe_prompt
defulat: false
default: false
type: boolean
help:
en_US: Whether to inject a safety prompt before all conversations.

View File

@ -24,7 +24,7 @@ parameter_rules:
min: 1
max: 8000
- name: safe_prompt
defulat: false
default: false
type: boolean
help:
en_US: Whether to inject a safety prompt before all conversations.

View File

@ -24,7 +24,7 @@ parameter_rules:
min: 1
max: 8000
- name: safe_prompt
defulat: false
default: false
type: boolean
help:
en_US: Whether to inject a safety prompt before all conversations.

View File

@ -24,7 +24,7 @@ parameter_rules:
min: 1
max: 2048
- name: safe_prompt
defulat: false
default: false
type: boolean
help:
en_US: Whether to inject a safety prompt before all conversations.

View File

@ -24,7 +24,7 @@ parameter_rules:
min: 1
max: 8000
- name: safe_prompt
defulat: false
default: false
type: boolean
help:
en_US: Whether to inject a safety prompt before all conversations.

View File

@ -1,10 +1,8 @@
import importlib
import logging
import os
from collections import OrderedDict
from typing import Optional
import yaml
from pydantic import BaseModel
from core.model_runtime.entities.model_entities import ModelType
@ -12,6 +10,7 @@ from core.model_runtime.entities.provider_entities import ProviderConfig, Provid
from core.model_runtime.model_providers.__base.model_provider import ModelProvider
from core.model_runtime.schema_validators.model_credential_schema_validator import ModelCredentialSchemaValidator
from core.model_runtime.schema_validators.provider_credential_schema_validator import ProviderCredentialSchemaValidator
from core.utils.position_helper import get_position_map, sort_to_dict_by_position_map
logger = logging.getLogger(__name__)
@ -200,7 +199,6 @@ class ModelProviderFactory:
if self.model_provider_extensions:
return self.model_provider_extensions
model_providers = {}
# get the path of current classes
current_path = os.path.abspath(__file__)
@ -215,17 +213,10 @@ class ModelProviderFactory:
]
# get _position.yaml file path
position_file_path = os.path.join(model_providers_path, '_position.yaml')
# read _position.yaml file
position_map = {}
if os.path.exists(position_file_path):
with open(position_file_path, encoding='utf-8') as f:
positions = yaml.safe_load(f)
# convert list to dict with key as model provider name, value as index
position_map = {position: index for index, position in enumerate(positions)}
position_map = get_position_map(model_providers_path)
# traverse all model_provider_dir_paths
model_providers: list[ModelProviderExtension] = []
for model_provider_dir_path in model_provider_dir_paths:
# get model_provider dir name
model_provider_name = os.path.basename(model_provider_dir_path)
@ -256,14 +247,13 @@ class ModelProviderFactory:
logger.warning(f"Missing {model_provider_name}.yaml file in {model_provider_dir_path}, Skip.")
continue
model_providers[model_provider_name] = ModelProviderExtension(
model_providers.append(ModelProviderExtension(
name=model_provider_name,
provider_instance=model_provider_class(),
position=position_map.get(model_provider_name)
)
))
sorted_items = sorted(model_providers.items(), key=lambda x: (x[1].position is None, x[1].position))
sorted_extensions = OrderedDict(sorted_items)
sorted_extensions = sort_to_dict_by_position_map(position_map, model_providers, lambda x: x.name)
self.model_provider_extensions = sorted_extensions

View File

@ -25,6 +25,7 @@ from core.model_runtime.entities.model_entities import (
AIModelEntity,
DefaultParameterName,
FetchFrom,
ModelFeature,
ModelPropertyKey,
ModelType,
ParameterRule,
@ -166,11 +167,23 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
"""
generate custom model entities from credentials
"""
support_function_call = False
features = []
function_calling_type = credentials.get('function_calling_type', 'no_call')
if function_calling_type == 'function_call':
features = [ModelFeature.TOOL_CALL]
support_function_call = True
endpoint_url = credentials["endpoint_url"]
# if not endpoint_url.endswith('/'):
# endpoint_url += '/'
# if 'https://api.openai.com/v1/' == endpoint_url:
# features = [ModelFeature.STREAM_TOOL_CALL]
entity = AIModelEntity(
model=model,
label=I18nObject(en_US=model),
model_type=ModelType.LLM,
fetch_from=FetchFrom.CUSTOMIZABLE_MODEL,
features=features if support_function_call else [],
model_properties={
ModelPropertyKey.CONTEXT_SIZE: int(credentials.get('context_size', "4096")),
ModelPropertyKey.MODE: credentials.get('mode'),
@ -194,14 +207,6 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
max=1,
precision=2
),
ParameterRule(
name="top_k",
label=I18nObject(en_US="Top K"),
type=ParameterType.INT,
default=int(credentials.get('top_k', 1)),
min=1,
max=100
),
ParameterRule(
name=DefaultParameterName.FREQUENCY_PENALTY.value,
label=I18nObject(en_US="Frequency Penalty"),
@ -232,7 +237,7 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
output=Decimal(credentials.get('output_price', 0)),
unit=Decimal(credentials.get('unit', 0)),
currency=credentials.get('currency', "USD")
)
),
)
if credentials['mode'] == 'chat':
@ -292,14 +297,22 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
raise ValueError("Unsupported completion type for model configuration.")
# annotate tools with names, descriptions, etc.
function_calling_type = credentials.get('function_calling_type', 'no_call')
formatted_tools = []
if tools:
data["tool_choice"] = "auto"
if function_calling_type == 'function_call':
data['functions'] = [{
"name": tool.name,
"description": tool.description,
"parameters": tool.parameters
} for tool in tools]
elif function_calling_type == 'tool_call':
data["tool_choice"] = "auto"
for tool in tools:
formatted_tools.append(helper.dump_model(PromptMessageFunction(function=tool)))
for tool in tools:
formatted_tools.append(helper.dump_model(PromptMessageFunction(function=tool)))
data["tools"] = formatted_tools
data["tools"] = formatted_tools
if stop:
data["stop"] = stop
@ -367,9 +380,9 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
for chunk in response.iter_lines(decode_unicode=True, delimiter=delimiter):
if chunk:
#ignore sse comments
# ignore sse comments
if chunk.startswith(':'):
continue
continue
decoded_chunk = chunk.strip().lstrip('data: ').lstrip()
chunk_json = None
try:
@ -452,10 +465,13 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
response_content = ''
tool_calls = None
function_calling_type = credentials.get('function_calling_type', 'no_call')
if completion_type is LLMMode.CHAT:
response_content = output.get('message', {})['content']
tool_calls = output.get('message', {}).get('tool_calls')
if function_calling_type == 'tool_call':
tool_calls = output.get('message', {}).get('tool_calls')
elif function_calling_type == 'function_call':
tool_calls = output.get('message', {}).get('function_call')
elif completion_type is LLMMode.COMPLETION:
response_content = output['text']
@ -463,7 +479,10 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
assistant_message = AssistantPromptMessage(content=response_content, tool_calls=[])
if tool_calls:
assistant_message.tool_calls = self._extract_response_tool_calls(tool_calls)
if function_calling_type == 'tool_call':
assistant_message.tool_calls = self._extract_response_tool_calls(tool_calls)
elif function_calling_type == 'function_call':
assistant_message.tool_calls = [self._extract_response_function_call(tool_calls)]
usage = response_json.get("usage")
if usage:
@ -522,33 +541,34 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
message = cast(AssistantPromptMessage, message)
message_dict = {"role": "assistant", "content": message.content}
if message.tool_calls:
message_dict["tool_calls"] = [helper.dump_model(PromptMessageFunction(function=tool_call)) for tool_call
in
message.tool_calls]
# function_call = message.tool_calls[0]
# message_dict["function_call"] = {
# "name": function_call.function.name,
# "arguments": function_call.function.arguments,
# }
# message_dict["tool_calls"] = [helper.dump_model(PromptMessageFunction(function=tool_call)) for tool_call
# in
# message.tool_calls]
function_call = message.tool_calls[0]
message_dict["function_call"] = {
"name": function_call.function.name,
"arguments": function_call.function.arguments,
}
elif isinstance(message, SystemPromptMessage):
message = cast(SystemPromptMessage, message)
message_dict = {"role": "system", "content": message.content}
elif isinstance(message, ToolPromptMessage):
message = cast(ToolPromptMessage, message)
message_dict = {
"role": "tool",
"content": message.content,
"tool_call_id": message.tool_call_id
}
# message_dict = {
# "role": "function",
# "role": "tool",
# "content": message.content,
# "name": message.tool_call_id
# "tool_call_id": message.tool_call_id
# }
message_dict = {
"role": "function",
"content": message.content,
"name": message.tool_call_id
}
else:
raise ValueError(f"Got unknown type {message}")
if message.name is not None:
if message.name:
message_dict["name"] = message.name
return message_dict
@ -693,3 +713,26 @@ class OAIAPICompatLargeLanguageModel(_CommonOAI_API_Compat, LargeLanguageModel):
tool_calls.append(tool_call)
return tool_calls
def _extract_response_function_call(self, response_function_call) \
-> AssistantPromptMessage.ToolCall:
"""
Extract function call from response
:param response_function_call: response function call
:return: tool call
"""
tool_call = None
if response_function_call:
function = AssistantPromptMessage.ToolCall.ToolCallFunction(
name=response_function_call['name'],
arguments=response_function_call['arguments']
)
tool_call = AssistantPromptMessage.ToolCall(
id=response_function_call['name'],
type="function",
function=function
)
return tool_call

View File

@ -75,6 +75,28 @@ model_credential_schema:
value: llm
default: '4096'
type: text-input
- variable: function_calling_type
show_on:
- variable: __model_type
value: llm
label:
en_US: Function calling
type: select
required: false
default: no_call
options:
- value: function_call
label:
en_US: Support
zh_Hans: 支持
# - value: tool_call
# label:
# en_US: Tool Call
# zh_Hans: Tool Call
- value: no_call
label:
en_US: Not Support
zh_Hans: 不支持
- variable: stream_mode_delimiter
label:
zh_Hans: 流模式返回结果的分隔符

View File

@ -4,7 +4,6 @@ from typing import Any
from langchain.schema import BaseOutputParser
from core.model_runtime.errors.invoke import InvokeError
from core.prompt.prompts import SUGGESTED_QUESTIONS_AFTER_ANSWER_INSTRUCTION_PROMPT
@ -14,11 +13,11 @@ class SuggestedQuestionsAfterAnswerOutputParser(BaseOutputParser):
return SUGGESTED_QUESTIONS_AFTER_ANSWER_INSTRUCTION_PROMPT
def parse(self, text: str) -> Any:
json_string = text.strip()
action_match = re.search(r".*(\[\".+\"\]).*", json_string, re.DOTALL)
action_match = re.search(r"\[.*?\]", text.strip(), re.DOTALL)
if action_match is not None:
json_obj = json.loads(action_match.group(1).strip(), strict=False)
json_obj = json.loads(action_match.group(0).strip())
else:
raise InvokeError("Could not parse LLM output: {text}")
json_obj= []
print(f"Could not parse LLM output: {text}")
return json_obj

View File

@ -1,4 +1,4 @@
# Written by YORKI MINAKO🤡
# Written by YORKI MINAKO🤡, Edited by Xiaoyi
CONVERSATION_TITLE_PROMPT = """You need to decompose the user's input into "subject" and "intention" in order to accurately figure out what the user's input language actually is.
Notice: the language type user use could be diverse, which can be English, Chinese, Español, Arabic, Japanese, French, and etc.
MAKE SURE your output is the SAME language as the user's input!
@ -86,6 +86,21 @@ otherwise, it cannot exist as a variable in the variables.
If you believe revising the original input will result in a better response from the language model, you may \
suggest revisions.
<<PRINCIPLES OF GOOD PROMPT>>
Integrate the intended audience in the prompt e.g. the audience is an expert in the field.
Break down complex tasks into a sequence of simpler prompts in an interactive conversation.
Implement example-driven prompting (Use few-shot prompting).
When formatting your prompt start with Instruction followed by either Example if relevant. \
Subsequently present your content. Use one or more line breaks to separate instructions examples questions context and input data.
Incorporate the following phrases: Your task is and You MUST.
Incorporate the following phrases: You will be penalized.
Use leading words like writing think step by step.
Add to your prompt the following phrase Ensure that your answer is unbiased and does not rely on stereotypes.
Assign a role to the large language models.
Use Delimiters.
To write an essay /text /paragraph /article or any type of text that should be detailed: Write a detailed [essay/text/paragraph] for me on [topic] in detail by adding all the information necessary.
Clearly state the requirements that the model must follow in order to produce content in the form of the keywords regulations hint or instructions
<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like, \
no any other string out of markdown code snippet:
@ -102,27 +117,18 @@ and fill in variables, with a welcome sentence, and keep TLDR.
[EXAMPLE A]
```json
{
"prompt": "Write a letter about love",
"variables": [],
"opening_statement": "Hi! I'm your love letter writer AI."
"prompt": "I need your help to translate the following {{Input_language}}paper paragraph into {{Target_language}}, in a style similar to a popular science magazine in {{Target_language}}. #### Rules Ensure accurate conveyance of the original text's facts and context during translation. Maintain the original paragraph format and retain technical terms and company abbreviations ",
"variables": ["Input_language", "Target_language"],
"opening_statement": " Hi. I am your translation assistant. I can help you with any translation and ensure accurate conveyance of information. "
}
```
[EXAMPLE B]
```json
{
"prompt": "Translate from {{lanA}} to {{lanB}}",
"variables": ["lanA", "lanB"],
"opening_statement": "Welcome to use translate app"
}
```
[EXAMPLE C]
```json
{
"prompt": "Write a story about {{topic}}",
"variables": ["topic"],
"opening_statement": "I'm your story writer"
"prompt": "Your task is to review the provided meeting notes and create a concise summary that captures the essential information, focusing on key takeaways and action items assigned to specific individuals or departments during the meeting. Use clear and professional language, and organize the summary in a logical manner using appropriate formatting such as headings, subheadings, and bullet points. Ensure that the summary is easy to understand and provides a comprehensive but succinct overview of the meeting's content, with a particular focus on clearly indicating who is responsible for each action item.",
"variables": ["meeting_notes"],
"opening_statement": "Hi! I'm your meeting notes summarizer AI. I can help you with any meeting notes and ensure accurate conveyance of information."
}
```

View File

@ -29,10 +29,10 @@ class ExcelExtractor(BaseExtractor):
def extract(self) -> list[Document]:
"""Load from file path."""
data = []
keys = []
wb = load_workbook(filename=self._file_path, read_only=True)
# loop over all sheets
for sheet in wb:
keys = []
if 'A1:A1' == sheet.calculate_dimension():
sheet.reset_dimensions()
for row in sheet.iter_rows(values_only=True):

View File

@ -24,3 +24,4 @@
- gaode
- wecom
- qrcode
- dingtalk

View File

@ -1,8 +1,7 @@
import os.path
from yaml import FullLoader, load
from core.tools.entities.user_entities import UserToolProvider
from core.utils.position_helper import get_position_map, sort_by_position_map
class BuiltinToolProviderSort:
@ -11,18 +10,14 @@ class BuiltinToolProviderSort:
@classmethod
def sort(cls, providers: list[UserToolProvider]) -> list[UserToolProvider]:
if not cls._position:
tmp_position = {}
file_path = os.path.join(os.path.dirname(__file__), '..', '_position.yaml')
with open(file_path) as f:
for pos, val in enumerate(load(f, Loader=FullLoader)):
tmp_position[val] = pos
cls._position = tmp_position
cls._position = get_position_map(os.path.join(os.path.dirname(__file__), '..'))
def sort_compare(provider: UserToolProvider) -> int:
def name_func(provider: UserToolProvider) -> str:
if provider.type == UserToolProvider.ProviderType.MODEL:
return cls._position.get(f'model.{provider.name}', 10000)
return cls._position.get(provider.name, 10000)
sorted_providers = sorted(providers, key=sort_compare)
return f'model.{provider.name}'
else:
return provider.name
sorted_providers = sort_by_position_map(cls._position, providers, name_func)
return sorted_providers

View File

@ -0,0 +1,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg fill="#4aa4f8" width="800px" height="800px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon" stroke="#4aa4f8">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
<g id="SVGRepo_iconCarrier"> <path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm227 385.3c-1 4.2-3.5 10.4-7 17.8h.1l-.4.7c-20.3 43.1-73.1 127.7-73.1 127.7s-.1-.2-.3-.5l-15.5 26.8h74.5L575.1 810l32.3-128h-58.6l20.4-84.7c-16.5 3.9-35.9 9.4-59 16.8 0 0-31.2 18.2-89.9-35 0 0-39.6-34.7-16.6-43.4 9.8-3.7 47.4-8.4 77-12.3 40-5.4 64.6-8.2 64.6-8.2S422 517 392.7 512.5c-29.3-4.6-66.4-53.1-74.3-95.8 0 0-12.2-23.4 26.3-12.3 38.5 11.1 197.9 43.2 197.9 43.2s-207.4-63.3-221.2-78.7c-13.8-15.4-40.6-84.2-37.1-126.5 0 0 1.5-10.5 12.4-7.7 0 0 153.3 69.7 258.1 107.9 104.8 37.9 195.9 57.3 184.2 106.7z"/> </g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,8 @@
from core.tools.provider.builtin.dingtalk.tools.dingtalk_group_bot import DingTalkGroupBotTool
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
class DingTalkProvider(BuiltinToolProviderController):
def _validate_credentials(self, credentials: dict) -> None:
DingTalkGroupBotTool()
pass

View File

@ -0,0 +1,13 @@
identity:
author: Bowen Liang
name: dingtalk
label:
en_US: DingTalk
zh_Hans: 钉钉
pt_BR: DingTalk
description:
en_US: DingTalk group robot
zh_Hans: 钉钉群机器人
pt_BR: DingTalk group robot
icon: icon.svg
credentials_for_provider:

View File

@ -0,0 +1,83 @@
import base64
import hashlib
import hmac
import logging
import time
import urllib.parse
from typing import Any, Union
import httpx
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
class DingTalkGroupBotTool(BuiltinTool):
def _invoke(self, user_id: str, tool_parameters: dict[str, Any]
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
"""
invoke tools
Dingtalk custom group robot API docs:
https://open.dingtalk.com/document/orgapp/custom-robot-access
"""
content = tool_parameters.get('content')
if not content:
return self.create_text_message('Invalid parameter content')
access_token = tool_parameters.get('access_token')
if not access_token:
return self.create_text_message('Invalid parameter access_token. '
'Regarding information about security details,'
'please refer to the DingTalk docs:'
'https://open.dingtalk.com/document/robots/customize-robot-security-settings')
sign_secret = tool_parameters.get('sign_secret')
if not sign_secret:
return self.create_text_message('Invalid parameter sign_secret. '
'Regarding information about security details,'
'please refer to the DingTalk docs:'
'https://open.dingtalk.com/document/robots/customize-robot-security-settings')
msgtype = 'text'
api_url = 'https://oapi.dingtalk.com/robot/send'
headers = {
'Content-Type': 'application/json',
}
params = {
'access_token': access_token,
}
self._apply_security_mechanism(params, sign_secret)
payload = {
"msgtype": msgtype,
"text": {
"content": content,
}
}
try:
res = httpx.post(api_url, headers=headers, params=params, json=payload)
if res.is_success:
return self.create_text_message("Text message sent successfully")
else:
return self.create_text_message(
f"Failed to send the text message, status code: {res.status_code}, response: {res.text}")
except Exception as e:
return self.create_text_message("Failed to send message to group chat bot. {}".format(e))
@staticmethod
def _apply_security_mechanism(params: dict[str, Any], sign_secret: str):
try:
timestamp = str(round(time.time() * 1000))
secret_enc = sign_secret.encode('utf-8')
string_to_sign = f'{timestamp}\n{sign_secret}'
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
params['timestamp'] = timestamp
params['sign'] = sign
except Exception:
msg = "Failed to apply security mechanism to the request."
logging.exception(msg)

View File

@ -0,0 +1,52 @@
identity:
name: dingtalk_group_bot
author: Bowen Liang
label:
en_US: Send Group Message
zh_Hans: 发送群消息
pt_BR: Send Group Message
icon: icon.svg
description:
human:
en_US: Sending a group message on DingTalk via the webhook of group bot
zh_Hans: 通过钉钉的群机器人webhook发送群消息
pt_BR: Sending a group message on DingTalk via the webhook of group bot
llm: A tool for sending messages to a chat group on DingTalk(钉钉) .
parameters:
- name: access_token
type: secret-input
required: true
label:
en_US: access token
zh_Hans: access token
pt_BR: access token
human_description:
en_US: access_token in the group robot webhook
zh_Hans: 群自定义机器人webhook中access_token字段的值
pt_BR: access_token in the group robot webhook
form: form
- name: sign_secret
type: secret-input
required: true
label:
en_US: secret key for signing
zh_Hans: 加签秘钥
pt_BR: secret key for signing
human_description:
en_US: secret key for signing
zh_Hans: 加签秘钥
pt_BR: secret key for signing
form: form
- name: content
type: string
required: true
label:
en_US: content
zh_Hans: 消息内容
pt_BR: content
human_description:
en_US: Content to sent to the group.
zh_Hans: 群消息文本
pt_BR: Content to sent to the group.
llm_description: Content of the message
form: llm

View File

@ -33,3 +33,8 @@ credentials_for_provider:
en_US: Please input your model
zh_Hans: 请输入你的模型名称
pt_BR: Please input your model
help:
en_US: The model name of the StableDiffusion server
zh_Hans: StableDiffusion服务器的模型名称
pt_BR: The model name of the StableDiffusion server
url: https://docs.dify.ai/tutorials/tool-configuration/stable-diffusion

View File

@ -131,7 +131,8 @@ class StableDiffusionTool(BuiltinTool):
negative_prompt=negative_prompt,
width=width,
height=height,
steps=steps)
steps=steps,
model=model)
return self.text2img(base_url=base_url,
lora=lora,
@ -139,7 +140,8 @@ class StableDiffusionTool(BuiltinTool):
negative_prompt=negative_prompt,
width=width,
height=height,
steps=steps)
steps=steps,
model=model)
def validate_models(self) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
"""
@ -197,7 +199,7 @@ class StableDiffusionTool(BuiltinTool):
def img2img(self, base_url: str, lora: str, image_binary: bytes,
prompt: str, negative_prompt: str,
width: int, height: int, steps: int) \
width: int, height: int, steps: int, model: str) \
-> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
"""
generate image
@ -213,7 +215,8 @@ class StableDiffusionTool(BuiltinTool):
"sampler_name": "Euler a",
"restore_faces": False,
"steps": steps,
"script_args": ["outpainting mk2"]
"script_args": ["outpainting mk2"],
"override_settings": {"sd_model_checkpoint": model}
}
if lora:
@ -236,7 +239,7 @@ class StableDiffusionTool(BuiltinTool):
except Exception as e:
return self.create_text_message('Failed to generate image')
def text2img(self, base_url: str, lora: str, prompt: str, negative_prompt: str, width: int, height: int, steps: int) \
def text2img(self, base_url: str, lora: str, prompt: str, negative_prompt: str, width: int, height: int, steps: int, model: str) \
-> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
"""
generate image
@ -253,6 +256,7 @@ class StableDiffusionTool(BuiltinTool):
draw_options['height'] = height
draw_options['steps'] = steps
draw_options['negative_prompt'] = negative_prompt
draw_options['override_settings']['sd_model_checkpoint'] = model
try:
url = str(URL(base_url) / 'sdapi' / 'v1' / 'txt2img')

View File

@ -0,0 +1,42 @@
import calendar
from datetime import datetime
from typing import Any, Union
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
class WeekdayTool(BuiltinTool):
def _invoke(self,
user_id: str,
tool_parameters: dict[str, Any],
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
"""
Calculate the day of the week for a given date
"""
year = tool_parameters.get('year')
month = tool_parameters.get('month')
day = tool_parameters.get('day')
date_obj = self.convert_datetime(year, month, day)
if not date_obj:
return self.create_text_message(f'Invalid date: Year {year}, Month {month}, Day {day}.')
weekday_name = calendar.day_name[date_obj.weekday()]
month_name = calendar.month_name[month]
readable_date = f"{month_name} {date_obj.day}, {date_obj.year}"
return self.create_text_message(f'{readable_date} is {weekday_name}.')
@staticmethod
def convert_datetime(year, month, day) -> datetime | None:
try:
# allowed range in datetime module
if not (year >= 1 and 1 <= month <= 12 and 1 <= day <= 31):
return None
year = int(year)
month = int(month)
day = int(day)
return datetime(year, month, day)
except ValueError:
return None

View File

@ -0,0 +1,42 @@
identity:
name: weekday
author: Bowen Liang
label:
en_US: Weekday Calculator
zh_Hans: 星期几计算器
description:
human:
en_US: A tool for calculating the weekday of a given date.
zh_Hans: 计算指定日期为星期几的工具。
llm: A tool for calculating the weekday of a given date by year, month and day.
parameters:
- name: year
type: number
required: true
form: llm
label:
en_US: Year
zh_Hans:
human_description:
en_US: Year
zh_Hans:
- name: month
type: number
required: true
form: llm
label:
en_US: Month
zh_Hans:
human_description:
en_US: Month
zh_Hans:
- name: day
type: number
required: true
form: llm
label:
en_US: day
zh_Hans:
human_description:
en_US: day
zh_Hans:

View File

@ -0,0 +1,70 @@
import logging
import os
from collections import OrderedDict
from collections.abc import Callable
from typing import Any, AnyStr
import yaml
def get_position_map(
folder_path: AnyStr,
file_name: str = '_position.yaml',
) -> dict[str, int]:
"""
Get the mapping from name to index from a YAML file
:param folder_path:
:param file_name: the YAML file name, default to '_position.yaml'
:return: a dict with name as key and index as value
"""
try:
position_file_name = os.path.join(folder_path, file_name)
if not os.path.exists(position_file_name):
return {}
with open(position_file_name, encoding='utf-8') as f:
positions = yaml.safe_load(f)
position_map = {}
for index, name in enumerate(positions):
if name and isinstance(name, str):
position_map[name.strip()] = index
return position_map
except:
logging.warning(f'Failed to load the YAML position file {folder_path}/{file_name}.')
return {}
def sort_by_position_map(
position_map: dict[str, int],
data: list[Any],
name_func: Callable[[Any], str],
) -> list[Any]:
"""
Sort the objects by the position map.
If the name of the object is not in the position map, it will be put at the end.
:param position_map: the map holding positions in the form of {name: index}
:param name_func: the function to get the name of the object
:param data: the data to be sorted
:return: the sorted objects
"""
if not position_map or not data:
return data
return sorted(data, key=lambda x: position_map.get(name_func(x), float('inf')))
def sort_to_dict_by_position_map(
position_map: dict[str, int],
data: list[Any],
name_func: Callable[[Any], str],
) -> OrderedDict[str, Any]:
"""
Sort the objects into a ordered dict by the position map.
If the name of the object is not in the position map, it will be put at the end.
:param position_map: the map holding positions in the form of {name: index}
:param name_func: the function to get the name of the object
:param data: the data to be sorted
:return: an OrderedDict with the sorted pairs of name and object
"""
sorted_items = sort_by_position_map(position_map, data, name_func)
return OrderedDict([(name_func(item), item) for item in sorted_items])

View File

@ -26,5 +26,6 @@ def handle(sender, **kwargs):
conversation.name = name
except:
pass
db.session.merge(conversation)
db.session.commit()

View File

@ -726,6 +726,7 @@ class MessageFile(db.Model):
created_by = db.Column(UUID, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
class MessageAnnotation(db.Model):
__tablename__ = 'message_annotations'
__table_args__ = (

View File

@ -11,7 +11,7 @@ flask-cors~=4.0.0
gunicorn~=21.2.0
gevent~=23.9.1
langchain==0.0.250
openai~=1.3.6
openai~=1.13.3
tiktoken~=0.5.2
psycopg2-binary~=2.9.6
pycryptodome==3.19.1

View File

@ -44,6 +44,10 @@ def clean_dataset_task(dataset_id: str, tenant_id: str, indexing_technique: str,
documents = db.session.query(Document).filter(Document.dataset_id == dataset_id).all()
segments = db.session.query(DocumentSegment).filter(DocumentSegment.dataset_id == dataset_id).all()
if documents is None or len(documents) == 0:
logging.info(click.style('No documents found for dataset: {}'.format(dataset_id), fg='green'))
return
index_processor = IndexProcessorFactory(doc_form).init_index_processor()
index_processor.clean(dataset, None)

View File

@ -2,7 +2,7 @@ version: '3.1'
services:
# API service
api:
image: langgenius/dify-api:0.5.8
image: langgenius/dify-api:0.5.9
restart: always
environment:
# Startup mode, 'api' starts the API server.
@ -135,7 +135,7 @@ services:
# worker service
# The Celery worker for processing the queue.
worker:
image: langgenius/dify-api:0.5.8
image: langgenius/dify-api:0.5.9
restart: always
environment:
# Startup mode, 'worker' starts the Celery worker for processing the queue.
@ -206,7 +206,7 @@ services:
# Frontend web application.
web:
image: langgenius/dify-web:0.5.8
image: langgenius/dify-web:0.5.9
restart: always
environment:
EDITION: SELF_HOSTED

View File

@ -178,10 +178,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
title="Request"
tag="POST"
label="/datasets/{dataset_id}/document/create_by_file"
targetCode={`curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
targetCode={`curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
>
```bash {{ title: 'cURL' }}
curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \
curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \
--header 'Authorization: Bearer {api_key}' \
--form 'data="{\"name\":\"Dify\",\"indexing_technique\":\"high_quality\",\"process_rule\":{\"rules\":{\"pre_processing_rules\":[{\"id\":\"remove_extra_spaces\",\"enabled\":true},{\"id\":\"remove_urls_emails\",\"enabled\":true}],\"segmentation\":{\"separator\":\"###\",\"max_tokens\":500}},\"mode\":\"custom\"}}";type=text/plain' \
--form 'file=@"/path/to/file"'
@ -491,10 +491,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
title="Request"
tag="POST"
label="/datasets/{dataset_id}/documents/{document_id}/update_by_file"
targetCode={`curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"name":"Dify","indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
targetCode={`curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"name":"Dify","indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
>
```bash {{ title: 'cURL' }}
curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \
curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \
--header 'Authorization: Bearer {api_key}' \
--form 'data="{\"name\":\"Dify\",\"indexing_technique\":\"high_quality\",\"process_rule\":{\"rules\":{\"pre_processing_rules\":[{\"id\":\"remove_extra_spaces\",\"enabled\":true},{\"id\":\"remove_urls_emails\",\"enabled\":true}],\"segmentation\":{\"separator\":\"###\",\"max_tokens\":500}},\"mode\":\"custom\"}}";type=text/plain' \
--form 'file=@"/path/to/file"'

View File

@ -76,7 +76,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
targetCode={`curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_text' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"name": "text","text": "text","indexing_technique": "high_quality","process_rule": {"mode": "automatic"}}'`}
>
```bash {{ title: 'cURL' }}
curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_text' \
curl --location --request --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_text' \
--header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \
--data-raw '{
@ -178,10 +178,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
title="Request"
tag="POST"
label="/datasets/{dataset_id}/document/create_by_file"
targetCode={`curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
targetCode={`curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
>
```bash {{ title: 'cURL' }}
curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \
curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/create_by_file' \
--header 'Authorization: Bearer {api_key}' \
--form 'data="{\"name\":\"Dify\",\"indexing_technique\":\"high_quality\",\"process_rule\":{\"rules\":{\"pre_processing_rules\":[{\"id\":\"remove_extra_spaces\",\"enabled\":true},{\"id\":\"remove_urls_emails\",\"enabled\":true}],\"segmentation\":{\"separator\":\"###\",\"max_tokens\":500}},\"mode\":\"custom\"}}";type=text/plain' \
--form 'file=@"/path/to/file"'
@ -491,10 +491,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
title="Request"
tag="POST"
label="/datasets/{dataset_id}/documents/{document_id}/update_by_file"
targetCode={`curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"name":"Dify","indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
targetCode={`curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \\\n--header 'Authorization: Bearer {api_key}' \\\n--form 'data="{"name":"Dify","indexing_technique":"high_quality","process_rule":{"rules":{"pre_processing_rules":[{"id":"remove_extra_spaces","enabled":true},{"id":"remove_urls_emails","enabled":true}],"segmentation":{"separator":"###","max_tokens":500}},"mode":"custom"}}";type=text/plain' \\\n--form 'file=@"/path/to/file"'`}
>
```bash {{ title: 'cURL' }}
curl --location POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \
curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/document/{document_id}/create_by_file' \
--header 'Authorization: Bearer {api_key}' \
--form 'data="{\"name\":\"Dify\",\"indexing_technique\":\"high_quality\",\"process_rule\":{\"rules\":{\"pre_processing_rules\":[{\"id\":\"remove_extra_spaces\",\"enabled\":true},{\"id\":\"remove_urls_emails\",\"enabled\":true}],\"segmentation\":{\"separator\":\"###\",\"max_tokens\":500}},\"mode\":\"custom\"}}";type=text/plain' \
--form 'file=@"/path/to/file"'

View File

@ -162,14 +162,17 @@ export function Markdown(props: { content: string; className?: string }) {
const image = node.children[0]
return (
// eslint-disable-next-line @next/next/no-img-element
<img
src={image.properties.src}
width={250}
height={250}
className="max-w-full h-auto align-middle border-none rounded-lg shadow-md hover:shadow-lg transition-shadow duration-300 ease-in-out mt-2 mb-2"
alt={image.properties.alt}
/>
<>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={image.properties.src}
width={250}
height={250}
className="max-w-full h-auto align-middle border-none rounded-lg shadow-md hover:shadow-lg transition-shadow duration-300 ease-in-out mt-2 mb-2"
alt={image.properties.alt}
/>
<p>{paragraph.children.slice(1)}</p>
</>
)
}
return <p>{paragraph.children}</p>

View File

@ -42,13 +42,13 @@ The text generation application offers non-session support and is ideal for tran
### Request Body
<Properties>
<Property name='query' type='string' key='query'>
User Input/Question content
</Property>
<Property name='inputs' type='object' key='inputs'>
Allows the entry of various variable values defined by the App.
The `inputs` parameter contains multiple key/value pairs, with each key corresponding to a specific variable and each value being the specific value for that variable.
The text generation application requires at least one key/value pair to be inputted.
- `query` (string) Required
The input text, the content to be processed.
</Property>
<Property name='response_mode' type='string' key='response_mode'>
The mode of response return, supporting:
@ -138,14 +138,16 @@ The text generation application offers non-session support and is ideal for tran
</Col>
<Col sticky>
<CodeGroup title="Request" tag="POST" label="/completion-messages" targetCode={`curl -X POST '${props.appDetail.api_base_url}/completion-messages' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": ${JSON.stringify(props.inputs)},\n "response_mode": "streaming"\n "user": "abc-123"\n}'\n`}>
<CodeGroup title="Request" tag="POST" label="/completion-messages" targetCode={`curl -X POST '${props.appDetail.api_base_url}/completion-messages' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": {"query": "Hello, world!"},\n "response_mode": "streaming"\n "user": "abc-123"\n}'\n`}>
```bash {{ title: 'cURL' }}
curl -X POST '${props.appDetail.api_base_url}/completion-messages' \
--header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"inputs": {},
"inputs": {
"query": "Hello, world!"
},
"response_mode": "streaming",
"user": "abc-123"
}'

View File

@ -41,13 +41,12 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
### Request Body
<Properties>
<Property name='query' type='string' key='query'>
用户输入/提问内容。
</Property>
<Property name='inputs' type='object' key='inputs'>
(选填)允许传入 App 定义的各变量值。
inputs 参数包含了多组键值对Key/Value pairs每组的键对应一个特定变量每组的值则是该变量的具体值。
文本生成型应用要求至少传入一组键值对。
- `query` (string) 必填
用户输入的文本内容。
</Property>
<Property name='response_mode' type='string' key='response_mode'>
- `streaming` 流式模式(推荐)。基于 SSE**[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)**)实现类似打字机输出方式的流式返回。
@ -140,18 +139,21 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
</Col>
<Col sticky>
<CodeGroup title="Request" tag="POST" label="/completion-messages" targetCode={`curl -X POST '${props.appDetail.api_base_url}/completion-messages' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": ${JSON.stringify(props.inputs)},\n "response_mode": "streaming",\n "user": "abc-123"\n}'\n`}>
<CodeGroup title="Request" tag="POST" label="/completion-messages" targetCode={`curl -X POST '${props.appDetail.api_base_url}/completion-messages' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": {"query": "Hello, world!"},\n "response_mode": "streaming"\n "user": "abc-123"\n}'\n`}>
```bash {{ title: 'cURL' }}
curl -X POST '${props.appDetail.api_base_url}/completion-messages' \
--header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"inputs": {},
"inputs": {
"query": "Hello, world!"
},
"response_mode": "streaming",
"user": "abc-123"
}'
```
```
</CodeGroup>
### blocking

View File

@ -205,7 +205,7 @@ const translation = {
intendedAudience: 'Who is the intended audience?',
intendedAudiencePlaceHolder: 'e.g. Student',
solveProblem: 'What problems do they hope AI can solve for them?',
solveProblemPlaceHolder: 'e.g. Assessing academic performance',
solveProblemPlaceHolder: 'e.g. Extract insights and summarize information from long reports and articles',
generate: 'Generate',
audiencesRequired: 'Audiences required',
problemRequired: 'Problem required',

View File

@ -0,0 +1,87 @@
const translation = {
title: 'Annotations',
name: 'Réponse à l\'Annotation',
editBy: 'Réponse éditée par {{author}}',
noData: {
title: 'Aucune annotation',
description: 'Vous pouvez modifier les annotations en déboguant l\'application, ou importer des annotations en masse ici pour une réponse de haute qualité.',
},
table: {
header: {
question: 'question',
answer: 'réponse',
createdAt: 'créé à',
hits: 'clics',
actions: 'actions',
addAnnotation: 'Ajouter une Annotation',
bulkImport: 'Importation en Vrac',
bulkExport: 'Exportation en Vrac',
clearAll: 'Effacer toutes les annotations',
},
},
editModal: {
title: 'Modifier la réponse à l\'annotation',
queryName: 'Requête de l\'utilisateur',
answerName: 'Bot conteur',
yourAnswer: 'Votre réponse',
answerPlaceholder: 'Tapez votre réponse ici',
yourQuery: 'Votre requête',
queryPlaceholder: 'Tapez votre requête ici',
removeThisCache: 'Supprimez cette Annotation',
createdAt: 'Créé à',
},
addModal: {
title: 'Ajouter une réponse d\'annotation',
queryName: 'Question',
answerName: 'Réponse',
answerPlaceholder: 'Tapez la réponse ici',
queryPlaceholder: 'Tapez la requête ici',
createNext: 'Ajoutez une autre réponse annotée',
},
batchModal: {
title: 'Importation en masse',
csvUploadTitle: 'Glissez et déposez votre fichier CSV ici, ou',
browse: 'parcourir',
tip: 'Le fichier CSV doit se conformer à la structure suivante :',
question: 'question',
answer: 'réponse',
contentTitle: 'contenu du bloc',
content: 'contenu',
template: 'Téléchargez le modèle ici',
cancel: 'Annuler',
run: 'Exécuter le lot',
runError: 'L\'exécution du lot a échoué',
processing: 'Dans le traitement par lots',
completed: 'Importation terminée',
error: 'Erreur d\'Importation',
ok: 'D\'accord',
},
errorMessage: {
answerRequired: 'Une réponse est requise',
queryRequired: 'La question est requise',
},
viewModal: {
annotatedResponse: 'Réponse à l\'annotation',
hitHistory: 'Historique des coups',
hit: 'Clic',
hits: 'Clics',
noHitHistory: 'Aucun historique de recherche',
},
hitHistoryTable: {
query: 'Requête',
match: 'Correspondance',
response: 'Réponse',
source: 'Source',
score: 'Score',
time: 'Temps',
},
initSetup: {
title: 'Réponse d\'Annotation Configuration Initiale',
configTitle: 'Configuration de la Réponse d\'Annotation',
confirmBtn: 'Enregistrer & Activer',
configConfirmBtn: 'Enregistrer',
},
embeddingModelSwitchTip: 'Modèle de vectorisation de texte d\'annotation, changer de modèles entraînera une ré-intégration, ce qui entraînera des coûts supplémentaires.',
}
export default translation

82
web/i18n/fr-FR/app-api.ts Normal file
View File

@ -0,0 +1,82 @@
const translation = {
apiServer: 'Serveur API',
apiKey: 'Clé API',
status: 'Statut',
disabled: 'Désactivé',
ok: 'En Service',
copy: 'Copier',
copied: 'Copié',
play: 'Jouer',
pause: 'Pause',
playing: 'Jouant',
merMaind: {
rerender: 'Refaire Rerendu',
},
never: 'Jamais',
apiKeyModal: {
apiSecretKey: 'Clé secrète de l\'API',
apiSecretKeyTips: 'Pour prévenir l\'abus de l\'API, protégez votre clé API. Évitez de l\'utiliser comme du texte brut dans le code front-end. :)',
createNewSecretKey: 'Créer une nouvelle clé secrète',
secretKey: 'Clé Secrète',
created: 'CRÉÉ',
lastUsed: 'DERNIÈRE UTILISATION',
generateTips: 'Gardez cette clé dans un endroit sûr et accessible.',
},
actionMsg: {
deleteConfirmTitle: 'Supprimer cette clé secrète ?',
deleteConfirmTips: 'Cette action ne peut pas être annulée.',
ok: 'D\'accord',
},
completionMode: {
title: 'API de l\'application Completion',
info: 'Pour une génération de texte de haute qualité, telle que des articles, des résumés et des traductions, utilisez l\'API completion-messages avec l\'entrée de l\'utilisateur. La génération de texte repose sur les paramètres du modèle et les modèles de prompt définis dans',
createCompletionApi: 'Créer un Message de Fin',
createCompletionApiTip: 'Créez un message de fin pour soutenir le mode question-réponse.',
inputsTips: '(Facultatif) Fournissez des champs de saisie utilisateur sous forme de paires clé-valeur, correspondant aux variables dans Prompt Eng. La clé est le nom de la variable, la valeur est la valeur du paramètre. Si le type de champ est Sélection, la valeur sou',
queryTips: 'Contenu du texte saisi par l\'utilisateur.',
blocking: 'Type de blocage, en attente de l\'exécution pour terminer et renvoyer les résultats. (Les demandes peuvent être interrompues si le processus est long)',
streaming: 'retours en continu. Mise en œuvre de retours en continu basée sur SSE (Server-Sent Events).',
messageFeedbackApi: 'Retour de message (j\'aime)',
messageFeedbackApiTip: 'Évaluez les messages reçus au nom des utilisateurs finaux avec des likes ou des dislikes. Ces données sont visibles sur la page Logs & Annotations et sont utilisées pour le réglage fin des modèles futurs.',
messageIDTip: 'ID de message',
ratingTip: 'aimer ou ne pas aimer, null est annuler',
parametersApi: 'Obtenir des informations sur les paramètres de l\'application',
parametersApiTip: 'Récupérer les paramètres d\'entrée configurés, y compris les noms de variables, les noms de champs, les types et les valeurs par défaut. Généralement utilisé pour afficher ces champs dans un formulaire ou pour remplir les valeurs par défaut après le charg',
},
chatMode: {
title: 'API de l\'application de chat',
info: 'Pour des applications conversationnelles polyvalentes utilisant un format Q&R, appelez l\'API de chat-messages pour initier le dialogue. Maintenez les conversations en cours en passant l\'ID de conversation retourné. Les paramètres de réponse et les modèles dépendent des paramètres de',
createChatApi: 'Créer un message de chat',
createChatApiTip: 'Créez un nouveau message de conversation ou continuez un dialogue existant.',
inputsTips: '(Facultatif) Fournir des champs de saisie utilisateur sous forme de paires clé-valeur, correspondant aux variables dans Prompt Eng. La clé est le nom de la variable, la valeur est la valeur du paramètre. Si le type de champ est Sélection, la valeur soumise',
queryTips: 'Contenu de la question/saisie de l\'utilisateur',
blocking: 'Type de blocage, en attente de l\'exécution pour terminer et renvoyer les résultats. (Les demandes peuvent être interrompues si le processus est long)',
streaming: 'retours en continu. Mise en œuvre de retours en continu basée sur SSE (Server-Sent Events).',
conversationIdTip: '(Optional) Conversation ID: leave empty for first-time conversation; pass conversation_id from context to continue dialogue.',
messageFeedbackApi: 'Message de retour d\'information de l\'utilisateur du terminal, comme',
messageFeedbackApiTip: 'Évaluez les messages reçus au nom des utilisateurs finaux avec des likes ou des dislikes. Ces données sont visibles sur la page Logs & Annotations et sont utilisées pour l\'ajustement futur du modèle.',
messageIDTip: 'ID de message',
ratingTip: 'aimer ou ne pas aimer, null est annuler',
chatMsgHistoryApi: 'Obtenez le message de l\'historique de chat',
chatMsgHistoryApiTip: 'La première page renvoie la dernière `limit` bar, qui est en ordre inverse.',
chatMsgHistoryConversationIdTip: 'ID de conversation',
chatMsgHistoryFirstId: 'ID du premier enregistrement de chat sur la page actuelle. La valeur par défaut est aucune.',
chatMsgHistoryLimit: 'Combien de chats sont renvoyés en une seule demande',
conversationsListApi: 'Obtenir la liste des conversations',
conversationsListApiTip: 'Obtient la liste des sessions de l\'utilisateur actuel. Par défaut, les 20 dernières sessions sont renvoyées.',
conversationsListFirstIdTip: 'L\'ID du dernier enregistrement sur la page actuelle, par défaut aucun.',
conversationsListLimitTip: 'Combien de chats sont renvoyés dans une seule requête',
conversationRenamingApi: 'Renommage de la conversation',
conversationRenamingApiTip: 'Renommez les conversations ; le nom est affiché dans les interfaces client multi-session.',
conversationRenamingNameTip: 'Nouveau nom',
parametersApi: 'Obtenir des informations sur les paramètres de l\'application',
parametersApiTip: 'Récupérer les paramètres d\'entrée configurés, y compris les noms de variables, les noms de champs, les types et les valeurs par défaut. Typiquement utilisé pour afficher ces champs dans un formulaire ou pour remplir les valeurs par défaut après le chargement du',
},
develop: {
requestBody: 'Corps de la Requête',
pathParams: 'Params de chemin',
query: 'Requête',
},
}
export default translation

409
web/i18n/fr-FR/app-debug.ts Normal file
View File

@ -0,0 +1,409 @@
const translation = {
pageTitle: {
line1: 'INVITATION',
line2: 'Ingénierie',
},
orchestrate: 'Orchestrer',
promptMode: {
simple: 'Passez en Mode Expert pour modifier l\'intégralité du PROMPT',
advanced: 'Mode Expert',
switchBack: 'Revenir en arrière',
advancedWarning: {
title: 'Vous êtes passé en Mode Expert, et une fois que vous modifiez le PROMPT, vous NE POUVEZ PAS revenir au mode basique.',
description: 'En mode Expert, vous pouvez modifier l\'intégralité du PROMPT.',
learnMore: 'En savoir plus',
ok: 'D\'accord',
},
operation: {
addMessage: 'Ajouter un message',
},
contextMissing: 'Le composant de contexte est manquant, l\'efficacité de la suggestion peut ne pas être bonne.',
},
operation: {
applyConfig: 'Publier',
resetConfig: 'Réinitialiser',
debugConfig: 'Déboguer',
addFeature: 'Ajouter une fonctionnalité',
automatic: 'Automatique',
stopResponding: 'Arrêtez de répondre',
agree: 'comme',
disagree: 'déteste',
cancelAgree: 'Annuler comme',
cancelDisagree: 'Annuler le dislike',
userAction: 'Utilisateur',
},
notSetAPIKey: {
title: 'La clé du fournisseur LLM n\'a pas été définie',
trailFinished: 'Parcours terminé',
description: 'La clé du fournisseur LLM n\'a pas été définie, et elle doit être définie avant le débogage.',
settingBtn: 'Aller aux paramètres',
},
trailUseGPT4Info: {
title: 'Ne prend pas en charge gpt-4 pour le moment',
description: 'Utilisez gpt-4, veuillez définir la clé API.',
},
feature: {
groupChat: {
title: 'Amélioration de chat',
description: 'Ajouter des paramètres de pré-conversation pour les applications peut améliorer l\'expérience utilisateur.',
},
groupExperience: {
title: 'Amélioration de l\'expérience',
},
conversationOpener: {
title: 'Convertisseurs de conversation',
description: 'Dans une application de chat, la première phrase que l\'IA prononce activement à l\'utilisateur est généralement utilisée comme message de bienvenue.',
},
suggestedQuestionsAfterAnswer: {
title: 'Suivi',
description: 'La configuration de la suggestion des prochaines questions peut offrir aux utilisateurs une meilleure discussion.',
resDes: '3 suggestions pour la prochaine question de l\'utilisateur.',
tryToAsk: 'Essayez de demander',
},
moreLikeThis: {
title: 'Plus comme ça',
description: 'Générez plusieurs textes à la fois, puis modifiez et continuez à générer',
generateNumTip: 'Nombre de chaque temps généré',
tip: 'L\'utilisation de cette fonctionnalité entraînera un surcoût de tokens supplémentaires',
},
speechToText: {
title: 'Discours en Texte',
description: 'Une fois activé, vous pouvez utiliser l\'entrée vocale.',
resDes: 'La saisie vocale est activée',
},
textToSpeech: {
title: 'Texte à la parole',
description: 'Une fois activé, le texte peut être converti en parole.',
resDes: 'La Texte à Audio est activée',
},
citation: {
title: 'Citations et Attributions',
description: 'Une fois activé, affichez le document source et la section attribuée du contenu généré.',
resDes: 'Les citations et attributions sont activées',
},
annotation: {
title: 'Réponse d\'Annotation',
description: 'Vous pouvez manuellement ajouter une réponse de haute qualité au cache pour une correspondance prioritaire avec des questions d\'utilisateur similaires.',
resDes: 'La réponse d\'annotation est activée',
scoreThreshold: {
title: 'Seuil de Score',
description: 'Utilisé pour définir le seuil de similarité pour la réponse d\'annotation.',
easyMatch: 'Correspondance Facile',
accurateMatch: 'Correspondance précise',
},
matchVariable: {
title: 'Correspondance de Variable',
choosePlaceholder: 'Choisissez la variable correspondante',
},
cacheManagement: 'Annotations',
cached: 'Annoté',
remove: 'Supprimer',
removeConfirm: 'Supprimer cette annotation ?',
add: 'Ajouter une annotation',
edit: 'Modifier l\'annotation',
},
dataSet: {
title: 'Contexte',
noData: 'Vous pouvez importer des Connaissances comme contexte',
words: 'Mots',
textBlocks: 'Blocs de texte',
selectTitle: 'Sélectionnez la connaissance de référence',
selected: 'Connaissance sélectionnée',
noDataSet: 'Aucune connaissance trouvée',
toCreate: 'Aller à créer',
notSupportSelectMulti: 'Actuellement, ne prend en charge qu\'une seule Connaissance',
queryVariable: {
title: 'Variable de requête',
tip: 'Cette variable sera utilisée comme entrée de requête pour la récupération du contexte, obtenant des informations contextuelles liées à l\'entrée de cette variable.',
choosePlaceholder: 'Choisissez la variable de requête',
noVar: 'Aucune variable',
noVarTip: 'veuillez créer une variable sous la section Variables',
unableToQueryDataSet: 'Impossible de questionner la Connaissance',
unableToQueryDataSetTip: 'Impossible d\'interroger la Connaissance avec succès, veuillez choisir une variable de requête de contexte dans la section contexte.',
ok: 'D\'accord',
contextVarNotEmpty: 'la variable de requête de contexte ne peut pas être vide',
deleteContextVarTitle: 'Supprimer la variable "{{varName}}" ?',
deleteContextVarTip: 'Cette variable a été définie comme une variable de requête de contexte, et sa suppression affectera l\'utilisation normale de la Connaissance. Si vous devez toujours la supprimer, veuillez la re-sélectionner dans la section contexte.',
},
},
tools: {
title: 'Outils',
tips: 'Les outils fournissent une méthode d\'appel API standard, prenant en compte les entrées de l\'utilisateur ou des variables comme paramètres de requête pour interroger des données externes en tant que contexte.',
toolsInUse: '{{count}} outils en usage',
modal: {
title: 'Outil',
toolType: {
title: 'Type d\'outil',
placeholder: 'Veuillez sélectionner le type d\'outil',
},
name: {
title: 'Nom',
placeholder: 'Veuillez entrer le nom',
},
variableName: {
title: 'Nom de la Variable',
placeholder: 'Veuillez entrer le nom de la variable',
},
},
},
conversationHistory: {
title: 'Historique de Conversation',
description: 'Définir les noms de préfixe pour les rôles de conversation',
tip: 'L\'historique de conversation n\'est pas activé, veuillez ajouter <histories> dans le prompt ci-dessus.',
learnMore: 'En savoir plus',
editModal: {
title: 'Modifier les noms de rôles de conversation',
userPrefix: 'Préfixe utilisateur',
assistantPrefix: 'Préfixe de l\'assistant',
},
},
toolbox: {
title: 'BOÎTE À OUTILS',
},
moderation: {
title: 'Modération de contenu',
description: 'Sécurisez la sortie du modèle en utilisant l\'API de modération ou en conservant une liste de mots sensibles.',
allEnabled: 'Contenu Entrant/Sortant Activé',
inputEnabled: 'Contenu Activé',
outputEnabled: 'Contenu de SORTIE activé',
modal: {
title: 'Paramètres de modération de contenu',
provider: {
title: 'Fournisseur',
openai: 'Modération OpenAI',
openaiTip: {
prefix: 'La modération d\'OpenAI nécessite une clé API OpenAI configurée dans le',
suffix: '.',
},
keywords: 'Mots-clés',
},
keywords: {
tip: 'Un par ligne, séparés par des sauts de ligne. Jusqu\'à 100 caractères par ligne.',
placeholder: 'Un par ligne, séparé par des sauts de ligne',
line: 'Ligne',
},
content: {
input: 'Modérer le contenu INPUT',
output: 'Modérer le contenu de SORTIE',
preset: 'Réponses préétablies',
placeholder: 'Contenu des réponses prédéfinies ici',
condition: 'Contenu MODÉRÉ pour INPUT et OUTPUT activé au moins une fois',
fromApi: 'Les réponses prédéfinies sont renvoyées par l\'API',
errorMessage: 'Les réponses prédéfinies ne peuvent pas être vides',
supportMarkdown: 'Prise en charge de Markdown',
},
openaiNotConfig: {
before: 'La modération d\'OpenAI nécessite une clé API OpenAI configurée dans le',
after: 'Sorry, but you didn\'t provide a text to translate. Could you please provide the text?',
},
},
},
},
automatic: {
title: 'Orchestration automatique d\'application',
description: 'Décrivez votre scénario, Dify orchestrera une application pour vous.',
intendedAudience: 'Qui est le public cible ?',
intendedAudiencePlaceHolder: 'par exemple. Étudiant',
solveProblem: 'Quels problèmes espèrent-ils que l\'IA peut résoudre pour eux ?',
solveProblemPlaceHolder: 'par exemple, Évaluation des performances académiques',
generate: 'Générer',
audiencesRequired: 'Audiences requises',
problemRequired: 'Problème requis',
resTitle: 'Nous avons orchestré l\'application suivante pour vous.',
apply: 'Appliquez cette orchestration',
noData: 'Décrivez votre cas d\'utilisation sur la gauche, l\'aperçu de l\'orchestration s\'affichera ici.',
loading: 'Orchestration de l\'application pour vous...',
overwriteTitle: 'Remplacer la configuration existante ?',
overwriteMessage: 'L\'application de cette orchestration remplacera la configuration existante.',
},
resetConfig: {
title: 'Confirmer la réinitialisation ?',
message:
'Réinitialiser supprime les modifications, en restaurant la dernière configuration publiée.',
},
errorMessage: {
nameOfKeyRequired: 'name of the key: {{key}} required',
valueOfVarRequired: 'La valeur de {{key}} ne peut pas être vide',
queryRequired: 'Le texte de la requête est requis.',
waitForResponse:
'Veuillez attendre que la réponse au message précédent soit terminée.',
waitForBatchResponse:
'Veuillez attendre que la réponse à la tâche en lot soit terminée.',
notSelectModel: 'Veuillez choisir un modèle',
waitForImgUpload: 'Veuillez attendre que l\'image soit téléchargée',
},
chatSubTitle: 'Instructions',
completionSubTitle: 'Indicatif de Prompt',
promptTip:
'Les prompts guident les réponses de l\'IA avec des instructions et des contraintes. Insérez des variables comme {{input}}. Ce prompt ne sera pas visible pour les utilisateurs.',
formattingChangedTitle: 'Formatage modifié',
formattingChangedText:
'La modification du formatage réinitialisera la zone de débogage, êtes-vous sûr ?',
variableTitle: 'Variables',
variableTip:
'Les utilisateurs remplissent des variables dans un formulaire, remplaçant automatiquement les variables dans le prompt.',
notSetVar: 'Les variables permettent aux utilisateurs d\'introduire des mots de prompt ou des remarques d\'ouverture lors du remplissage des formulaires. Vous pouvez essayer de saisir "{{input}}" dans les mots de prompt.',
autoAddVar: 'Des variables indéfinies référencées dans le pre-prompt, voulez-vous les ajouter dans le formulaire d\'entrée de l\'utilisateur ?',
variableTable: {
key: 'Clé Variable',
name: 'Nom du champ d\'entrée de l\'utilisateur',
optional: 'Facultatif',
type: 'Type d\'Entrée',
action: 'Actions',
typeString: 'Chaîne',
typeSelect: 'Sélectionner',
},
varKeyError: {
canNoBeEmpty: 'La clé variable ne peut pas être vide',
tooLong: 'Variable key: {{key}} too length. Can not be longer then 30 characters',
notValid: 'Variable key: {{key}} is invalid. Can only contain letters, numbers, and underscores',
notStartWithNumber: 'Variable key: {{key}} can not start with a number',
keyAlreadyExists: 'Variable key: :{{key}} already exists',
},
otherError: {
promptNoBeEmpty: 'Le prompt ne peut pas être vide',
historyNoBeEmpty: 'L\'historique de la conversation doit être défini dans le prompt',
queryNoBeEmpty: 'La requête doit être définie dans le prompt',
},
variableConig: {
modalTitle: 'Paramètres du champ',
description: 'Paramètre pour la variable {{varName}}',
fieldType: 'Type de champ',
string: 'Texte Court',
paragraph: 'Paragraphe',
select: 'Sélectionner',
notSet: 'Non défini, essayez de taper {{input}} dans l\'invite de préfixe',
stringTitle: 'Options de la boîte de texte du formulaire',
maxLength: 'Longueur maximale',
options: 'Options',
addOption: 'Ajouter une option',
apiBasedVar: 'Variable basée sur l\'API',
},
vision: {
name: 'Vision',
description: 'Enable Vision permettra au modèle de prendre des images et de répondre à des questions à leur sujet.',
settings: 'Paramètres',
visionSettings: {
title: 'Paramètres de Vision',
resolution: 'Résolution',
resolutionTooltip: `low res will allow model receive a low-res 512 x 512 version of the image, and represent the image with a budget of 65 tokens. This allows the API to return faster responses and consume fewer input tokens for use cases that do not require high detail.
\n
high res will first allows the model to see the low res image and then creates detailed crops of input images as 512px squares based on the input image size. Each of the detailed crops uses twice the token budget for a total of 129 tokens.`,
high: 'Élevé',
low: 'Faible',
uploadMethod: 'Méthode de Téléchargement',
both: 'Les deux',
localUpload: 'Téléchargement Local',
url: 'URL',
uploadLimit: 'Limite de téléchargement',
},
},
voice: {
name: 'Voix',
defaultDisplay: 'Voix par défaut',
description: 'Paramètres de la voix de synthèse vocale',
settings: 'Paramètres',
voiceSettings: {
title: 'Paramètres de voix',
language: 'Langue',
resolutionTooltip: 'Support de la langue pour la voix de synthèse de texte.',
voice: 'Voix',
},
},
openingStatement: {
title: 'Ouverture de Conversation',
add: 'Ajouter',
writeOpner: 'Écrire l\'introduction',
placeholder: 'Rédigez votre message d\'ouverture ici, vous pouvez utiliser des variables, essayez de taper {{variable}}.',
openingQuestion: 'Questions d\'ouverture',
noDataPlaceHolder:
'Commencer la conversation avec l\'utilisateur peut aider l\'IA à établir une connexion plus proche avec eux dans les applications conversationnelles.',
varTip: 'Vous pouvez utiliser des variables, essayez de taper {{variable}}',
tooShort: 'Au moins 20 mots de l\'invite initiale sont requis pour générer des remarques d\'ouverture pour la conversation.',
notIncludeKey: 'The initial prompt does not include the variable: {{key}}. Please add it to the initial prompt.',
},
modelConfig: {
model: 'Modèle',
setTone: 'Définir le ton des réponses',
title: 'Modèle et Paramètres',
modeType: {
chat: 'Discussion',
completion: 'Complet',
},
},
inputs: {
title: 'Déboguer et Aperçu',
noPrompt: 'Essayez d\'écrire une proposition dans l\'entrée pré-proposition',
userInputField: 'Champ de saisie utilisateur',
noVar: 'Remplissez la valeur de la variable, qui sera automatiquement remplacée dans le mot d\'invite chaque fois qu\'une nouvelle session est démarrée.',
chatVarTip:
'Remplissez la valeur de la variable, qui sera automatiquement remplacée dans le mot d\'invite chaque fois qu\'une nouvelle session est démarrée',
completionVarTip:
'Remplissez la valeur de la variable, qui sera automatiquement remplacée dans les mots de l\'invite chaque fois qu\'une question est soumise.',
previewTitle: 'Aperçu de la prompte',
queryTitle: 'Contenu de la requête',
queryPlaceholder: 'Veuillez entrer le texte de la demande.',
run: 'EXÉCUTER',
},
result: 'Texte de sortie',
datasetConfig: {
settingTitle: 'Paramètres de récupération',
retrieveOneWay: {
title: 'Récupération N-vers-1',
description: 'En fonction de l\'intention de l\'utilisateur et des descriptions de Connaissance, l\'Agent sélectionne de manière autonome la meilleure Connaissance pour interroger. Idéal pour les applications avec une Connaissance distincte et limitée.',
},
retrieveMultiWay: {
title: 'Récupération multi-chemins',
description: 'En fonction de l\'intention de l\'utilisateur, interroge toutes les connaissances, récupère le texte pertinent de plusieurs sources et sélectionne les meilleurs résultats correspondant à la requête de l\'utilisateur après réordonnancement. La configuration de l\'API du modèle de réordonnancement est requise',
},
rerankModelRequired: 'Un modèle de réorganisation est nécessaire',
params: 'Paramètres',
top_k: 'Top K',
top_kTip: 'Utilisé pour filtrer les morceaux qui sont les plus similaires aux questions de l\'utilisateur. Le système ajustera également dynamiquement la valeur de Top K, selon max_tokens du modèle sélectionné.',
score_threshold: 'Seuil de Score',
score_thresholdTip: 'Utilisé pour définir le seuil de similarité pour le filtrage des morceaux.',
retrieveChangeTip: 'La modification du mode d\'indexation et du mode de récupération peut affecter les applications associées à cette Connaissance.',
},
debugAsSingleModel: 'Déboguer comme Modèle Unique',
debugAsMultipleModel: 'Déboguer en tant que Modèles Multiples',
duplicateModel: 'Dupliquer',
publishAs: 'Publier comme',
assistantType: {
name: 'Type d\'Assistant',
chatAssistant: {
name: 'Assistant de Base',
description: 'Construisez un assistant basé sur le chat en utilisant un grand modèle de langage',
},
agentAssistant: {
name: 'Assistant Agent',
description: 'Construisez un Agent intelligent qui peut choisir de manière autonome des outils pour accomplir les tâches',
},
},
agent: {
agentMode: 'Mode Agent',
agentModeDes: 'Définissez le type de mode d\'inférence pour l\'agent',
agentModeType: {
ReACT: 'RéAgir',
functionCall: 'Appel de fonction',
},
setting: {
name: 'Paramètres de l\'Agent',
description: 'Les paramètres de l\'Assistant Agent permettent de définir le mode de l\'agent et des fonctionnalités avancées comme les prompts intégrés, uniquement disponibles dans le type Agent.',
maximumIterations: {
name: 'Nombre Maximum d\'Itérations',
description: 'Limiter le nombre d\'itérations qu\'un assistant agent peut exécuter',
},
},
buildInPrompt: 'Prompt Intégré',
firstPrompt: 'Première Prompte',
nextIteration: 'Prochaine Itération',
promptPlaceholder: 'Écrivez votre prompt ici',
tools: {
name: 'Outils',
description: 'L\'utilisation d\'outils peut étendre les capacités des LLM, comme la recherche sur internet ou l\'exécution de calculs scientifiques.',
enabled: 'Activé',
},
},
}
export default translation

69
web/i18n/fr-FR/app-log.ts Normal file
View File

@ -0,0 +1,69 @@
const translation = {
title: 'Journaux',
description: 'Les journaux enregistrent l\'état de fonctionnement de l\'application, y compris les entrées de l\'utilisateur et les réponses de l\'IA.',
dateTimeFormat: 'JJ/MM/AAAA hh:mm A',
table: {
header: {
time: 'Temps',
endUser: 'Utilisateur final',
input: 'Entrée',
output: 'Sortie',
summary: 'Titre',
messageCount: 'Nombre de Messages',
userRate: 'Taux d\'utilisateur',
adminRate: 'Taux Op.',
},
pagination: {
previous: 'Précédent',
next: 'Suivant',
},
empty: {
noChat: 'Aucune conversation pour le moment',
noOutput: 'Aucune sortie',
element: {
title: 'Quelqu\'un est là ?',
content: 'Observez et annotez les interactions entre les utilisateurs finaux et les applications IA ici pour améliorer continuellement la précision de l\'IA. Vous pouvez essayer de <shareLink>partager</shareLink> ou de <testLink>tester</testLink> l\'application Web',
},
},
},
detail: {
time: 'Temps',
conversationId: 'ID de conversation',
promptTemplate: 'Modèle de Prompt',
promptTemplateBeforeChat: 'Modèle de Prompt Avant le Chat · En Tant que Message Système',
annotationTip: 'Améliorations Marquées par {{user}}',
timeConsuming: 'Apologies, but you haven\'t provided any text to translate. Could you please provide the text so I can help you with the translation?',
second: '"s"',
tokenCost: 'Jeton dépensé',
loading: 'chargement',
operation: {
like: 'comme',
dislike: 'déteste',
addAnnotation: 'Ajouter une amélioration',
editAnnotation: 'Amélioration de l\'édition',
annotationPlaceholder: 'Entrez la réponse attendue que vous souhaitez que l\'IA donne, qui peut être utilisée pour l\'ajustement fin du modèle et l\'amélioration continue de la qualité de génération de texte à l\'avenir.',
},
variables: 'Variables',
uploadImages: 'Images Téléchargées',
},
filter: {
period: {
today: 'Aujourd\'hui',
last7days: 'Les 7 Derniers Jours',
last4weeks: 'Les 4 dernières semaines',
last3months: 'Les 3 derniers mois',
last12months: 'Les 12 derniers mois',
monthToDate: 'Mois à ce jour',
quarterToDate: 'Trimestre à ce jour',
yearToDate: 'Année à ce jour',
allTime: 'Tout le temps',
},
annotation: {
all: 'Tout',
annotated: 'Améliorations annotées ({{count}} éléments)',
not_annotated: 'Non Annoté',
},
},
}
export default translation

View File

@ -0,0 +1,139 @@
const translation = {
welcome: {
firstStepTip: 'Pour commencer,',
enterKeyTip: 'entrez votre clé API OpenAI ci-dessous',
getKeyTip: 'Obtenez votre clé API depuis le tableau de bord OpenAI',
placeholder: 'Votre clé API OpenAI (par exemple, sk-xxxx)',
},
apiKeyInfo: {
cloud: {
trial: {
title: 'Vous utilisez le quota d\'essai de {{providerName}}.',
description: 'Le quota d\'essai est fourni pour votre utilisation de test. Avant que les appels de quota d\'essai ne soient épuisés, veuillez configurer votre propre fournisseur de modèle ou acheter un quota supplémentaire.',
},
exhausted: {
title: 'Votre quota d\'essai a été utilisé, veuillez configurer votre APIKey.',
description: 'Votre quota d\'essai a été épuisé. Veuillez configurer votre propre fournisseur de modèle ou acheter un quota supplémentaire.',
},
},
selfHost: {
title: {
row1: 'Pour commencer,',
row2: 'configurez d\'abord votre fournisseur de modèle.',
},
},
callTimes: 'Heures d\'appel',
usedToken: 'Token utilisé',
setAPIBtn: 'Allez configurer le fournisseur de modèle',
tryCloud: 'Ou essayez la version cloud de Dify avec un devis gratuit',
},
overview: {
title: 'Aperçu',
appInfo: {
explanation: 'WebApp IA prête à l\'emploi',
accessibleAddress: 'URL publique',
preview: 'Aperçu',
regenerate: 'Régénérer',
preUseReminder: 'Veuillez activer WebApp avant de continuer.',
settings: {
entry: 'Paramètres',
title: 'Paramètres de l\'application Web',
webName: 'Nom de l\'application Web',
webDesc: 'Description de l\'application web',
webDescTip: 'Ce texte sera affiché du côté du client, fournissant des indications de base sur comment utiliser l\'application',
webDescPlaceholder: 'Entrez la description de la WebApp',
language: 'Langue',
more: {
entry: 'Montrer plus de paramètres',
copyright: 'Droit d\'auteur',
copyRightPlaceholder: 'Entrez le nom de l\'auteur ou de l\'organisation',
privacyPolicy: 'Politique de Confidentialité',
privacyPolicyPlaceholder: 'Entrez le lien de la politique de confidentialité',
privacyPolicyTip: 'Aide les visiteurs à comprendre les données que l\'application collecte, voir la <privacyPolicyLink>Politique de Confidentialité</privacyPolicyLink> de Dify.',
},
},
embedded: {
entry: 'Intégré',
title: 'Intégrer sur le site web',
explanation: 'Choisissez la manière d\'intégrer l\'application de chat à votre site web',
iframe: 'Pour ajouter l\'application de chat n\'importe où sur votre site web, ajoutez cette iframe à votre code html.',
scripts: 'Pour ajouter une application de chat en bas à droite de votre site web, ajoutez ce code à votre html.',
chromePlugin: 'Installez l\'extension Chrome Dify Chatbot',
copied: 'Copié',
copy: 'Copier',
},
qrcode: {
title: 'QR code à partager',
scan: 'Application de Partage de Scan',
download: 'Télécharger le Code QR',
},
customize: {
way: 'manière',
entry: 'Personnaliser',
title: 'Personnaliser l\'WebApp IA',
explanation: 'Vous pouvez personnaliser l\'interface utilisateur de l\'application Web pour répondre à vos besoins en termes de scénario et de style.',
way1: {
name: 'Faites une fourchette du code client, modifiez-le et déployez-le sur Vercel (recommandé)',
step1: 'Faites une fourchette du code client et modifiez-le',
step1Tip: 'Cliquez ici pour bifurquer le code source dans votre compte GitHub et modifier le code',
step1Operation: 'Dify-WebClient',
step2: 'Déployer sur Vercel',
step2Tip: 'Cliquez ici pour importer le dépôt dans Vercel et déployer',
step2Operation: 'Importer le dépôt',
step3: 'Configurer les variables d\'environnement',
step3Tip: 'Ajoutez les variables d\'environnement suivantes dans Vercel',
},
way2: {
name: 'Écrivez du code côté client pour appeler l\'API et déployez-le sur un serveur',
operation: 'Documentation',
},
},
},
apiInfo: {
title: 'API du service Backend',
explanation: 'Facilement intégré dans votre application',
accessibleAddress: 'Point de terminaison du service API',
doc: 'Référence API',
},
status: {
running: 'En service',
disable: 'Désactiver',
},
},
analysis: {
title: 'Analyse',
ms: 'ms',
tokenPS: 'Jeton/s',
totalMessages: {
title: 'Messages Totaux',
explanation: 'Nombre quotidien d\'interactions IA ; ingénierie/debuggage de prompt exclu.',
},
activeUsers: {
title: 'Utilisateurs Actifs',
explanation: 'Utilisateurs uniques participant à des Q&A avec l\'IA ; l\'ingénierie/débogage de prompt exclu.',
},
tokenUsage: {
title: 'Utilisation de Token',
explanation: 'Reflet de l\'utilisation quotidienne des jetons du modèle de langage pour l\'application, utile à des fins de contrôle des coûts.',
consumed: 'Consommé',
},
avgSessionInteractions: {
title: 'Interactions Moyennes par Session',
explanation: 'Comptage continu de la communication utilisateur-IA ; pour les applications basées sur la conversation.',
},
userSatisfactionRate: {
title: 'Taux de Satisfaction de l\'Utilisateur',
explanation: 'Le nombre de "j\'aime" par 1 000 messages. Cela indique la proportion de réponses dont les utilisateurs sont très satisfaits.',
},
avgResponseTime: {
title: 'Temps de réponse moyen',
explanation: 'Temps (ms) pour que l\'IA traite/réponde; pour les applications basées sur le texte.',
},
tps: {
title: 'Vitesse de Sortie des Tokens',
explanation: 'Mesurez la performance du LLM. Comptez la vitesse de sortie des Tokens du LLM depuis le début de la demande jusqu\'à l\'achèvement de la sortie.',
},
},
}
export default translation

54
web/i18n/fr-FR/app.ts Normal file
View File

@ -0,0 +1,54 @@
const translation = {
createApp: 'Créer une nouvelle application',
types: {
all: 'Tout',
assistant: 'Assistant',
completion: 'Complétion',
},
modes: {
completion: 'Générateur de Texte',
chat: 'Assistant de Base',
},
createFromConfigFile: 'Créer une application à partir du fichier de configuration',
deleteAppConfirmTitle: 'Supprimer cette application ?',
deleteAppConfirmContent:
'La suppression de l\'application est irréversible. Les utilisateurs ne pourront plus accéder à votre application, et toutes les configurations de prompt et les journaux seront définitivement supprimés.',
appDeleted: 'Application supprimée',
appDeleteFailed: 'Échec de la suppression de l\'application',
join: 'Rejoignez la communauté',
communityIntro:
'Discutez avec les membres de l\'équipe, les contributeurs et les développeurs sur différents canaux.',
roadmap: 'Voir notre feuille de route',
appNamePlaceholder: 'Veuillez entrer le nom de l\'application',
newApp: {
startToCreate: 'Commençons avec votre nouvelle application',
captionName: 'Icône et nom de l\'application',
captionAppType: 'Quel type d\'application voulez-vous créer ?',
previewDemo: 'Aperçu de la démo',
chatApp: 'Assistant',
chatAppIntro:
'Je veux construire une application basée sur le chat. Cette application utilise un format de questions-réponses, permettant plusieurs tours de conversation continue.',
agentAssistant: 'Nouvel Assistant Agent',
completeApp: 'Générateur de Texte',
completeAppIntro:
'Je veux créer une application qui génère du texte de haute qualité basé sur des prompts, tels que la génération d\'articles, de résumés, de traductions, et plus encore.',
showTemplates: 'Je veux choisir à partir d\'un modèle',
hideTemplates: 'Revenir à la sélection de mode',
Create: 'Créer',
Cancel: 'Annuler',
nameNotEmpty: 'Le nom ne peut pas être vide',
appTemplateNotSelected: 'Veuillez sélectionner un modèle',
appTypeRequired: 'Veuillez sélectionner un type d\'application',
appCreated: 'Application créée',
appCreateFailed: 'Échec de la création de l\'application',
},
editApp: {
startToEdit: 'Modifier l\'application',
},
emoji: {
ok: 'D\'accord',
cancel: 'Annuler',
},
}
export default translation

115
web/i18n/fr-FR/billing.ts Normal file
View File

@ -0,0 +1,115 @@
const translation = {
currentPlan: 'Plan Actuel',
upgradeBtn: {
plain: 'Mettre à jour le plan',
encourage: 'Mettre à niveau maintenant',
encourageShort: 'Mise à niveau',
},
viewBilling: 'Gérer la facturation et les abonnements',
buyPermissionDeniedTip: 'Veuillez contacter votre administrateur d\'entreprise pour vous abonner',
plansCommon: {
title: 'Choisissez un plan qui vous convient',
yearlyTip: 'Obtenez 2 mois gratuitement en vous abonnant annuellement !',
mostPopular: 'Le Plus Populaire',
planRange: {
monthly: 'Mensuel',
yearly: 'Annuel',
},
month: 'mois',
year: 'année',
save: 'Enregistrer',
free: 'Gratuit',
currentPlan: 'Plan Actuel',
contractSales: 'Contactez les ventes',
contractOwner: 'Contacter le chef d\'équipe',
startForFree: 'Commencez gratuitement',
getStartedWith: 'Commencez avec',
contactSales: 'Contacter les ventes',
talkToSales: 'Parlez aux Ventes',
modelProviders: 'Fournisseurs de Modèles',
teamMembers: 'Membres de l\'équipe',
buildApps: 'Construire des Applications',
vectorSpace: 'Espace Vectoriel',
vectorSpaceBillingTooltip: 'Chaque 1MB peut stocker environ 1,2 million de caractères de données vectorisées (estimé en utilisant les embeddings OpenAI, varie selon les modèles).',
vectorSpaceTooltip: 'L\'espace vectoriel est le système de mémoire à long terme nécessaire pour que les LLMs comprennent vos données.',
documentsUploadQuota: 'Quota de téléchargement de documents',
documentProcessingPriority: 'Priorité de Traitement de Document',
documentProcessingPriorityTip: 'Pour une priorité de traitement de documents plus élevée, veuillez mettre à niveau votre plan.',
documentProcessingPriorityUpgrade: 'Traitez plus de données avec une précision plus élevée à des vitesses plus rapides.',
priority: {
'standard': 'Standard',
'priority': 'Priorité',
'top-priority': 'Priorité Maximale',
},
logsHistory: 'Historique des logs',
customTools: 'Outils personnalisés',
unavailable: 'Indisponible',
days: 'jours',
unlimited: 'Illimité',
support: 'Assistance',
supportItems: {
communityForums: 'Forums communautaires',
emailSupport: 'Support par email',
priorityEmail: 'Support prioritaire par email et chat',
logoChange: 'Changement de logo',
SSOAuthentication: 'Authentification SSO',
personalizedSupport: 'Soutien personnalisé',
dedicatedAPISupport: 'Support dédié pour l\'API',
customIntegration: 'Intégration personnalisée et support',
ragAPIRequest: 'Requêtes API RAG',
bulkUpload: 'Téléchargement en masse de documents',
agentMode: 'Mode Agent',
workflow: 'Flux de travail',
},
comingSoon: 'Bientôt disponible',
member: 'Membre',
memberAfter: 'Membre',
messageRequest: {
title: 'Crédits de message',
tooltip: 'Quotas d\'invocation de messages pour divers plans utilisant les modèles OpenAI (sauf gpt4). Les messages dépassant la limite utiliseront votre clé API OpenAI.',
},
annotatedResponse: {
title: 'Limites de quota d\'annotation',
tooltip: 'L\'édition manuelle et l\'annotation des réponses fournissent des capacités de réponse aux questions de haute qualité personnalisables pour les applications. (Applicable uniquement dans les applications de chat)',
},
ragAPIRequestTooltip: 'Fait référence au nombre d\'appels API invoquant uniquement les capacités de traitement de la base de connaissances de Dify.',
receiptInfo: 'Seuls le propriétaire de l\'équipe et l\'administrateur de l\'équipe peuvent s\'abonner et consulter les informations de facturation',
},
plans: {
sandbox: {
name: 'Bac à sable',
description: '200 essais gratuits de GPT',
includesTitle: 'Inclus :',
},
professional: {
name: 'Professionnel',
description: 'Pour les individus et les petites équipes afin de débloquer plus de puissance à un prix abordable.',
includesTitle: 'Tout ce qui est dans le plan gratuit, plus :',
},
team: {
name: 'Équipe',
description: 'Collaborez sans limites et profitez d\'une performance de premier ordre.',
includesTitle: 'Tout ce qui est inclus dans le plan Professionnel, plus :',
},
enterprise: {
name: 'Entreprise',
description: 'Obtenez toutes les capacités et le support pour les systèmes à grande échelle et critiques pour la mission.',
includesTitle: 'Tout ce qui est inclus dans le plan Équipe, plus :',
},
},
vectorSpace: {
fullTip: 'L\'espace vectoriel est plein.',
fullSolution: 'Mettez à niveau votre plan pour obtenir plus d\'espace.',
},
apps: {
fullTipLine1: 'Mettez à jour votre plan pour',
fullTipLine2: 'construire plus d\'applications.',
},
annotatedResponse: {
fullTipLine1: 'Mettez à niveau votre plan pour',
fullTipLine2: 'annotez plus de conversations.',
quotaTitle: 'Quota de Réponse d\'Annotation',
},
}
export default translation

505
web/i18n/fr-FR/common.ts Normal file
View File

@ -0,0 +1,505 @@
const translation = {
api: {
success: 'Succès',
actionSuccess: 'Action réussie',
saved: 'Sauvegardé',
create: 'Créé',
remove: 'Supprimé',
},
operation: {
create: 'Créer',
confirm: 'Confirmer',
cancel: 'Annuler',
clear: 'Clair',
save: 'Enregistrer',
edit: 'Modifier',
add: 'Ajouter',
added: 'Ajouté',
refresh: 'Redémarrer',
reset: 'Réinitialiser',
search: 'Recherche',
change: 'Changer',
remove: 'Supprimer',
send: 'Envoyer',
copy: 'Copier',
lineBreak: 'Saut de ligne',
sure: 'Je suis sûr',
download: 'Télécharger',
delete: 'Supprimer',
settings: 'Paramètres',
setup: 'Configuration',
getForFree: 'Obtenez gratuitement',
reload: 'Recharger',
ok: 'D\'accord',
log: 'Journal',
learnMore: 'En savoir plus',
params: 'Paramètres',
},
placeholder: {
input: 'Veuillez entrer',
select: 'Veuillez sélectionner',
},
voice: {
language: {
zhHans: 'Chinois',
enUS: 'Anglais',
deDE: 'Allemand',
frFR: 'Français',
esES: 'Espagnol',
itIT: 'Italien',
thTH: 'Thaï.',
idID: 'Indonésien',
jaJP: 'Japonais',
koKR: 'Coréen',
ptBR: 'Portugais',
ruRU: 'Russe',
ukUA: 'Ukrainien',
},
},
unit: {
char: 'caractères',
},
actionMsg: {
noModification: 'Aucune modification pour le moment.',
modifiedSuccessfully: 'Modifié avec succès',
modifiedUnsuccessfully: 'Modifié sans succès',
copySuccessfully: 'Copié avec succès',
paySucceeded: 'Paiement réussi',
payCancelled: 'Paiement annulé',
generatedSuccessfully: 'Généré avec succès',
generatedUnsuccessfully: 'Généré sans succès',
},
model: {
params: {
temperature: 'Température',
temperatureTip:
'Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.',
top_p: 'Haut P',
top_pTip:
'Controls diversity via nucleus sampling: 0.5 means half of all likelihood-weighted options are considered.',
presence_penalty: 'Pénalité de présence',
presence_penaltyTip:
'Combien pénaliser les nouveaux tokens en fonction de leur apparition dans le texte jusqu\'à présent. Augmente la probabilité du modèle de parler de nouveaux sujets.',
frequency_penalty: 'Pénalité de fréquence',
frequency_penaltyTip:
'Combien pénaliser les nouveaux tokens en fonction de leur fréquence existante dans le texte jusqu\'à présent. Réduit la probabilité du modèle de répéter la même ligne mot pour mot.',
max_tokens: 'Max jeton',
max_tokensTip:
'Utilisé pour limiter la longueur maximale de la réponse, en jetons. \nDes valeurs plus grandes peuvent limiter l\'espace restant pour les mots de prompt, les journaux de chat, et la Connaissance. \nIl est recommandé de le régler en dessous des',
maxTokenSettingTip: 'Votre réglage de max token est élevé, limitant potentiellement l\'espace pour les prompts, les requêtes et les données. Envisagez de le définir en dessous de 2/3.',
setToCurrentModelMaxTokenTip: 'Le max token est mis à jour à 80% du max token du modèle actuel {{maxToken}}.',
stop_sequences: 'Séquences d\'arrêt',
stop_sequencesTip: 'Jusqu\'à quatre séquences où l\'API arrêtera de générer d\'autres tokens. Le texte renvoyé ne contiendra pas la séquence d\'arrêt.',
stop_sequencesPlaceholder: 'Entrez la séquence et appuyez sur Tab',
},
tone: {
Creative: 'Créatif',
Balanced: 'Équilibré',
Precise: 'Précis',
Custom: 'Personnalisé',
},
addMoreModel: 'Allez dans les paramètres pour ajouter plus de modèles',
},
menus: {
status: 'bêta',
explore: 'Explorer',
apps: 'Studio',
plugins: 'Plugins',
pluginsTips: 'Intégrez des plugins tiers ou créez des AI-Plugins compatibles avec ChatGPT.',
datasets: 'Connaissance',
datasetsTips: 'COMING SOON: Import your own text data or write data in real-time via Webhook for LLM context enhancement.',
newApp: 'Nouvelle Application',
newDataset: 'Créer des Connaissances',
tools: 'Outils',
},
userProfile: {
settings: 'Paramètres',
workspace: 'Espace de travail',
createWorkspace: 'Créer un Espace de Travail',
helpCenter: 'Aide',
roadmapAndFeedback: 'Feuille de route & Retour d\'information',
community: 'Communauté',
about: 'À propos',
logout: 'Se déconnecter',
},
settings: {
accountGroup: 'COMPTE',
workplaceGroup: 'ESPACE DE TRAVAIL',
account: 'Mon compte',
members: 'Membres',
billing: 'Facturation',
integrations: 'Intégrations',
language: 'Langue',
provider: 'Fournisseur de Modèle',
dataSource: 'Source de Données',
plugin: 'Plugins',
apiBasedExtension: 'Extension API',
},
account: {
avatar: 'Avatar',
name: 'Nom',
email: 'Courriel',
password: 'Mot de passe',
passwordTip: 'Vous pouvez définir un mot de passe permanent si vous ne souhaitez pas utiliser des codes de connexion temporaires.',
setPassword: 'Définir un mot de passe',
resetPassword: 'Réinitialiser le mot de passe',
currentPassword: 'Mot de passe actuel',
newPassword: 'Nouveau mot de passe',
confirmPassword: 'Confirmer le mot de passe',
notEqual: 'Les deux mots de passe sont différents.',
langGeniusAccount: 'Compte Dify',
langGeniusAccountTip: 'Votre compte Dify et les données utilisateur associées.',
editName: 'Modifier le nom',
showAppLength: 'Afficher {{length}} applications',
},
members: {
team: 'Équipe',
invite: 'Ajouter',
name: 'NOM',
lastActive: 'DERNIÈRE ACTIVITÉ',
role: 'RÔLES',
pending: 'En attente...',
owner: 'Propriétaire',
admin: 'Administrateur',
adminTip: 'Peut construire des applications & gérer les paramètres de l\'équipe',
normal: 'Normal',
normalTip: 'Peut seulement utiliser des applications, ne peut pas construire des applications',
inviteTeamMember: 'Ajouter un membre de l\'équipe',
inviteTeamMemberTip: 'Ils peuvent accéder directement à vos données d\'équipe après s\'être connectés.',
email: 'Courrier électronique',
emailInvalid: 'Format de courriel invalide',
emailPlaceholder: 'Veuillez entrer des emails',
sendInvite: 'Envoyer une invitation',
invitedAsRole: 'Invité en tant qu\'utilisateur {{role}}',
invitationSent: 'Invitation envoyée',
invitationSentTip: 'Invitation envoyée, et ils peuvent se connecter à Dify pour accéder aux données de votre équipe.',
invitationLink: 'Lien d\'invitation',
failedinvitationEmails: 'Les utilisateurs ci-dessous n\'ont pas été invités avec succès',
ok: 'D\'accord',
removeFromTeam: 'Retirer de l\'équipe',
removeFromTeamTip: 'Supprimera l\'accès de l\'équipe',
setAdmin: 'Définir comme administrateur',
setMember: 'Définir en tant que membre ordinaire',
disinvite: 'Annuler l\'invitation',
deleteMember: 'Supprimer Membre',
you: '(Vous)',
},
integrations: {
connected: 'Connecté',
google: 'Google',
googleAccount: 'Connectez-vous avec un compte Google',
github: 'GitHub',
githubAccount: 'Connectez-vous avec un compte GitHub',
connect: 'Connecter',
},
language: {
displayLanguage: 'Langue d\'affichage',
timezone: 'Fuseau horaire',
},
provider: {
apiKey: 'Clé API',
enterYourKey: 'Entrez votre clé API ici',
invalidKey: 'Clé API OpenAI invalide',
validatedError: 'Validation failed: ',
validating: 'Validation de la clé...',
saveFailed: 'La sauvegarde de la clé API a échoué',
apiKeyExceedBill: 'Cette clé API n\'a pas de quota disponible, veuillez lire',
addKey: 'Ajouter une clé',
comingSoon: 'Bientôt disponible',
editKey: 'Modifier',
invalidApiKey: 'Clé API invalide',
azure: {
apiBase: 'Base de l\'API',
apiBasePlaceholder: 'L\'URL de base de l\'API de votre point de terminaison Azure OpenAI.',
apiKey: 'Clé API',
apiKeyPlaceholder: 'Entrez votre clé API ici',
helpTip: 'Apprenez le service OpenAI Azure',
},
openaiHosted: {
openaiHosted: 'OpenAI Hébergé',
onTrial: 'EN ESSAI',
exhausted: 'QUOTA ÉPUISÉ',
desc: 'Le service d\'hébergement OpenAI fourni par Dify vous permet d\'utiliser des modèles tels que GPT-3.5. Avant que votre quota d\'essai ne soit épuisé, vous devez configurer d\'autres fournisseurs de modèles.',
callTimes: 'Temps d\'appel',
usedUp: 'Quota d\'essai épuisé. Ajoutez votre propre fournisseur de modèle.',
useYourModel: 'Utilise actuellement son propre fournisseur de modèle.',
close: 'Fermer',
},
anthropicHosted: {
anthropicHosted: 'Anthropic Claude',
onTrial: 'EN ESSAI',
exhausted: 'QUOTA ÉPUISÉ',
desc: 'Modèle puissant, qui excelle dans une large gamme de tâches allant du dialogue sophistiqué et de la génération de contenu créatif à l\'instruction détaillée.',
callTimes: 'Temps d\'appel',
usedUp: 'Quota d\'essai épuisé. Ajoutez votre propre fournisseur de modèle.',
useYourModel: 'Utilise actuellement son propre fournisseur de modèle.',
close: 'Fermer',
},
anthropic: {
using: 'La capacité d\'embedding est utilisée',
enableTip: 'Pour activer le modèle Anthropic, vous devez d\'abord vous lier à OpenAI ou au service Azure OpenAI.',
notEnabled: 'Non activé',
keyFrom: 'Obtenez votre clé API de chez Anthropic',
},
encrypted: {
front: 'Votre clé API sera chiffrée et stockée en utilisant',
back: 'technologie.',
},
},
modelProvider: {
notConfigured: 'Le modèle du système n\'a pas encore été entièrement configuré, et certaines fonctions peuvent être indisponibles.',
systemModelSettings: 'Paramètres du Modèle Système',
systemModelSettingsLink: 'Pourquoi est-il nécessaire de mettre en place un modèle de système ?',
selectModel: 'Sélectionnez votre modèle',
setupModelFirst: 'Veuillez d\'abord configurer votre modèle',
systemReasoningModel: {
key: 'Modèle de Raisonnement du Système',
tip: 'Définissez le modèle d\'inférence par défaut à utiliser pour la création d\'applications, ainsi que des fonctionnalités telles que la génération de noms de dialogue et la suggestion de la prochaine question utiliseront également le modèle d\'inférence par défaut.',
},
embeddingModel: {
key: 'Modèle d\'Embedding',
tip: 'Définissez le modèle par défaut pour le traitement d\'incorporation de documents de la Connaissance, à la fois la récupération et l\'importation de la Connaissance utilisent ce modèle d\'Embedding pour le traitement de vectorisation. Si vous changez de modèle, la dimension du vecteur entre la connaissance importée et la question ne sera pas cohérente, ce qui entraînera un échec de la recherche. Pour éviter les échecs de recherche, veuillez ne pas changer de modèle à volonté.',
required: 'Le modèle d\'embedding est requis',
},
speechToTextModel: {
key: 'Modèle de Texte-à-Parole',
tip: 'Définissez le modèle par défaut pour l\'entrée de texte par la parole dans la conversation.',
},
ttsModel: {
key: 'Modèle de Texte-à-Parole',
tip: 'Définissez le modèle par défaut pour l\'entrée de texte à la parole dans une conversation.',
},
rerankModel: {
key: 'Modèle de Réorganisation',
tip: 'Le modèle de réorganisation réorganisera la liste des documents candidats en fonction de la correspondance sémantique avec la requête de l\'utilisateur, améliorant ainsi les résultats du classement sémantique.',
},
quota: 'Quota',
searchModel: 'Modèle de recherche',
noModelFound: 'Aucun modèle trouvé pour {{model}}',
models: 'Modèles',
showMoreModelProvider: 'Montrer plus de fournisseur de modèle',
selector: {
tip: 'Ce modèle a été supprimé. Veuillez ajouter un modèle ou sélectionner un autre modèle.',
emptyTip: 'Aucun modèle disponible',
emptySetting: 'Veuillez aller dans les paramètres pour configurer',
rerankTip: 'Veuillez configurer le modèle Rerank',
},
card: {
quota: 'QUOTA',
onTrial: 'En Essai',
paid: 'Payé',
quotaExhausted: 'Quota épuisé',
callTimes: 'Temps d\'appel',
tokens: 'Jetons',
buyQuota: 'Acheter Quota',
priorityUse: 'Utilisation prioritaire',
removeKey: 'Supprimer la clé API',
tip: 'La priorité sera donnée au quota payant. Le quota d\'essai sera utilisé après épuisement du quota payant.',
},
item: {
deleteDesc: '{{modelName}} sont utilisés comme modèles de raisonnement système. Certaines fonctions ne seront pas disponibles après la suppression. Veuillez confirmer.',
freeQuota: 'QUOTA GRATUIT',
},
addApiKey: 'Ajoutez votre clé API',
invalidApiKey: 'Clé API invalide',
encrypted: {
front: 'Votre clé API sera cryptée et stockée en utilisant',
back: 'technologie.',
},
freeQuota: {
howToEarn: 'Comment gagner',
},
addMoreModelProvider: 'AJOUTER PLUS DE FOURNISSEUR DE MODÈLE',
addModel: 'Ajouter un modèle',
modelsNum: '{{num}} Modèles',
showModels: 'Montrer les modèles',
showModelsNum: 'Afficher {{num}} Modèles',
collapse: 'Effondrer',
config: 'Configuration',
modelAndParameters: 'Modèle et Paramètres',
model: 'Modèle',
featureSupported: '{{feature}} pris en charge',
callTimes: 'Temps d\'appel',
credits: 'Crédits de Messages',
buyQuota: 'Acheter Quota',
getFreeTokens: 'Obtenez des Tokens gratuits',
priorityUsing: 'Prioriser l\'utilisation',
deprecated: 'Obsolète',
confirmDelete: 'confirmer la suppression?',
quotaTip: 'Tokens gratuits restants disponibles',
loadPresets: 'Charger les Présents',
parameters: 'PARAMÈTRES',
},
dataSource: {
add: 'Ajouter une source de données',
connect: 'Connecter',
notion: {
title: 'Notion',
description: 'Utiliser Notion comme source de données pour la Connaissance.',
connectedWorkspace: 'Espace de travail connecté',
addWorkspace: 'Ajouter un espace de travail',
connected: 'Connecté',
disconnected: 'Déconnecté',
changeAuthorizedPages: 'Modifier les pages autorisées',
pagesAuthorized: 'Pages autorisées',
sync: 'Synchronisation',
remove: 'Supprimer',
selector: {
pageSelected: 'Pages Sélectionnées',
searchPages: 'Rechercher des pages...',
noSearchResult: 'Aucun résultat de recherche',
addPages: 'Ajouter des pages',
preview: 'APERÇU',
},
},
},
plugin: {
serpapi: {
apiKey: 'Clé API',
apiKeyPlaceholder: 'Entrez votre clé API',
keyFrom: 'Obtenez votre clé SerpAPI depuis la page de compte SerpAPI',
},
},
apiBasedExtension: {
title: 'Les extensions API fournissent une gestion centralisée des API, simplifiant la configuration pour une utilisation facile à travers les applications de Dify.',
link: 'Apprenez comment développer votre propre Extension API.',
linkUrl: 'https://docs.dify.ai/fonctionnalites/extension/extension_basee_sur_api',
add: 'Ajouter l\'extension API',
selector: {
title: 'Extension de l\'API',
placeholder: 'Veuillez sélectionner l\'extension API',
manage: 'Gérer l\'extension API',
},
modal: {
title: 'Ajouter une extension API',
editTitle: 'Modifier l\'extension API',
name: {
title: 'Nom',
placeholder: 'Veuillez entrer le nom',
},
apiEndpoint: {
title: 'Point de terminaison API',
placeholder: 'Veuillez entrer le point de terminaison de l\'API',
},
apiKey: {
title: 'clé API',
placeholder: 'Veuillez entrer la clé API',
lengthError: 'La longueur de la clé API ne peut pas être inférieure à 5 caractères',
},
},
type: 'Tapez',
},
about: {
changeLog: 'Journal des modifications',
updateNow: 'Mettre à jour maintenant',
nowAvailable: 'Dify {{version}} est maintenant disponible.',
latestAvailable: 'Dify {{version}} est la dernière version disponible.',
},
appMenus: {
overview: 'Aperçu',
promptEng: 'Orchestrer',
apiAccess: 'Accès API',
logAndAnn: 'Journaux & Annonces.',
},
environment: {
testing: 'TESTER',
development: 'DÉVELOPPEMENT',
},
appModes: {
completionApp: 'Générateur de Texte',
chatApp: 'Appli de Chat',
},
datasetMenus: {
documents: 'Documents',
hitTesting: 'Test de Récupération',
settings: 'Paramètres',
emptyTip: 'La Connaissance n\'a pas été associée, veuillez aller à l\'application ou au plug-in pour compléter l\'association.',
viewDoc: 'Voir la documentation',
relatedApp: 'applications liées',
},
voiceInput: {
speaking: 'Parle maintenant...',
converting: 'Conversion en texte...',
notAllow: 'microphone non autorisé',
},
modelName: {
'gpt-3.5-turbo': 'GPT-3.5-Turbo',
'gpt-3.5-turbo-16k': 'GPT-3.5-Turbo-16K',
'gpt-4': 'GPT-4',
'gpt-4-32k': 'GPT-4-32K',
'text-davinci-003': 'Texte-Davinci-003',
'text-embedding-ada-002': 'Texte-Intégration-Ada-002',
'whisper-1': 'Whisper-1',
'claude-instant-1': 'Claude-Instant',
'claude-2': 'Claude-2',
},
chat: {
renameConversation: 'Renommer la conversation',
conversationName: 'Nom de la conversation',
conversationNamePlaceholder: 'Veuillez entrer le nom de la conversation',
conversationNameCanNotEmpty: 'Nom de la conversation requis',
citation: {
title: 'CITATIONS',
linkToDataset: 'Lien vers la Connaissance',
characters: 'Personnages :',
hitCount: 'Nombre de récupérations :',
vectorHash: 'Hachage vectoriel:',
hitScore: 'Score de Récupération:',
},
},
promptEditor: {
placeholder: 'Écrivez votre mot d\'invite ici, entrez \'{\' pour insérer une variable, entrez \'/\' pour insérer un bloc de contenu d\'invite',
context: {
item: {
title: 'Contexte',
desc: 'Insérez le modèle de contexte',
},
modal: {
title: '{{num}} Connaissance en Contexte',
add: 'Ajouter Contexte',
footer: 'Vous pouvez gérer les contextes dans la section Contexte ci-dessous.',
},
},
history: {
item: {
title: 'Historique des conversations',
desc: 'Insérer le modèle de message historique',
},
modal: {
title: 'EXEMPLE',
user: 'Bonjour',
assistant: 'Bonjour ! Comment puis-je vous aider aujourd\'hui ?',
edit: 'Modifier les Noms des Rôles de Conversation',
},
},
variable: {
item: {
title: 'Variables & Outils Externes',
desc: 'Insérer des Variables & Outils Externes',
},
modal: {
add: 'Nouvelle variable',
addTool: 'Nouvel outil',
},
},
query: {
item: {
title: 'Requête',
desc: 'Insérez le modèle de requête utilisateur',
},
},
existed: 'Existe déjà dans le prompt',
},
imageUploader: {
uploadFromComputer: 'Télécharger depuis l\'ordinateur',
uploadFromComputerReadError: 'La lecture de l\'image a échoué, veuillez réessayer.',
uploadFromComputerUploadError: 'Le téléchargement de l\'image a échoué, veuillez télécharger à nouveau.',
uploadFromComputerLimit: 'Le téléchargement d\'images ne peut pas dépasser {{size}} MB',
pasteImageLink: 'Collez le lien de l\'image',
pasteImageLinkInputPlaceholder: 'Collez le lien de l\'image ici',
pasteImageLinkInvalid: 'Lien d\'image invalide',
imageUpload: 'Téléchargement d\'image',
},
}
export default translation

30
web/i18n/fr-FR/custom.ts Normal file
View File

@ -0,0 +1,30 @@
const translation = {
custom: 'Personnalisation',
upgradeTip: {
prefix: 'Mettez à niveau votre plan pour',
suffix: 'personnalisez votre marque.',
},
webapp: {
title: 'Personnalisez la marque WebApp',
removeBrand: 'Supprimer Propulsé par Dify',
changeLogo: 'Changer Propulsé par l\'Image de Marque',
changeLogoTip: 'Format SVG ou PNG avec une taille minimum de 40x40px',
},
app: {
title: 'Personnaliser la marque de l\'en-tête de l\'application',
changeLogoTip: 'Format SVG ou PNG avec une taille minimale de 80x80px',
},
upload: 'Télécharger',
uploading: 'Téléchargement',
uploadedFail: 'Le téléchargement de l\'image a échoué, veuillez la télécharger à nouveau.',
change: 'Changer',
apply: 'Appliquer',
restore: 'Rétablir les paramètres par défaut',
customize: {
contactUs: 'Contactez-nous',
prefix: 'Pour personnaliser le logo de la marque dans l\'application, s\'il vous plaît',
suffix: 'pour passer à l\'édition Enterprise.',
},
}
export default translation

View File

@ -0,0 +1,130 @@
const translation = {
steps: {
header: {
creation: 'Créer des Connaissances',
update: 'Ajouter des données',
},
one: 'Choisissez la source de données',
two: 'Prétraitement et Nettoyage du Texte',
three: 'Exécutez et terminez',
},
error: {
unavailable: 'Cette connaissance n\'est pas disponible',
},
stepOne: {
filePreview: 'Aperçu du fichier',
pagePreview: 'Aperçu de la page',
dataSourceType: {
file: 'Importer à partir d\'un fichier texte',
notion: 'Synchroniser depuis Notion',
web: 'Synchroniser depuis le site web',
},
uploader: {
title: 'Télécharger le fichier texte',
button: 'Glisser et déposer le fichier, ou',
browse: 'Parcourir',
tip: 'Prend en charge {{supportTypes}}. Max {{size}}MB chacun.',
validation: {
typeError: 'Type de fichier non pris en charge',
size: 'Fichier trop volumineux. Le maximum est de {{size}}MB',
count: 'Plusieurs fichiers non pris en charge',
filesNumber: 'Vous avez atteint la limite de téléchargement par lot de {{filesNumber}}.',
},
cancel: 'Annuler',
change: 'Changer',
failed: 'Le téléchargement a échoué',
},
notionSyncTitle: 'Notion n\'est pas connecté',
notionSyncTip: 'Pour synchroniser avec Notion, une connexion à Notion doit d\'abord être établie.',
connect: 'Aller à connecter',
button: 'suivant',
emptyDatasetCreation: 'Je veux créer un Savoir vide',
modal: {
title: 'Créer une Connaissance vide',
tip: 'Une Connaissance vide ne contiendra aucun document, et vous pouvez télécharger des documents à tout moment.',
input: 'Nom de la connaissance',
placeholder: 'Veuillez entrer',
nameNotEmpty: 'Le nom ne peut pas être vide',
nameLengthInvaild: 'Le nom doit comporter entre 1 et 40 caractères.',
cancelButton: 'Annuler',
confirmButton: 'Créer',
failed: 'Création échouée',
},
},
stepTwo: {
segmentation: 'Paramètres de bloc',
auto: 'Automatique',
autoDescription: 'Définir automatiquement les règles de découpage et de prétraitement. Il est recommandé aux utilisateurs non familiers de sélectionner ceci.',
custom: 'Personnalisé',
customDescription: 'Personnalisez les règles de morceaux, la longueur des morceaux et les règles de prétraitement, etc.',
separator: 'Identifiant de segment',
separatorPlaceholder: 'Par exemple, nouvelle ligne (\\\\n) ou séparateur spécial (tel que "***")',
maxLength: 'Longueur maximale du morceau',
overlap: 'Chevauchement de morceaux',
overlapTip: 'La définition d\'un chevauchement de morceaux peut maintenir la pertinence sémantique entre eux, améliorant ainsi l\'effet de récupération. Il est recommandé de définir 10%-25% de la taille maximale du morceau.',
overlapCheck: 'le chevauchement de morceaux ne doit pas être plus grand que la longueur maximale de morceau',
rules: 'Règles de prétraitement du texte',
removeExtraSpaces: 'Remplacer les espaces consécutifs, les sauts de ligne et les tabulations',
removeUrlEmails: 'Supprimez toutes les URL et adresses e-mail',
removeStopwords: 'Supprimez les mots vides tels que "a", "an", "the"',
preview: 'Confirmer & Aperçu',
reset: 'Réinitialiser',
indexMode: 'Mode d\'index',
qualified: 'Haute Qualité',
recommend: 'Recommander',
qualifiedTip: 'Appelez l\'interface d\'embedding système par défaut pour le traitement afin de fournir une précision plus élevée lorsque les utilisateurs font une requête.',
warning: 'Veuillez d\'abord configurer la clé API du fournisseur de modèle.',
click: 'Aller aux paramètres',
economical: 'Économique',
economicalTip: 'Utilisez des moteurs vectoriels hors ligne, des index de mots-clés, etc. pour réduire la précision sans dépenser de jetons',
QATitle: 'Segmentation en format Question & Réponse',
QATip: 'Activer cette option consommera plus de jetons',
QALanguage: 'Segmenter en utilisant',
emstimateCost: 'Estimation',
emstimateSegment: 'Morceaux estimés',
segmentCount: 'morceaux',
calculating: 'En calcul...',
fileSource: 'Prétraiter les documents',
notionSource: 'Prétraiter les pages',
other: 'et autres',
fileUnit: 'fichiers',
notionUnit: 'pages',
previousStep: 'Étape précédente',
nextStep: 'Enregistrer & Traiter',
save: 'Enregistrer & Traiter',
cancel: 'Annuler',
sideTipTitle: 'Pourquoi découper et prétraiter ?',
sideTipP1: 'Lors du traitement des données textuelles, le découpage et le nettoyage sont deux étapes importantes de la prétraitement.',
sideTipP2: 'La segmentation divise les longs textes en paragraphes afin que les modèles puissent mieux comprendre. Cela améliore la qualité et la pertinence des résultats du modèle.',
sideTipP3: 'Le nettoyage élimine les caractères et les formats inutiles, rendant le Savoir plus propre et plus facile à analyser.',
sideTipP4: 'Un bon découpage et nettoyage améliorent les performances du modèle, fournissant des résultats plus précis et précieux.',
previewTitle: 'Aperçu',
previewTitleButton: 'Aperçu',
previewButton: 'Passage au format Q&R',
previewSwitchTipStart: 'L\'aperçu actuel du morceau est en format texte, passer à un aperçu en format de questions-réponses va',
previewSwitchTipEnd: 'consommer des tokens supplémentaires',
characters: 'personnages',
indexSettedTip: 'Pour changer la méthode d\'index, veuillez aller à la',
retrivalSettedTip: 'Pour changer la méthode d\'index, veuillez aller à la',
datasetSettingLink: 'Paramètres de connaissance.',
},
stepThree: {
creationTitle: '🎉 Connaissance créée',
creationContent: 'Nous avons automatiquement nommé le Savoir, vous pouvez le modifier à tout moment',
label: 'Nom de la connaissance',
additionTitle: '🎉 Document téléchargé',
additionP1: 'Le document a été téléchargé dans la Connaissance',
additionP2: ', vous pouvez le trouver dans la liste des documents de la Connaissance.',
stop: 'Arrêter le traitement',
resume: 'Reprendre le traitement',
navTo: 'Aller au document',
sideTipTitle: 'Qu\'est-ce qui suit ?',
sideTipContent: 'Après l\'indexation du document, la Connaissance peut être intégrée dans l\'application en tant que contexte, vous pouvez trouver le paramètre de contexte sur la page d\'orchestration de prompt. Vous pouvez également le créer en tant que plugin d\'indexation ChatGPT ind',
modelTitle: 'Êtes-vous sûr de vouloir arrêter l\'embedding ?',
modelContent: 'Si vous devez reprendre le traitement plus tard, vous continuerez à partir de l\'endroit où vous vous êtes arrêté.',
modelButtonConfirm: 'Confirmer',
modelButtonCancel: 'Annuler',
},
}
export default translation

View File

@ -0,0 +1,349 @@
const translation = {
list: {
title: 'Documents',
desc: 'Tous les fichiers de la Connaissance sont affichés ici, et l\'ensemble de la Connaissance peut être lié aux citations Dify ou indexé via le plugin Chat.',
addFile: 'ajouter un fichier',
addPages: 'Ajouter des Pages',
table: {
header: {
fileName: 'NOM DU FICHIER',
words: 'MOTS',
hitCount: 'NOMBRE DE RÉCUPÉRATIONS',
uploadTime: 'TEMPS DE TÉLÉCHARGEMENT',
status: 'STATUT',
action: 'ACTION',
},
},
action: {
uploadFile: 'Télécharger un nouveau fichier',
settings: 'Paramètres de segment',
addButton: 'Ajouter un morceau',
add: 'Ajouter un morceau',
batchAdd: 'Ajout en lot',
archive: 'Archive',
unarchive: 'Décompresser',
delete: 'Supprimer',
enableWarning: 'Le fichier archivé ne peut pas être activé',
sync: 'Synchroniser',
},
index: {
enable: 'Activer',
disable: 'Désactiver',
all: 'Tout',
enableTip: 'Le fichier peut être indexé',
disableTip: 'Le fichier ne peut pas être indexé',
},
status: {
queuing: 'Mise en file d\'attente',
indexing: 'Indexation',
paused: 'En pause',
error: 'Erreur',
available: 'Disponible',
enabled: 'Activé',
disabled: 'Désactivé',
archived: 'Archivé',
},
empty: {
title: 'Il n\'y a pas encore de documentation',
upload: {
tip: 'Vous pouvez télécharger des fichiers, synchroniser à partir du site web, ou à partir d\'applications web comme Notion, GitHub, etc.',
},
sync: {
tip: 'Dify téléchargera périodiquement des fichiers de votre Notion et terminera le traitement.',
},
},
delete: {
title: 'Êtes-vous sûr de vouloir supprimer ?',
content: 'Si vous avez besoin de reprendre le traitement plus tard, vous continuerez à partir de l\'endroit où vous vous êtes arrêté',
},
batchModal: {
title: 'Ajouter des lots de segments',
csvUploadTitle: 'Faites glisser et déposez votre fichier CSV ici, ou',
browse: 'parcourir',
tip: 'Le fichier CSV doit se conformer à la structure suivante :',
question: 'question',
answer: 'réponse',
contentTitle: 'contenu du bloc',
content: 'contenu',
template: 'Téléchargez le modèle ici',
cancel: 'Annuler',
run: 'Exécuter le lot',
runError: 'L\'exécution du lot a échoué',
processing: 'Dans le traitement par lots',
completed: 'Importation terminée',
error: 'Erreur d\'Importation',
ok: 'D\'accord',
},
},
metadata: {
title: 'Métadonnées',
desc: 'L\'étiquetage des métadonnées pour les documents permet à l\'IA d\'y accéder en temps opportun et expose la source des références pour les utilisateurs.',
dateTimeFormat: 'MMMM D, YYYY hh:mm A',
docTypeSelectTitle: 'Veuillez sélectionner un type de document',
docTypeChangeTitle: 'Changer le type de document',
docTypeSelectWarning:
'Si le type de document est modifié, les métadonnées actuellement remplies ne seront plus conservées',
firstMetaAction: 'Allons-y',
placeholder: {
add: 'Ajouter',
select: 'Sélectionner',
},
source: {
upload_file: 'Télécharger le fichier',
notion: 'Synchroniser le formulaire depuis Notion',
github: 'Synchroniser à partir de Github',
},
type: {
book: 'Livre',
webPage: 'Page Web',
paper: 'Papier',
socialMediaPost: 'Publication sur les Réseaux Sociaux',
personalDocument: 'Document Personnel',
businessDocument: 'Document Commercial',
IMChat: 'Chat IM',
wikipediaEntry: 'Entrée Wikipédia',
notion: 'Synchroniser depuis Notion',
github: 'Synchroniser depuis Github',
technicalParameters: 'Paramètres Techniques',
},
field: {
processRule: {
processDoc: 'Document de Processus',
segmentRule: 'Règle de Segment',
segmentLength: 'Longueur des Morceaux',
processClean: 'Processus de Nettoyage du Texte',
},
book: {
title: 'Titre',
language: 'Langue',
author: 'Auteur',
publisher: 'Éditeur',
publicationDate: 'Date de publication',
ISBN: 'ISBN',
category: 'Catégorie',
},
webPage: {
title: 'Titre',
url: 'URL',
language: 'Langue',
authorPublisher: 'Auteur/Éditeur',
publishDate: 'Date de publication',
topicsKeywords: 'Sujets/Mots-clés',
description: 'Description',
},
paper: {
title: 'Titre',
language: 'Langue',
author: 'Auteur',
publishDate: 'Date de publication',
journalConferenceName: 'Nom du Journal/Conférence',
volumeIssuePage: 'Volume/Numéro/Page',
DOI: 'DOI',
topicsKeywords: 'Sujets/Mots-clés',
abstract: 'Résumé',
},
socialMediaPost: {
platform: 'Plateforme',
authorUsername: 'Auteur/Nom d\'utilisateur',
publishDate: 'Date de publication',
postURL: 'URL de publication',
topicsTags: 'Sujets/Tags',
},
personalDocument: {
title: 'Titre',
author: 'Auteur',
creationDate: 'Date de Création',
lastModifiedDate: 'Date de Dernière Modification',
documentType: 'Type de Document',
tagsCategory: 'Tags/Catégorie',
},
businessDocument: {
title: 'Titre',
author: 'Auteur',
creationDate: 'Date de création',
lastModifiedDate: 'Date de Dernière Modification',
documentType: 'Type de Document',
departmentTeam: 'Département/Équipe',
},
IMChat: {
chatPlatform: 'Plateforme de Chat',
chatPartiesGroupName: 'Nom du groupe/Parties de discussion',
participants: 'Participants',
startDate: 'Date de Début',
endDate: 'Date de fin',
topicsKeywords: 'Sujets/Mots-clés',
fileType: 'Type de fichier',
},
wikipediaEntry: {
title: 'Titre',
language: 'Langue',
webpageURL: 'URL de la page web',
editorContributor: 'Éditeur/Contributeur',
lastEditDate: 'Date de dernière modification',
summaryIntroduction: 'Résumé/Introduction',
},
notion: {
title: 'Titre',
language: 'Langue',
author: 'Auteur',
createdTime: 'Heure de création',
lastModifiedTime: 'Dernière Modification',
url: 'URL',
tag: 'Étiquette',
description: 'Description',
},
github: {
repoName: 'Nom du dépôt',
repoDesc: 'Description du dépôt',
repoOwner: 'Propriétaire du dépôt',
fileName: 'Nom du Fichier',
filePath: 'Chemin du fichier',
programmingLang: 'Langage de programmation',
url: 'URL',
license: 'Licence',
lastCommitTime: 'Heure du dernier commit',
lastCommitAuthor: 'Auteur du dernier commit',
},
originInfo: {
originalFilename: 'Nom de fichier original',
originalFileSize: 'Taille originale du fichier',
uploadDate: 'Date de téléchargement',
lastUpdateDate: 'Date de dernière mise à jour',
source: 'Source',
},
technicalParameters: {
segmentSpecification: 'Spécification des morceaux',
segmentLength: 'Longueur des morceaux',
avgParagraphLength: 'Longueur moyenne de paragraphe',
paragraphs: 'Paragraphes',
hitCount: 'Nombre de récupérations',
embeddingTime: 'Temps d\'incorporation',
embeddedSpend: 'Dépenses intégrées',
},
},
languageMap: {
zh: 'Chinois',
en: 'Anglais',
es: 'Espagnol',
fr: 'Français',
de: 'Allemand',
ja: 'Japonais',
ko: 'Coréen',
ru: 'Russe',
ar: 'Arabe',
pt: 'Portugais',
it: 'Italien',
nl: 'Néerlandais',
pl: 'Polonais',
sv: 'Suédois',
tr: 'Turc',
he: 'Hébreu',
hi: 'Hindi',
da: 'Danois',
fi: 'Finlandais',
no: 'Norvégien',
hu: 'Hongrois',
el: 'Grec',
cs: 'Tchèque',
th: 'Thaï',
id: 'Indonésien',
},
categoryMap: {
book: {
fiction: 'Fiction',
biography: 'Biographie',
history: 'Histoire',
science: 'Science',
technology: 'Technologie',
education: 'Éducation',
philosophy: 'Philosophie',
religion: 'Religion',
socialSciences: 'Sciences Sociales',
art: 'Art',
travel: 'Voyage',
health: 'Santé',
selfHelp: 'AutoAssistance',
businessEconomics: 'Économie d\'entreprise',
cooking: 'Cuisson',
childrenYoungAdults: 'EnfantsJeunesAdultes',
comicsGraphicNovels: 'BandesDessinéesRomansGraphiques',
poetry: 'Poésie',
drama: 'Drame',
other: 'Autre',
},
personalDoc: {
notes: 'Notes',
blogDraft: 'Brouillon de Blog',
diary: 'Journal',
researchReport: 'Rapport de Recherche',
bookExcerpt: 'Extrait de livre',
schedule: 'Programme',
list: 'Liste',
projectOverview: 'Aperçu du Projet',
photoCollection: 'Collection de Photos',
creativeWriting: 'Écriture Créative',
codeSnippet: 'Extrait de Code',
designDraft: 'Projet de Conception',
personalResume: 'Curriculum Vitae Personnel',
other: 'Autre',
},
businessDoc: {
meetingMinutes: 'Compte-rendu de Réunion',
researchReport: 'Rapport de Recherche',
proposal: 'Proposition',
employeeHandbook: 'Manuel de l\'employé',
trainingMaterials: 'Matériaux de Formation',
requirementsDocument: 'Document de Spécifications',
designDocument: 'Document de Conception',
productSpecification: 'Spécification du produit',
financialReport: 'Rapport Financier',
marketAnalysis: 'Analyse de marché',
projectPlan: 'Plan de Projet',
teamStructure: 'Structure de l\'équipe',
policiesProcedures: 'Politiques & Procédures',
contractsAgreements: 'Contrats & Accords',
emailCorrespondence: 'Correspondance par Email',
other: 'Autre',
},
},
},
embedding: {
processing: 'Traitement des embeddings...',
paused: 'Intégration en pause',
completed: 'Intégration terminée',
error: 'Erreur d\'embedding',
docName: 'Prétraitement du document',
mode: 'Règle de segmentation',
segmentLength: 'Longueur des morceaux',
textCleaning: 'Pré-définition du texte et nettoyage',
segments: 'Paragraphes',
highQuality: 'Mode haute qualité',
economy: 'Mode économique',
estimate: 'Consommation estimée',
stop: 'Arrêtez le traitement',
resume: 'Reprendre le traitement',
automatic: 'Automatique',
custom: 'Personnalisé',
previewTip: 'L\'aperçu du paragraphe sera disponible après la fin de l\'embedding.',
},
segment: {
paragraphs: 'Paragraphes',
keywords: 'Mots Clés',
addKeyWord: 'Ajouter un mot-clé',
keywordError: 'La longueur maximale du mot-clé est de 20',
characters: 'personnages',
hitCount: 'Nombre de récupérations',
vectorHash: 'Vector hash: ',
questionPlaceholder: 'ajoutez la question ici',
questionEmpty: 'La question ne peut pas être vide',
answerPlaceholder: 'ajoutez une réponse ici',
answerEmpty: 'La réponse ne peut pas être vide',
contentPlaceholder: 'ajoutez du contenu ici',
contentEmpty: 'Le contenu ne peut pas être vide',
newTextSegment: 'Nouveau Segment de Texte',
newQaSegment: 'Nouveau Segment Q&R',
delete: 'Supprimer ce morceau ?',
},
}
export default translation

View File

@ -0,0 +1,28 @@
const translation = {
title: 'Test de Récupération',
desc: 'Testez l\'effet d\'impact de la Connaissance basée sur le texte de la requête donnée.',
dateTimeFormat: 'JJ/MM/AAAA hh:mm A',
recents: 'Récents',
table: {
header: {
source: 'Source',
text: 'Texte',
time: 'Temps',
},
},
input: {
title: 'Texte source',
placeholder: 'Veuillez entrer un texte, une phrase déclarative courte est recommandée.',
countWarning: 'Jusqu\'à 200 caractères.',
indexWarning: 'Connaissances de haute qualité uniquement.',
testing: 'Test',
},
hit: {
title: 'PARAGRAPHES DE RÉCUPÉRATION',
emptyTip: 'Les résultats des tests de récupération s\'afficheront ici',
},
noRecentTip: 'Aucun résultat de requête récent ici',
viewChart: 'Voir GRAPHIQUE VECTORIEL',
}
export default translation

View File

@ -0,0 +1,33 @@
const translation = {
title: 'Paramètres de connaissance',
desc: 'Ici, vous pouvez modifier les propriétés et les méthodes de fonctionnement de la Connaissance.',
form: {
name: 'Nom de la Connaissance',
namePlaceholder: 'Veuillez entrer le nom de la Connaissance',
nameError: 'Le nom ne peut pas être vide',
desc: 'Description des connaissances',
descInfo: 'Veuillez rédiger une description textuelle claire pour décrire le contenu de la Connaissance. Cette description sera utilisée comme base pour la correspondance lors de la sélection parmi plusieurs Connaissances pour l\'inférence.',
descPlaceholder: 'Décrivez ce qui se trouve dans cette Connaissance. Une description détaillée permet à l\'IA d\'accéder au contenu de la Connaissance en temps opportun. Si vide, Dify utilisera la stratégie de hit par défaut.',
descWrite: 'Apprenez comment rédiger une bonne description de connaissance.',
permissions: 'Autorisations',
permissionsOnlyMe: 'Seulement moi',
permissionsAllMember: 'Tous les membres de l\'équipe',
indexMethod: 'Méthode d\'Indexation',
indexMethodHighQuality: 'Haute Qualité',
indexMethodHighQualityTip: 'Appelez l\'interface d\'embedding d\'OpenAI pour le traitement afin de fournir une précision plus élevée lorsque les utilisateurs font une requête.',
indexMethodEconomy: 'Économique',
indexMethodEconomyTip: 'Utilisez des moteurs vectoriels hors ligne, des index de mots-clés, etc. pour réduire la précision sans dépenser de jetons',
embeddingModel: 'Modèle d\'Embedding',
embeddingModelTip: 'Changez le modèle intégré, veuillez aller à',
embeddingModelTipLink: 'Paramètres',
retrievalSetting: {
title: 'Paramètre de récupération',
learnMore: 'En savoir plus',
description: 'à propos de la méthode de récupération.',
longDescription: 'À propos de la méthode de récupération, vous pouvez la modifier à tout moment dans les paramètres de Connaissance.',
},
save: 'Enregistrer',
},
}
export default translation

47
web/i18n/fr-FR/dataset.ts Normal file
View File

@ -0,0 +1,47 @@
const translation = {
knowledge: 'Connaissance',
documentCount: ' documents',
wordCount: 'k mots',
appCount: ' applications liées',
createDataset: 'Créer des Connaissances',
createDatasetIntro: 'Importez vos propres données textuelles ou écrivez des données en temps réel via Webhook pour l\'amélioration du contexte LLM.',
deleteDatasetConfirmTitle: 'Supprimer cette Connaissance ?',
deleteDatasetConfirmContent:
'La suppression de la Connaissance est irréversible. Les utilisateurs ne pourront plus accéder à votre Savoir, et toutes les configurations de prompt et les journaux seront supprimés de façon permanente.',
datasetDeleted: 'Connaissance supprimée',
datasetDeleteFailed: 'Échec de la suppression de la Connaissance',
didYouKnow: 'Saviez-vous ?',
intro1: 'La Connaissance peut être intégrée dans l\'application Dify',
intro2: 'comme un contexte',
intro3: ',',
intro4: 'ou ça ',
intro5: 'peut être créé',
intro6: 'comme un plug-in d\'index ChatGPT autonome à publier',
unavailable: 'Indisponible',
unavailableTip: 'Le modèle d\'embedding n\'est pas disponible, le modèle d\'embedding par défaut doit être configuré',
datasets: 'CONNAISSANCE',
datasetsApi: 'API',
retrieval: {
semantic_search: {
title: 'Recherche Vectorielle',
description: 'Générez des embeddings de requête et recherchez le morceau de texte le plus similaire à sa représentation vectorielle.',
},
full_text_search: {
title: 'Recherche en Texte Intégral',
description: 'Indexez tous les termes dans le document, permettant aux utilisateurs de rechercher n\'importe quel terme et de récupérer le fragment de texte pertinent contenant ces termes.',
},
hybrid_search: {
title: 'Recherche Hybride',
description: 'Exécutez une recherche en texte intégral et des recherches vectorielles en même temps, réorganisez pour sélectionner la meilleure correspondance pour la requête de l\'utilisateur. La configuration de l\'API du modèle de réorganisation est nécessaire.',
recommend: 'Recommander',
},
invertedIndex: {
title: 'Index inversé',
description: 'L\'Index inversé est une structure utilisée pour une récupération efficace. Organisé par termes, chaque terme pointe vers des documents ou des pages web le contenant.',
},
change: 'Changer',
changeRetrievalMethod: 'Changer la méthode de récupération',
},
}
export default translation

41
web/i18n/fr-FR/explore.ts Normal file
View File

@ -0,0 +1,41 @@
const translation = {
title: 'Explorer',
sidebar: {
discovery: 'Découverte',
chat: 'Discussion',
workspace: 'Espace de travail',
action: {
pin: 'Épingle',
unpin: 'Détacher',
rename: 'Renommer',
delete: 'Supprimer',
},
delete: {
title: 'Supprimer l\'application',
content: 'Êtes-vous sûr de vouloir supprimer cette application ?',
},
},
apps: {
title: 'Explorez les applications par Dify',
description: 'Utilisez ces applications modèles instantanément ou personnalisez vos propres applications basées sur les modèles.',
allCategories: 'Toutes les catégories',
},
appCard: {
addToWorkspace: 'Ajouter à l\'espace de travail',
customize: 'Personnaliser',
},
appCustomize: {
title: 'Créer une application à partir de {{name}}',
subTitle: 'Icône de l\'application & nom',
nameRequired: 'Le nom de l\'application est requis',
},
category: {
Assistant: 'Assistant',
Writing: 'Écriture',
Translate: 'Traduire',
Programming: 'Programmation',
HR: 'RH',
},
}
export default translation

4
web/i18n/fr-FR/layout.ts Normal file
View File

@ -0,0 +1,4 @@
const translation = {
}
export default translation

59
web/i18n/fr-FR/login.ts Normal file
View File

@ -0,0 +1,59 @@
const translation = {
pageTitle: 'Salut, commençons !👋',
welcome: 'Bienvenue sur Dify, veuillez vous connecter pour continuer.',
email: 'Adresse e-mail',
emailPlaceholder: 'Votre email',
password: 'Mot de passe',
passwordPlaceholder: 'Votre mot de passe',
name: 'Nom d\'utilisateur',
namePlaceholder: 'Votre nom d\'utilisateur',
forget: 'Mot de passe oublié ?',
signBtn: 'Se connecter',
installBtn: 'Mettre en place',
setAdminAccount: 'Configuration d\'un compte administrateur',
setAdminAccountDesc: 'Privilèges maximum pour le compte administrateur, qui peut être utilisé pour créer des applications et gérer les fournisseurs de LLM, etc.',
createAndSignIn: 'Créer et se connecter',
oneMoreStep: 'Une étape de plus',
createSample: 'Sur la base de ces informations, nous créerons une application exemple pour vous',
invitationCode: 'Code d\'invitation',
invitationCodePlaceholder: 'Votre code d\'invitation',
interfaceLanguage: 'Langue de l\'interface',
timezone: 'Fuseau horaire',
go: 'Aller à Dify',
sendUsMail: 'Envoyez-nous votre introduction, et nous nous occuperons de la demande d\'invitation.',
acceptPP: 'J\'ai lu et j\'accepte la politique de confidentialité',
reset: 'Veuillez exécuter la commande suivante pour réinitialiser votre mot de passe',
withGitHub: 'Continuer avec GitHub',
withGoogle: 'Continuer avec Google',
rightTitle: 'Débloquez le plein potentiel des LLM',
rightDesc: 'Construisez sans effort des applications IA visuellement captivantes, opérationnelles et améliorables.',
tos: 'Conditions de Service',
pp: 'Politique de Confidentialité',
tosDesc: 'En vous inscrivant, vous acceptez nos',
donthave: 'Vous n\'avez pas ?',
invalidInvitationCode: 'Code d\'invitation invalide',
accountAlreadyInited: 'Compte déjà initialisé',
error: {
emailEmpty: 'Une adresse e-mail est requise',
emailInValid: 'Veuillez entrer une adresse email valide',
nameEmpty: 'Le nom est requis',
passwordEmpty: 'Un mot de passe est requis',
passwordInvalid: 'Le mot de passe doit contenir des lettres et des chiffres, et la longueur doit être supérieure à 8.',
},
license: {
tip: 'Avant de commencer Dify Community Edition, lisez le GitHub',
link: 'Licence Open-source',
},
join: 'Rejoindre',
joinTipStart: 'Je vous invite à rejoindre',
joinTipEnd: 'équipe sur Dify',
invalid: 'Le lien a expiré',
explore: 'Explorez Dify',
activatedTipStart: 'Vous avez rejoint le',
activatedTipEnd: 'équipe',
activated: 'Connectez-vous maintenant',
adminInitPassword: 'Mot de passe d\'initialisation de l\'administrateur',
validate: 'Valider',
}
export default translation

View File

@ -0,0 +1,4 @@
const translation = {
}
export default translation

View File

@ -0,0 +1,74 @@
const translation = {
common: {
welcome: 'Bienvenue à l\'utilisation',
appUnavailable: 'L\'application n\'est pas disponible',
appUnkonwError: 'L\'application n\'est pas disponible',
},
chat: {
newChat: 'Nouveau chat',
pinnedTitle: 'Épinglé',
unpinnedTitle: 'Discussions',
newChatDefaultName: 'Nouvelle conversation',
resetChat: 'Réinitialiser la conversation',
powerBy: 'Propulsé par',
prompt: 'Prompt',
privatePromptConfigTitle: 'Paramètres de conversation',
publicPromptConfigTitle: 'Prompt Initial',
configStatusDes: 'Avant de commencer, vous pouvez modifier les paramètres de conversation',
configDisabled:
'Les paramètres de la session précédente ont été utilisés pour cette session.',
startChat: 'Commencer le Chat',
privacyPolicyLeft:
'Veuillez lire',
privacyPolicyMiddle:
'politique de confidentialité',
privacyPolicyRight:
'fourni par le développeur de l\'application.',
deleteConversation: {
title: 'Supprimer la conversation',
content: 'Êtes-vous sûr de vouloir supprimer cette conversation ?',
},
tryToSolve: 'Essayez de résoudre',
temporarySystemIssue: 'Désolé, problème temporaire du système.',
},
generation: {
tabs: {
create: 'Exécuter une fois',
batch: 'Exécuter le lot',
saved: 'Enregistré',
},
savedNoData: {
title: 'Vous n\'avez pas encore enregistré de résultat !',
description: 'Commencez à générer du contenu et retrouvez vos résultats sauvegardés ici.',
startCreateContent: 'Commencez à créer du contenu',
},
title: 'Complétion IA',
queryTitle: 'Contenu de la requête',
completionResult: 'Résultat de la complétion',
queryPlaceholder: 'Rédigez le contenu de votre requête...',
run: 'Exécuter',
copy: 'Copier',
resultTitle: 'Complétion IA',
noData: 'L\'IA vous donnera ce que vous voulez ici.',
csvUploadTitle: 'Faites glisser et déposez votre fichier CSV ici, ou',
browse: 'parcourir',
csvStructureTitle: 'Le fichier CSV doit se conformer à la structure suivante :',
downloadTemplate: 'Téléchargez le modèle ici',
field: 'Champ',
batchFailed: {
info: '{{num}} exécutions échouées',
retry: 'Réessayer',
outputPlaceholder: 'Aucun contenu de sortie',
},
errorMsg: {
empty: 'Veuillez entrer le contenu dans le fichier téléchargé.',
fileStructNotMatch: 'Le fichier CSV téléchargé ne correspond pas à la structure.',
emptyLine: 'La ligne {{rowIndex}} est vide',
invalidLine: 'Row {{rowIndex}}: {{varName}} value can not be empty',
moreThanMaxLengthLine: 'Row {{rowIndex}}: {{varName}} value can not be more than {{maxLength}} characters',
atLeastOne: 'Veuillez entrer au moins une ligne dans le fichier téléchargé.',
},
},
}
export default translation

115
web/i18n/fr-FR/tools.ts Normal file
View File

@ -0,0 +1,115 @@
const translation = {
title: 'Outils',
createCustomTool: 'Créer un Outil Personnalisé',
type: {
all: 'Tout',
builtIn: 'Intégré',
custom: 'Personnalisé',
},
contribute: {
line1: 'Je suis intéressé par',
line2: 'contribuer des outils à Dify.',
viewGuide: 'Voir le guide',
},
author: 'Par',
auth: {
unauthorized: 'Pour Autoriser',
authorized: 'Autorisé',
setup: 'Mettez en place l\'autorisation à utiliser',
setupModalTitle: 'Configurer l\'Autorisation',
setupModalTitleDescription: 'Après avoir configuré les identifiants, tous les membres de l\'espace de travail peuvent utiliser cet outil lors de l\'orchestration des applications.',
},
includeToolNum: '{{num}} outils inclus',
addTool: 'Ajouter un outil',
createTool: {
title: 'Créer un Outil Personnalisé',
editAction: 'Configurer',
editTitle: 'Modifier l\'Outil Personnalisé',
name: 'Nom',
toolNamePlaceHolder: 'Entrez le nom de l\'outil',
schema: 'Schéma',
schemaPlaceHolder: 'Entrez votre schéma OpenAPI ici',
viewSchemaSpec: 'Voir la spécification OpenAPI-Swagger',
importFromUrl: 'Importer depuis l\'URL',
importFromUrlPlaceHolder: 'https://...',
urlError: 'Veuillez entrer une URL valide',
examples: 'Exemples',
exampleOptions: {
json: 'Météo(JSON)',
yaml: 'Animalerie (YAML)',
blankTemplate: 'Modèle Vierge',
},
availableTools: {
title: 'Outils Disponibles',
name: 'Nom',
description: 'Description',
method: 'Méthode',
path: 'Chemin',
action: 'Actions',
test: 'Test',
},
authMethod: {
title: 'Méthode d\'autorisation',
type: 'Type d\'autorisation',
keyTooltip: 'Clé de l\'en-tête HTTP. Vous pouvez la laisser telle quelle avec "Autorisation" si vous n\'avez aucune idée de ce que c\'est, ou la définir sur une valeur personnalisée.',
types: {
none: 'Aucun',
api_key: 'Clé API',
apiKeyPlaceholder: 'Nom de l\'en-tête HTTP pour la clé API',
apiValuePlaceholder: 'Entrez la clé API',
},
key: 'Clé',
value: 'Valeur',
},
authHeaderPrefix: {
title: 'Type d\'Authentification',
types: {
basic: 'Basique',
bearer: 'Porteur',
custom: 'Personnalisé',
},
},
privacyPolicy: 'Politique de confidentialité',
privacyPolicyPlaceholder: 'Veuillez entrer la politique de confidentialité',
},
test: {
title: 'Test',
parametersValue: 'Paramètres & Valeur',
parameters: 'Paramètres',
value: 'Valeur',
testResult: 'Résultats du Test',
testResultPlaceholder: 'Le résultat du test s\'affichera ici',
},
thought: {
using: 'Utilisation',
used: 'Utilisé',
requestTitle: 'Demande à',
responseTitle: 'Réponse de',
},
setBuiltInTools: {
info: 'Infos',
setting: 'Paramètres',
toolDescription: 'Description de l\'outil',
parameters: 'paramètres',
string: 'chaîne',
number: 'nombre',
required: 'Requis',
infoAndSetting: 'Infos & Paramètres',
},
noCustomTool: {
title: 'Pas d\'outils personnalisés !',
content: 'Ajoutez et gérez vos outils personnalisés ici pour construire des applications IA.',
createTool: 'Créer un outil',
},
noSearchRes: {
title: 'Désolé, aucun résultat !',
content: 'Nous n\'avons trouvé aucun outil correspondant à votre recherche.',
reset: 'Réinitialiser la recherche',
},
builtInPromptTitle: 'Invite',
toolRemoved: 'Outil supprimé',
notAuthorized: 'Outil non autorisé',
howToGet: 'Comment obtenir',
}
export default translation

View File

@ -16,6 +16,7 @@ export type I18nText = {
'ru-RU': string
'it-IT': string
'uk-UA': string
'vi-VN': string
}
export const languages = [
@ -47,7 +48,7 @@ export const languages = [
value: 'fr-FR',
name: 'Français(France)',
example: 'Bonjour, Dify!',
supported: false,
supported: true,
},
{
value: 'de-DE',
@ -97,6 +98,12 @@ export const languages = [
example: 'Привет, Dify!',
supported: true,
},
{
value: 'vi-VN',
name: 'Tiếng Việt(Việt Nam)',
example: 'Xin chào, Dify!',
supported: true,
},
]
export const LanguagesSupported = languages.filter(item => item.supported).map(item => item.value)
@ -119,6 +126,7 @@ export const NOTICE_I18N = {
ja_JP: '重要なお知らせ',
ko_KR: '중요 공지',
uk_UA: 'Важливе повідомлення',
vi_VN: 'Thông báo quan trọng',
},
desc: {
en_US: 'Our system will be unavailable from 19:00 to 24:00 UTC on August 28 for an upgrade. For questions, kindly contact our support team (support@dify.ai). We value your patience.',
@ -130,6 +138,7 @@ export const NOTICE_I18N = {
ja_JP: 'Our system will be unavailable from 19:00 to 24:00 UTC on August 28 for an upgrade. For questions, kindly contact our support team (support@dify.ai). We value your patience.',
ko_KR: 'Our system will be unavailable from 19:00 to 24:00 UTC on August 28 for an upgrade. For questions, kindly contact our support team (support@dify.ai). We value your patience.',
uk_UA: 'Наша система буде недоступна з 19:00 до 24:00 UTC 28 серпня для оновлення. Якщо у вас виникнуть запитання, будь ласка, зв’яжіться з нашою службою підтримки (support@dify.ai). Дякуємо за терпіння.',
vi_VN: 'Hệ thống của chúng tôi sẽ ngừng hoạt động từ 19:00 đến 24:00 UTC vào ngày 28 tháng 8 để nâng cấp. Nếu có thắc mắc, vui lòng liên hệ với nhóm hỗ trợ của chúng tôi (support@dify.ai). Chúng tôi đánh giá cao sự kiên nhẫn của bạn.',
},
href: '#',
}

77
web/i18n/script.js Normal file
View File

@ -0,0 +1,77 @@
/* eslint-disable no-eval */
const fs = require('node:fs')
const path = require('node:path')
const transpile = require('typescript').transpile
const targetLanguage = 'en-US'
const languages = ['zh-Hans', 'fr-FR', 'ja-JP', 'pt-BR', 'uk-UA', 'vi-VN']
async function getKeysFromLanuage(language) {
return new Promise((resolve, reject) => {
const folderPath = path.join(__dirname, language)
let allKeys = []
fs.readdir(folderPath, (err, files) => {
if (err) {
console.error('Error reading folder:', err)
reject(err)
return
}
files.forEach((file) => {
const filePath = path.join(folderPath, file)
const fileName = file.replace(/\.[^/.]+$/, '') // Remove file extension
const camelCaseFileName = fileName.replace(/[-_](.)/g, (_, c) =>
c.toUpperCase(),
) // Convert to camel case
// console.log(camelCaseFileName)
const content = fs.readFileSync(filePath, 'utf8')
const translation = eval(transpile(content))
const keys = Object.keys(translation)
const nestedKeys = []
const iterateKeys = (obj, prefix = '') => {
for (const key in obj) {
const nestedKey = prefix ? `${prefix}.${key}` : key
nestedKeys.push(nestedKey)
if (typeof obj[key] === 'object')
iterateKeys(obj[key], nestedKey)
}
}
iterateKeys(translation)
allKeys = [...keys, ...nestedKeys].map(
key => `${camelCaseFileName}.${key}`,
)
})
resolve(allKeys)
})
})
}
async function main() {
const compareKeysCount = async () => {
const targetKeys = await getKeysFromLanuage(targetLanguage)
const languagesKeys = await Promise.all(languages.map(language => getKeysFromLanuage(language)))
const keysCount = languagesKeys.map(keys => keys.length)
const targetKeysCount = targetKeys.length
const comparison = languages.reduce((result, language, index) => {
const languageKeysCount = keysCount[index]
const difference = targetKeysCount - languageKeysCount
result[language] = difference
return result
}, {})
console.log(comparison)
// Print missing keys
languages.forEach((language, index) => {
const missingKeys = targetKeys.filter(key => !languagesKeys[index].includes(key))
console.log(`Missing keys in ${language}:`, missingKeys)
})
}
compareKeysCount()
}
main()

View File

@ -0,0 +1,87 @@
const translation = {
title: 'Chú thích',
name: 'Chú thích cho câu Trả lời',
editBy: 'Câu trả lời được chỉnh sửa bởi {{author}}',
noData: {
title: 'Không có chú thích',
description: 'Bạn có thể chỉnh sửa chú thích trong phần gỡ lỗi ứng dụng hoặc nhập hàng loạt chú thích vào đây để có phản hồi chất lượng cao.',
},
table: {
header: {
question: 'câu hỏi',
answer: 'câu trả lời',
createdAt: 'tạo lúc',
hits: 'lượt truy cập',
actions: 'hành động',
addAnnotation: 'Thêm chú thích',
bulkImport: 'Nhập hàng loạt',
bulkExport: 'Xuất hoàng loạt',
clearAll: 'Xóa tất cả chú thích',
},
},
editModal: {
title: 'Chỉnh sửa chú thích Trả lời',
queryName: 'Truy vấn người dùng',
answerName: 'Câu chuyện của BOT',
yourAnswer: 'Câu trả lời của bạn',
answerPlaceholder: 'Nhập câu trả lời của bạn vào đây',
yourQuery: 'Truy vấn của bạn',
queryPlaceholder: 'Nhập truy vấn của bạn ở đây',
removeThisCache: 'Xóa chú thích này',
createdAt: 'Được tạo lúc',
},
addModal: {
title: 'Thêm chú thích Trả lời',
queryName: 'Câu hỏi',
answerName: 'Trả lời',
answerPlaceholder: 'Nhập câu trả lời vào đây',
queryPlaceholder: 'Nhập truy vấn ở đây',
createNext: 'Thêm một phản hồi có chú thích khác',
},
batchModal: {
title: 'Nhập hàng loạt',
csvUploadTitle: 'Kéo và thả tệp CSV của bạn vào đây hoặc ',
browse: 'duyệt',
tip: 'Tệp CSV phải tuân theo cấu trúc sau:',
question: 'câu hỏi',
answer: 'trả lời',
contentTitle: 'đoạn nội dung',
content: 'nội dung',
template: 'Tải mẫu tại đây',
cancel: 'Bỏ',
run: 'Run Batch',
runError: 'Run batch failed',
processing: 'In batch processing',
completed: 'Import completed',
error: 'Import Error',
ok: 'OK',
},
errorMessage: {
answerRequired: 'Câu trả lời là bắt buộc',
queryRequired: 'Câu hỏi là bắt buộc',
},
viewModal: {
annotatedResponse: 'Chú thích Trả lời',
hitHistory: 'Lịch sử lượt truy cập',
hit: 'Truy cập',
hits: 'Lượt truy cập',
noHitHistory: 'Không có lịch sử truy cập',
},
hitHistoryTable: {
query: 'Truy vấn',
match: 'Chính xác',
response: 'Phản ứng',
source: 'Nguồn',
score: 'Điểm',
time: 'Thời gian',
},
initSetup: {
title: 'Chú thích Trả lời Thiết lập ban đầu',
configTitle: 'Thiết lập trả lời chú thích',
confirmBtn: 'Lưu & Kích hoạt',
configConfirmBtn: 'Lưu',
},
embeddingModelSwitchTip: 'Mô hình vector hóa văn bản chú thích, mô hình chuyển đổi sẽ được nhúng lại, dẫn đến phát sinh thêm chi phí.',
}
export default translation

82
web/i18n/vi-VN/app-api.ts Normal file
View File

@ -0,0 +1,82 @@
const translation = {
apiServer: 'API Server',
apiKey: 'API Key',
status: 'Trạng thái',
disabled: 'Tắt',
ok: 'Đang hoạt động',
copy: 'Sao chép',
copied: 'Đã chép',
play: 'Chạy',
pause: 'Dừng',
playing: 'Đang chạy',
merMaind: {
rerender: 'Redo Rerender',
},
never: 'Không bao giờ',
apiKeyModal: {
apiSecretKey: 'API khoá bí mật',
apiSecretKeyTips: 'Để ngăn chặn việc lạm dụng API, hãy bảo vệ Khóa API của bạn. Tránh sử dụng nó dưới dạng văn bản thuần túy trong mã giao diện người dùng. :)',
createNewSecretKey: 'Tạo khóa bí mật mới',
secretKey: 'Khóa bí mật',
created: 'CREATED',
lastUsed: 'LAST USED',
generateTips: 'Giữ chìa khóa này ở nơi an toàn và dễ tiếp cận.',
},
actionMsg: {
deleteConfirmTitle: 'Xóa khóa bí mật này?',
deleteConfirmTips: 'Hành động này không thể được hoàn tác.',
ok: 'OK',
},
completionMode: {
title: 'Completion App API',
info: 'Đối với việc tạo văn bản chất lượng cao, như bài viết, tóm tắt và dịch thuật, hãy sử dụng API hoàn thành tin nhắn với đầu vào người dùng. Việc tạo văn bản dựa trên các thông số mô hình và mẫu đề xuất được thiết lập trong Dify Prompt Engineering.',
createCompletionApi: 'Tạo tin nhắn hoàn thành',
createCompletionApiTip: 'Tạo một tin nhắn hoàn thành để hỗ trợ chế độ câu hỏi và trả lời.',
inputsTips: '(Tùy chọn) Cung cấp các trường đầu vào người dùng dưới dạng cặp khóa-giá trị, tương ứng với các biến trong Prompt Eng. Khóa là tên biến, Giá trị là giá trị tham số. Nếu loại trường là Lựa chọn, Giá trị đã gửi phải là một trong các lựa chọn đã thiết lập trước.',
queryTips: 'Nội dung văn bản đầu vào của người dùng.',
blocking: 'Loại chặn, đợi để thực hiện hoàn tất và trả kết quả. (Yêu cầu có thể bị gián đoạn nếu quá trình kéo dài)',
streaming: 'trả về dữ liệu theo luồng. Thực hiện trả dữ liệu theo luồng dựa trên SSE (Sự kiện được gửi từ máy chủ).',
messageFeedbackApi: 'Phản hồi tin nhắn (thích)',
messageFeedbackApiTip: 'Đánh giá các tin nhắn nhận được thay mặt cho người dùng cuối với các lựa chọn thích hoặc không thích. Dữ liệu này hiển thị trên trang Nhật ký & Chú thích và được sử dụng cho việc điều chỉnh mô hình trong tương lai.',
messageIDTip: 'ID tin nhắn',
ratingTip: 'thích hoặc không thích, null là hủy bỏ',
parametersApi: 'Thu thập thông tin tham số ứng dụng',
parametersApiTip: 'Truy xuất các tham số Đầu vào được cấu hình, bao gồm tên biến, tên trường, loại và giá trị mặc định. Thường được sử dụng để hiển thị các trường này trong một biểu mẫu hoặc điền vào các giá trị mặc định sau khi máy khách tải.',
},
chatMode: {
title: 'Chat App API',
info: 'Đối với ứng dụng trò chuyện linh hoạt sử dụng định dạng Câu hỏi và Trả lời, gọi API tin nhắn trò chuyện để bắt đầu cuộc trò chuyện. Duy trì cuộc trò chuyện liên tục bằng cách chuyển conversation_id đã trả về. Các tham số phản hồi và mẫu phụ thuộc vào các cài đặt của Dify Prompt Eng.',
createChatApi: 'Tạo tin nhắn trò chuyện',
createChatApiTip: 'Tạo một tin nhắn trò chuyện mới hoặc tiếp tục một cuộc trò chuyện đang tồn tại.',
inputsTips: '(Tùy chọn) Cung cấp các trường đầu vào người dùng dưới dạng cặp khóa-giá trị, tương ứng với các biến trong Prompt Eng. Khóa là tên biến, Giá trị là giá trị tham số. Nếu loại trường là Lựa chọn, Giá trị đã gửi phải là một trong các lựa chọn đã thiết lập trước.',
queryTips: 'Nội dung câu hỏi của người dùng',
blocking: 'Loại chặn, đợi để thực hiện hoàn tất và trả kết quả. (Yêu cầu có thể bị gián đoạn nếu quá trình kéo dài)',
streaming: 'trả về dữ liệu theo luồng. Thực hiện trả dữ liệu theo luồng dựa trên SSE (Sự kiện được gửi từ máy chủ).',
conversationIdTip: '(Tùy chọn) ID cuộc trò chuyện: để trống cho cuộc trò chuyện lần đầu; chuyển conversation_id từ ngữ cảnh để tiếp tục cuộc trò chuyện.',
messageFeedbackApi: 'Phản hồi của người dùng cuối về tin nhắn, như',
messageFeedbackApiTip: 'Đánh giá các tin nhắn nhận được thay mặt cho người dùng cuối với các lựa chọn thích hoặc không thích. Dữ liệu này hiển thị trên trang Nhật ký & Chú thích và được sử dụng cho việc điều chỉnh mô hình trong tương lai.',
messageIDTip: 'ID tin nhắn',
ratingTip: 'thích hoặc không thích, null là hủy bỏ',
chatMsgHistoryApi: 'Lấy lịch sử tin nhắn trò chuyện',
chatMsgHistoryApiTip: 'Trang đầu tiên trả về `limit` tin nhắn mới nhất, được sắp xếp theo thứ tự ngược lại.',
chatMsgHistoryConversationIdTip: 'ID Cuộc trò chuyện',
chatMsgHistoryFirstId: 'ID của bản ghi trò chuyện đầu tiên trên trang hiện tại. Giá trị mặc định là không có.',
chatMsgHistoryLimit: 'Bao nhiêu cuộc trò chuyện được trả lại trong một yêu cầu',
conversationsListApi: 'Lấy danh sách cuộc trò chuyện',
conversationsListApiTip: 'Lấy danh sách phiên của người dùng hiện tại. Theo mặc định, trả về 20 phiên cuối cùng.',
conversationsListFirstIdTip: 'ID của bản ghi cuối cùng trên trang hiện tại, mặc định không có.',
conversationsListLimitTip: 'Bao nhiêu cuộc trò chuyện được trả lại trong một yêu cầu',
conversationRenamingApi: 'Đổi tên cuộc trò chuyện',
conversationRenamingApiTip: 'Đổi tên cuộc trò chuyện; tên sẽ được hiển thị trong giao diện nhiều phiên.',
conversationRenamingNameTip: 'Tên mới',
parametersApi: 'Thu thập thông tin tham số ứng dụng',
parametersApiTip: 'Truy xuất các tham số Đầu vào được cấu hình, bao gồm tên biến, tên trường, loại và giá trị mặc định. Thường được sử dụng để hiển thị các trường này trong một biểu mẫu hoặc điền vào các giá trị mặc định sau khi máy khách tải.',
},
develop: {
requestBody: 'Nội dung yêu cầu',
pathParams: 'Thông số đường dẫn',
query: 'Truy vấn',
},
}
export default translation

409
web/i18n/vi-VN/app-debug.ts Normal file
View File

@ -0,0 +1,409 @@
const translation = {
pageTitle: {
line1: 'PROMPT',
line2: 'Engineering',
},
orchestrate: 'Orchestrate',
promptMode: {
simple: 'Chuyển sang Chế độ Chuyên gia để chỉnh sửa toàn bộ PROMPT',
advanced: 'Chế độ Chuyên gia',
switchBack: 'Chuyển về',
advancedWarning: {
title: 'Bạn đã chuyển sang Chế độ Chuyên gia, và một khi bạn sửa đổi PROMPT, bạn KHÔNG THỂ quay lại chế độ cơ bản.',
description: 'Trong Chế độ Chuyên gia, bạn có thể chỉnh sửa toàn bộ PROMPT.',
learnMore: 'Tìm hiểu thêm',
ok: 'OK',
},
operation: {
addMessage: 'Thêm Tin nhắn',
},
contextMissing: 'Thiếu thành phần Ngữ cảnh, hiệu quả của prompt có thể không tốt.',
},
operation: {
applyConfig: 'Xuất bản',
resetConfig: 'Đặt lại',
debugConfig: 'Gỡ lỗi',
addFeature: 'Thêm Tính năng',
automatic: 'Tự động',
stopResponding: 'Dừng phản hồi',
agree: 'thích',
disagree: 'không thích',
cancelAgree: 'Hủy thích',
cancelDisagree: 'Hủy không thích',
userAction: 'Người dùng ',
},
notSetAPIKey: {
title: 'Khóa nhà cung cấp LLM chưa được đặt',
trailFinished: 'Kết thúc dấu vết',
description: 'Khóa nhà cung cấp LLM chưa được đặt, và cần được đặt trước khi gỡ lỗi.',
settingBtn: 'Đi đến cài đặt',
},
trailUseGPT4Info: {
title: 'Hiện không hỗ trợ gpt-4',
description: 'Sử dụng gpt-4, vui lòng đặt API Key.',
},
feature: {
groupChat: {
title: 'Nâng cao trò chuyện',
description: 'Thêm cài đặt trước cuộc trò chuyện cho ứng dụng có thể cải thiện trải nghiệm người dùng.',
},
groupExperience: {
title: 'Nâng cao trải nghiệm',
},
conversationOpener: {
title: 'Khởi động cuộc trò chuyện',
description: 'Trong một ứng dụng trò chuyện, câu nói đầu tiên mà AI tự động nói với người dùng thường được sử dụng như một lời chào.',
},
suggestedQuestionsAfterAnswer: {
title: 'Theo dõi',
description: 'Thiết lập đề xuất câu hỏi tiếp theo có thể mang lại trò chuyện tốt hơn cho người dùng.',
resDes: '3 đề xuất cho câu hỏi tiếp theo của người dùng.',
tryToAsk: 'Thử hỏi',
},
moreLikeThis: {
title: 'Nhiều hơn như vậy',
description: 'Tạo nhiều văn bản cùng một lúc, và sau đó chỉnh sửa và tiếp tục tạo ra.',
generateNumTip: 'Số lượng mỗi lần tạo ra',
tip: 'Sử dụng tính năng này sẽ tốn thêm token.',
},
speechToText: {
title: 'Chuyển đổi Giọng nói thành Văn bản',
description: 'Một khi được bật, bạn có thể sử dụng đầu vào giọng nói.',
resDes: 'Đầu vào Giọng nói đã được bật',
},
textToSpeech: {
title: 'Chuyển đổi Văn bản thành Giọng nói',
description: 'Một khi được bật, văn bản có thể được chuyển đổi thành giọng nói.',
resDes: 'Chuyển đổi Văn bản thành Âm thanh đã được bật',
},
citation: {
title: 'Trích dẫn và Ghi chú',
description: 'Một khi được bật, hiển thị tài liệu nguồn và phần được ghi nhận của nội dung được tạo ra.',
resDes: 'Trích dẫn và Ghi chú đã được bật',
},
annotation: {
title: 'Phản hồi Chú thích',
description: 'Bạn có thể thêm phản hồi chất lượng cao vào bộ nhớ cache để ưu tiên phù hợp với các câu hỏi của người dùng tương tự.',
resDes: 'Phản hồi Chú thích đã được bật',
scoreThreshold: {
title: 'Ngưỡng Điểm',
description: 'Được sử dụng để đặt ngưỡng tương đồng cho phản hồi chú thích.',
easyMatch: 'Tương đồng Dễ dàng',
accurateMatch: 'Tương đồng Chính xác',
},
matchVariable: {
title: 'Biến Phù hợp',
choosePlaceholder: 'Chọn biến phù hợp',
},
cacheManagement: 'Chú thích',
cached: 'Đã ghi chú',
remove: 'Xóa',
removeConfirm: 'Xóa chú thích này?',
add: 'Thêm chú thích',
edit: 'Chỉnh sửa chú thích',
},
dataSet: {
title: 'Ngữ cảnh',
noData: 'Bạn có thể nhập Dữ liệu như là ngữ cảnh',
words: 'Từ',
textBlocks: 'Khối Văn bản',
selectTitle: 'Chọn Kiến thức tham khảo',
selected: 'Kiến thức đã chọn',
noDataSet: 'Không tìm thấy Kiến thức',
toCreate: 'Đi tới tạo mới',
notSupportSelectMulti: 'Hiện chỉ hỗ trợ một Kiến thức',
queryVariable: {
title: 'Biến Truy vấn',
tip: 'Biến này sẽ được sử dụng làm đầu vào truy vấn cho việc truy xuất ngữ cảnh, lấy thông tin ngữ cảnh liên quan đến đầu vào của biến này.',
choosePlaceholder: 'Chọn biến truy vấn',
noVar: 'Không có biến',
noVarTip: 'xin vui lòng tạo một biến dưới phần Biến',
unableToQueryDataSet: 'Không thể truy vấn Kiến thức',
unableToQueryDataSetTip: 'Không thể truy vấn Kiến thức thành công, vui lòng chọn một biến truy vấn ngữ cảnh trong phần ngữ cảnh.',
ok: 'OK',
contextVarNotEmpty: 'biến truy vấn ngữ cảnh không thể trống',
deleteContextVarTitle: 'Xóa biến “{{varName}}”?',
deleteContextVarTip: 'Biến này đã được thiết lập là biến truy vấn ngữ cảnh, và việc loại bỏ nó sẽ ảnh hưởng đến việc sử dụng bình thường của Kiến thức. Nếu bạn vẫn cần xóa nó, vui lòng chọn lại nó trong phần ngữ cảnh.',
},
},
tools: {
title: 'Công cụ',
tips: 'Công cụ cung cấp một phương thức gọi API chuẩn, lấy đầu vào người dùng hoặc biến làm tham số yêu cầu để truy vấn dữ liệu bên ngoài như ngữ cảnh.',
toolsInUse: '{{count}} công cụ đang được sử dụng',
modal: {
title: 'Công cụ',
toolType: {
title: 'Loại Công cụ',
placeholder: 'Vui lòng chọn loại công cụ',
},
name: {
title: 'Tên',
placeholder: 'Vui lòng nhập tên',
},
variableName: {
title: 'Tên Biến',
placeholder: 'Vui lòng nhập tên biến',
},
},
},
conversationHistory: {
title: 'Lịch sử Cuộc trò chuyện',
description: 'Đặt tên tiền tố cho các vai trò trong cuộc trò chuyện',
tip: 'Lịch sử Cuộc trò chuyện chưa được bật, vui lòng thêm <histories> vào phần prompt ở trên.',
learnMore: 'Tìm hiểu thêm',
editModal: {
title: 'Chỉnh sửa Tên Vai trò Cuộc trò chuyện',
userPrefix: 'Tiền tố Người dùng',
assistantPrefix: 'Tiền tố Trợ lý',
},
},
toolbox: {
title: 'HỘP CÔNG CỤ',
},
moderation: {
title: 'Kiểm duyệt nội dung',
description: 'Bảo vệ đầu ra của mô hình bằng cách sử dụng API kiểm duyệt hoặc duy trì một danh sách từ nhạy cảm.',
allEnabled: 'Nội dung ĐẦU VÀO/ĐẦU RA Đã Bật',
inputEnabled: 'Nội dung ĐẦU VÀO Đã Bật',
outputEnabled: 'Nội dung ĐẦU RA Đã Bật',
modal: {
title: 'Cài đặt kiểm duyệt nội dung',
provider: {
title: 'Nhà cung cấp',
openai: 'Kiểm duyệt OpenAI',
openaiTip: {
prefix: 'Kiểm duyệt OpenAI yêu cầu một khóa API OpenAI được cấu hình trong ',
suffix: '.',
},
keywords: 'Từ khóa',
},
keywords: {
tip: 'Mỗi dòng một từ khóa, phân tách bằng các dòng. Tối đa 100 ký tự mỗi dòng.',
placeholder: 'Mỗi dòng một từ khóa, phân tách bằng các dòng',
line: 'Dòng',
},
content: {
input: 'Kiểm duyệt Nội dung ĐẦU VÀO',
output: 'Kiểm duyệt Nội dung ĐẦU RA',
preset: 'Câu trả lời mẫu',
placeholder: 'Nội dung câu trả lời mẫu ở đây',
condition: 'Đã bật ít nhất một kiểm duyệt nội dung ĐẦU VÀO và ĐẦU RA',
fromApi: 'Câu trả lời mẫu được trả về bởi API',
errorMessage: 'Câu trả lời mẫu không thể trống',
supportMarkdown: 'Hỗ trợ Markdown',
},
openaiNotConfig: {
before: 'Kiểm duyệt OpenAI yêu cầu một khóa API OpenAI được cấu hình trong',
after: '',
},
},
},
},
automatic: {
title: 'Tự động hóa triển khai ứng dụng',
description: 'Mô tả tình huống của bạn, Dify sẽ tự động hóa một ứng dụng cho bạn.',
intendedAudience: 'Ai là đối tượng mục tiêu?',
intendedAudiencePlaceHolder: 'ví dụ: Sinh viên',
solveProblem: 'Họ hy vọng AI có thể giải quyết vấn đề gì cho họ?',
solveProblemPlaceHolder: 'ví dụ: Đánh giá thành tích học tập',
generate: 'Tạo ra',
audiencesRequired: 'Yêu cầu Đối tượng mục tiêu',
problemRequired: 'Vấn đề cần thiết',
resTitle: 'Chúng tôi đã tự động hóa ứng dụng sau đây cho bạn.',
apply: 'Áp dụng tự động hóa này',
noData: 'Mô tả tình huống sử dụng của bạn ở bên trái, xem trước tự động hóa sẽ hiển thị ở đây.',
loading: 'Tự động hóa ứng dụng cho bạn...',
overwriteTitle: 'Ghi đè cấu hình hiện tại?',
overwriteMessage: 'Áp dụng tự động hóa này sẽ ghi đè lên cấu hình hiện tại.',
},
resetConfig: {
title: 'Xác nhận đặt lại?',
message:
'Đặt lại sẽ loại bỏ các thay đổi, khôi phục cấu hình đã xuất bản lần cuối.',
},
errorMessage: {
nameOfKeyRequired: 'tên của khóa: {{key}} được yêu cầu',
valueOfVarRequired: 'giá trị {{key}} không thể trống',
queryRequired: 'Văn bản yêu cầu được yêu cầu.',
waitForResponse:
'Vui lòng đợi phản hồi của tin nhắn trước để hoàn thành.',
waitForBatchResponse:
'Vui lòng đợi phản hồi của tác vụ hàng loạt để hoàn thành.',
notSelectModel: 'Vui lòng chọn một mô hình',
waitForImgUpload: 'Vui lòng đợi hình ảnh được tải lên',
},
chatSubTitle: 'Hướng dẫn',
completionSubTitle: 'Tiền Tố Lời Nhắc',
promptTip:
'Lời nhắc hướng dẫn các phản hồi của AI với hướng dẫn và ràng buộc. Chèn biến như {{input}}. Lời nhắc này sẽ không được hiển thị cho người dùng.',
formattingChangedTitle: 'Định dạng đã thay đổi',
formattingChangedText:
'Thay đổi định dạng sẽ đặt lại khu vực gỡ lỗi, bạn có chắc chắn không?',
variableTitle: 'Biến',
variableTip:
'Người dùng điền các biến vào một biểu mẫu, tự động thay thế các biến trong lời nhắc.',
notSetVar: 'Biến cho phép người dùng giới thiệu các từ khóa lời nhắc hoặc mở đầu khi điền vào biểu mẫu. Bạn có thể thử nhập "{{input}}" trong các từ khóa lời nhắc.',
autoAddVar: 'Biến không xác định được tham chiếu trong tiền-lời nhắc, bạn có muốn thêm chúng vào biểu mẫu đầu vào người dùng không?',
variableTable: {
key: 'Khóa Biến',
name: 'Tên Trường Nhập Liệu Người Dùng',
optional: 'Tùy chọn',
type: 'Loại Nhập Liệu',
action: 'Hành động',
typeString: 'Chuỗi',
typeSelect: 'Chọn',
},
varKeyError: {
canNoBeEmpty: 'Khóa biến không thể trống',
tooLong: 'Khóa biến: {{key}} quá dài. Không thể dài hơn 30 ký tự',
notValid: 'Khóa biến: {{key}} không hợp lệ. Chỉ có thể chứa chữ cái, số, và dấu gạch dưới',
notStartWithNumber: 'Khóa biến: {{key}} không thể bắt đầu bằng số',
keyAlreadyExists: 'Khóa biến: :{{key}} đã tồn tại',
},
otherError: {
promptNoBeEmpty: 'Lời nhắc không thể trống',
historyNoBeEmpty: 'Lịch sử cuộc trò chuyện phải được thiết lập trong lời nhắc',
queryNoBeEmpty: 'Truy vấn phải được thiết lập trong lời nhắc',
},
variableConig: {
modalTitle: 'Thiết lập trường',
description: 'Thiết lập cho biến {{varName}}',
fieldType: 'Loại Trường',
string: 'Văn Bản Ngắn',
paragraph: 'Đoạn Văn',
select: 'Chọn',
notSet: 'Không được thiết lập, hãy thử nhập {{input}} vào lời nhắc tiền.',
stringTitle: 'Tùy chọn hộp văn bản biểu mẫu',
maxLength: 'Độ dài Tối đa',
options: 'Tùy chọn',
addOption: 'Thêm tùy chọn',
apiBasedVar: 'Biến Dựa trên API',
},
vision: {
name: 'Tầm nhìn',
description: 'Cho phép tầm nhìn sẽ cho phép mô hình nhận hình ảnh và trả lời các câu hỏi về chúng.',
settings: 'Cài đặt',
visionSettings: {
title: 'Cài đặt Tầm nhìn',
resolution: 'Độ phân giải',
resolutionTooltip: `Độ phân giải thấp sẽ cho phép mô hình nhận một phiên bản hình ảnh 512 x 512 thấp hơn, và đại diện cho hình ảnh với ngân sách 65 token. Điều này cho phép API trả về phản hồi nhanh hơn và tiêu thụ ít token đầu vào cho các trường hợp sử dụng không yêu cầu chi tiết cao.
\n
đ phân giải cao sẽ đu tiên cho phép hình nhìn thấy hình nh thấp hơn sau đó tạo ra các cắt chi tiết của hình nh đu vào dưới dạng hình vuông 512px dựa trên kích thước hình nh đu vào. Mỗi cắt chi tiết sử dụng hai lần ngân sách token cho tổng cộng 129 token.`,
high: 'Cao',
low: 'Thấp',
uploadMethod: 'Phương thức Tải lên',
both: 'Cả hai',
localUpload: 'Tải lên Nội bộ',
url: 'URL',
uploadLimit: 'Giới hạn Tải lên',
},
},
voice: {
name: 'Giọng nói',
defaultDisplay: 'Giọng mặc định',
description: 'Cài đặt giọng nói văn bản thành tiếng',
settings: 'Cài đặt',
voiceSettings: {
title: 'Cài đặt Giọng nói',
language: 'Ngôn ngữ',
resolutionTooltip: 'Giọng nói văn bản hỗ trợ ngôn ngữ。',
voice: 'Giọng',
},
},
openingStatement: {
title: 'Mở đầu Trò chuyện',
add: 'Thêm',
writeOpner: 'Viết câu mở đầu',
placeholder: 'Viết thông điệp mở đầu của bạn ở đây, bạn có thể sử dụng biến, hãy thử nhập {{biến}}.',
openingQuestion: 'Câu Hỏi Mở đầu',
noDataPlaceHolder:
'Bắt đầu cuộc trò chuyện với người dùng có thể giúp AI thiết lập một mối quan hệ gần gũi hơn với họ trong các ứng dụng trò chuyện.',
varTip: 'Bạn có thể sử dụng biến, hãy thử nhập {{biến}}',
tooShort: 'Ít nhất 20 từ của lời nhắc ban đầu được yêu cầu để tạo ra các lời nhận đầu tiên cho cuộc trò chuyện.',
notIncludeKey: 'Lời nhắc ban đầu không bao gồm biến: {{khóa}}. Vui lòng thêm nó vào lời nhắc ban đầu.',
},
modelConfig: {
model: 'Mô hình',
setTone: 'Thiết lập tông của phản hồi',
title: 'Mô hình và Tham số',
modeType: {
chat: 'Trò chuyện',
completion: 'Hoàn thành',
},
},
inputs: {
title: 'Gỡ Lỗi và Xem Trước',
noPrompt: 'Hãy thử viết một số lời nhắc trong trường tiền-lời nhắc',
userInputField: 'Trường Nhập Liệu Người Dùng',
noVar: 'Điền vào giá trị của biến, nó sẽ tự động thay thế từ khóa lời nhắc mỗi khi bắt đầu phiên mới.',
chatVarTip:
'Điền vào giá trị của biến, nó sẽ tự động thay thế từ khóa lời nhắc mỗi khi bắt đầu phiên mới',
completionVarTip:
'Điền vào giá trị của biến, nó sẽ tự động thay thế từ khóa lời nhắc mỗi khi một câu hỏi được gửi.',
previewTitle: 'Xem Trước Lời Nhắc',
queryTitle: 'Nội dung Truy vấn',
queryPlaceholder: 'Vui lòng nhập văn bản yêu cầu.',
run: 'CHẠY',
},
result: 'Văn bản Đầu Ra',
datasetConfig: {
settingTitle: 'Cài đặt Truy xuất',
retrieveOneWay: {
title: 'N-to-1 Truy xuất',
description: 'Dựa trên ý định của người dùng và mô tả Kiến thức, Agent tự động chọn Kiến thức tốt nhất để truy vấn. Tốt nhất cho các ứng dụng có Kiến thức cụ thể, giới hạn.',
},
retrieveMultiWay: {
title: 'Truy xuất đa hướng',
description: 'Dựa trên ý định của người dùng, truy vấn qua tất cả Kiến thức, truy xuất văn bản liên quan từ nhiều nguồn và chọn ra kết quả tốt nhất phù hợp với truy vấn của người dùng sau khi sắp xếp lại. Yêu cầu cấu hình của API Rerank model.',
},
rerankModelRequired: 'Rerank model là bắt buộc',
params: 'Tham số',
top_k: 'Top K',
top_kTip: 'Sử dụng để lọc các phần chính xác nhất với các câu hỏi của người dùng. Hệ thống cũng sẽ tự động điều chỉnh giá trị của Top K, theo max_tokens của mô hình đã chọn.',
score_threshold: 'Ngưỡng Điểm',
score_thresholdTip: 'Sử dụng để thiết lập ngưỡng tương đồng cho việc lọc các phần.',
retrieveChangeTip: 'Thay đổi chế độ chỉ mục và chế độ truy xuất có thể ảnh hưởng đến các ứng dụng liên quan đến Kiến thức này.',
},
debugAsSingleModel: 'Gỡ Lỗi như Một Mô hình',
debugAsMultipleModel: 'Gỡ Lỗi như Nhiều Mô hình',
duplicateModel: 'Sao chép',
publishAs: 'Xuất bản dưới dạng',
assistantType: {
name: 'Loại Trợ lý',
chatAssistant: {
name: 'Trợ lý Cơ bản',
description: 'Xây dựng một trợ lý dựa trên trò chuyện sử dụng một Mô hình Ngôn ngữ Lớn.',
},
agentAssistant: {
name: 'Trợ lý Tác nhân',
description: 'Xây dựng một Tác nhân thông minh có thể tự động chọn các công cụ để hoàn thành các nhiệm vụ.',
},
},
agent: {
agentMode: 'Chế độ Tác nhân',
agentModeDes: 'Thiết lập loại chế độ suy luận cho tác nhân',
agentModeType: {
ReACT: 'ReAct',
functionCall: 'Gọi Hàm',
},
setting: {
name: 'Thiết lập Tác nhân',
description: 'Thiết lập Tác nhân cho phép thiết lập chế độ tác nhân và các tính năng nâng cao như các lời nhắc tích hợp sẵn, chỉ có sẵn trong loại Tác nhân.',
maximumIterations: {
name: 'Số Lần Lặp Tối đa',
description: 'Giới hạn số lần lặp một trợ lý tác nhân có thể thực hiện',
},
},
buildInPrompt: 'Lời Nhắc Tích Hợp',
firstPrompt: 'Tiền-lời Nhắc Đầu Tiên',
nextIteration: 'Lần Lặp Tiếp Theo',
promptPlaceholder: 'Viết tiền-lời nhắc của bạn ở đây',
tools: {
name: 'Công cụ',
description: 'Sử dụng công cụ có thể mở rộng các khả năng của LLM, như tìm kiếm trên internet hoặc thực hiện các phép tính khoa học',
enabled: 'Đã kích hoạt',
},
},
}
export default translation

69
web/i18n/vi-VN/app-log.ts Normal file
View File

@ -0,0 +1,69 @@
const translation = {
title: 'Nhật ký',
description: 'Nhật ký ghi lại trạng thái hoạt động của ứng dụng, bao gồm đầu vào của người dùng và phản hồi của trí tuệ nhân tạo.',
dateTimeFormat: 'MM/DD/YYYY hh:mm A',
table: {
header: {
time: 'Thời gian',
endUser: 'Người dùng cuối',
input: 'Đầu vào',
output: 'Đầu ra',
summary: 'Tiêu đề',
messageCount: 'Số lượng tin nhắn',
userRate: 'Tỷ lệ người dùng',
adminRate: 'Tỷ lệ quản trị',
},
pagination: {
previous: 'Trước',
next: 'Tiếp',
},
empty: {
noChat: 'Chưa có cuộc trò chuyện',
noOutput: 'Không có đầu ra',
element: {
title: 'Có ai ở đó không?',
content: 'Quan sát và ghi chú các tương tác giữa người dùng cuối và ứng dụng trí tuệ nhân tạo ở đây để liên tục cải thiện độ chính xác của trí tuệ nhân tạo. Bạn có thể thử <shareLink>chia sẻ</shareLink> hoặc <testLink>kiểm tra</testLink> ứng dụng Web của mình, sau đó quay lại trang này.',
},
},
},
detail: {
time: 'Thời gian',
conversationId: 'ID Cuộc trò chuyện',
promptTemplate: 'Mẫu Nhắc nhở',
promptTemplateBeforeChat: 'Mẫu Nhắc nhở Trước Cuộc trò chuyện · Như Tin nhắn Hệ thống',
annotationTip: 'Cải thiện Được Đánh Dấu bởi {{user}}',
timeConsuming: '',
second: 'giây',
tokenCost: 'Token đã tiêu',
loading: 'đang tải',
operation: {
like: 'thích',
dislike: 'không thích',
addAnnotation: 'Thêm Cải thiện',
editAnnotation: 'Chỉnh sửa Cải thiện',
annotationPlaceholder: 'Nhập câu trả lời mong muốn mà bạn muốn trí tuệ nhân tạo trả lời, có thể được sử dụng cho việc điều chỉnh mô hình và cải thiện liên tục chất lượng tạo văn bản trong tương lai.',
},
variables: 'Biến',
uploadImages: 'Ảnh đã tải lên',
},
filter: {
period: {
today: 'Hôm nay',
last7days: '7 Ngày qua',
last4weeks: '4 Tuần qua',
last3months: '3 Tháng qua',
last12months: '12 Tháng qua',
monthToDate: 'Từ Đầu tháng đến nay',
quarterToDate: 'Từ Đầu quý đến nay',
yearToDate: 'Từ Đầu năm đến nay',
allTime: 'Tất cả thời gian',
},
annotation: {
all: 'Tất cả',
annotated: 'Cải thiện Đã Đánh Dấu ({{count}} mục)',
not_annotated: 'Chưa Đánh Dấu',
},
},
}
export default translation

View File

@ -0,0 +1,139 @@
const translation = {
welcome: {
firstStepTip: 'Để bắt đầu,',
enterKeyTip: 'nhập khóa API OpenAI của bạn bên dưới',
getKeyTip: 'Lấy khóa API của bạn từ bảng điều khiển OpenAI',
placeholder: 'Khóa API OpenAI của bạn (ví dụ: sk-xxxx)',
},
apiKeyInfo: {
cloud: {
trial: {
title: 'Bạn đang sử dụng hạn mức thử nghiệm của {{providerName}}.',
description: 'Hạn mức thử nghiệm được cung cấp cho việc thử nghiệm của bạn. Trước khi hạn mức cuộc gọi thử nghiệm được sử dụng hết, vui lòng thiết lập nhà cung cấp mô hình của riêng bạn hoặc mua thêm hạn mức.',
},
exhausted: {
title: 'Hạn mức thử nghiệm của bạn đã được sử dụng hết, vui lòng thiết lập APIKey của bạn.',
description: 'Hạn mức thử nghiệm của bạn đã được sử dụng hết. Vui lòng thiết lập nhà cung cấp mô hình của riêng bạn hoặc mua thêm hạn mức.',
},
},
selfHost: {
title: {
row1: 'Để bắt đầu,',
row2: 'thiết lập nhà cung cấp mô hình của bạn trước.',
},
},
callTimes: 'Số lần gọi',
usedToken: 'Token đã sử dụng',
setAPIBtn: 'Đi đến thiết lập nhà cung cấp mô hình',
tryCloud: 'Hoặc thử phiên bản đám mây của Dify với báo giá miễn phí',
},
overview: {
title: 'Tổng quan',
appInfo: {
explanation: 'WebApp Trí tuệ nhân tạo Sẵn sàng sử dụng',
accessibleAddress: 'URL Công cộng',
preview: 'Xem trước',
regenerate: 'Tạo lại',
preUseReminder: 'Vui lòng kích hoạt WebApp trước khi tiếp tục.',
settings: {
entry: 'Cài đặt',
title: 'Cài đặt WebApp',
webName: 'Tên WebApp',
webDesc: 'Mô tả WebApp',
webDescTip: 'Văn bản này sẽ được hiển thị trên phía máy khách, cung cấp hướng dẫn cơ bản về cách sử dụng ứng dụng',
webDescPlaceholder: 'Nhập mô tả của WebApp',
language: 'Ngôn ngữ',
more: {
entry: 'Hiển thị thêm cài đặt',
copyright: 'Bản quyền',
copyRightPlaceholder: 'Nhập tên tác giả hoặc tổ chức',
privacyPolicy: 'Chính sách Bảo mật',
privacyPolicyPlaceholder: 'Nhập liên kết chính sách bảo mật',
privacyPolicyTip: 'Giúp người truy cập hiểu về dữ liệu mà ứng dụng thu thập, xem <privacyPolicyLink>Chính sách Bảo mật</privacyPolicyLink> của Dify.',
},
},
embedded: {
entry: 'Nhúng',
title: 'Nhúng vào trang web',
explanation: 'Chọn cách nhúng ứng dụng trò chuyện vào trang web của bạn',
iframe: 'Để thêm ứng dụng trò chuyện ở bất kỳ đâu trên trang web của bạn, thêm iframe này vào mã html của bạn.',
scripts: 'Để thêm ứng dụng trò chuyện vào phía dưới bên phải của trang web của bạn, thêm mã này vào mã html của bạn.',
chromePlugin: 'Cài đặt Phần mở rộng Chrome Dify Chatbot',
copied: 'Đã sao chép',
copy: 'Sao chép',
},
qrcode: {
title: 'Mã QR để chia sẻ',
scan: 'Quét để chia sẻ ứng dụng',
download: 'Tải về Mã QR',
},
customize: {
way: 'cách',
entry: 'Tùy chỉnh',
title: 'Tùy chỉnh WebApp Trí tuệ nhân tạo',
explanation: 'Bạn có thể tùy chỉnh giao diện trước của ứng dụng Web để phù hợp với kịch bản và nhu cầu phong cách của bạn.',
way1: {
name: 'Fork mã nguồn máy khách, chỉnh sửa và triển khai lên Vercel (được khuyến nghị)',
step1: 'Fork mã nguồn máy khách và chỉnh sửa',
step1Tip: 'Nhấn vào đây để fork mã nguồn vào tài khoản GitHub của bạn và chỉnh sửa mã',
step1Operation: 'Dify-WebClient',
step2: 'Triển khai lên Vercel',
step2Tip: 'Nhấn vào đây để nhập kho vào Vercel và triển khai',
step2Operation: 'Nhập kho',
step3: 'Cấu hình biến môi trường',
step3Tip: 'Thêm các biến môi trường sau vào Vercel',
},
way2: {
name: 'Viết mã phía máy khách để gọi API và triển khai nó lên máy chủ',
operation: 'Tài liệu',
},
},
},
apiInfo: {
title: 'API Dịch vụ Backend',
explanation: 'Dễ dàng tích hợp vào ứng dụng của bạn',
accessibleAddress: 'Điểm cuối API Dịch vụ',
doc: 'Tài liệu Tham khảo API',
},
status: {
running: 'Đang hoạt động',
disable: 'Tắt',
},
},
analysis: {
title: 'Phân tích',
ms: 'ms',
tokenPS: 'Token/s',
totalMessages: {
title: 'Tổng số tin nhắn',
explanation: 'Số lượt tương tác AI hàng ngày; không bao gồm kỹ thuật kịch bản / gỡ lỗi.',
},
activeUsers: {
title: 'Người dùng hoạt động',
explanation: 'Người dùng duy nhất tham gia trò chuyện với AI; không bao gồm kỹ thuật kịch bản / gỡ lỗi.',
},
tokenUsage: {
title: 'Sử dụng Token',
explanation: 'Phản ánh việc sử dụng token hàng ngày của mô hình ngôn ngữ cho ứng dụng, hữu ích cho mục đích kiểm soát chi phí.',
consumed: 'Đã tiêu',
},
avgSessionInteractions: {
title: 'Trung bình Tương tác trong phiên',
explanation: 'Số lượt giao tiếp giữa người dùng và AI liên tục; cho các ứng dụng dựa trên cuộc trò chuyện.',
},
userSatisfactionRate: {
title: 'Tỷ lệ Hài lòng của Người dùng',
explanation: 'Số lượng thích cho mỗi 1.000 tin nhắn. Điều này cho thấy tỷ lệ phản hồi mà người dùng rất hài lòng.',
},
avgResponseTime: {
title: 'Trung bình Thời gian Phản hồi',
explanation: 'Thời gian (ms) để AI xử lý / phản hồi; cho các ứng dụng dựa trên văn bản.',
},
tps: {
title: 'Tốc độ Đầu ra Token',
explanation: 'Đo hiệu suất của LLM. Đếm tốc độ đầu ra Token của LLM từ khi bắt đầu yêu cầu cho đến khi hoàn thành đầu ra.',
},
},
}
export default translation

54
web/i18n/vi-VN/app.ts Normal file
View File

@ -0,0 +1,54 @@
const translation = {
createApp: 'Tạo ứng dụng mới',
types: {
all: 'Tất cả',
assistant: 'Trợ lý',
completion: 'Hoàn thành',
},
modes: {
completion: 'Máy tạo văn bản',
chat: 'Trợ lý Cơ bản',
},
createFromConfigFile: 'Tạo ứng dụng từ tệp cấu hình',
deleteAppConfirmTitle: 'Xóa ứng dụng này?',
deleteAppConfirmContent:
'Việc xóa ứng dụng là không thể đảo ngược. Người dùng sẽ không thể truy cập vào ứng dụng của bạn nữa, và tất cả cấu hình và nhật ký mẫu sẽ bị xóa vĩnh viễn.',
appDeleted: 'Ứng dụng đã bị xóa',
appDeleteFailed: 'Xóa ứng dụng thất bại',
join: 'Tham gia cộng đồng',
communityIntro:
'Thảo luận với các thành viên nhóm, người đóng góp và nhà phát triển trên các kênh khác nhau.',
roadmap: 'Xem lộ trình của chúng tôi',
appNamePlaceholder: 'Vui lòng nhập tên của ứng dụng',
newApp: {
startToCreate: 'Hãy bắt đầu với ứng dụng mới của bạn',
captionName: 'Biểu tượng & tên ứng dụng',
captionAppType: 'Bạn muốn tạo loại ứng dụng nào?',
previewDemo: 'Xem trước demo',
chatApp: 'Trợ lý',
chatAppIntro:
'Tôi muốn xây dựng một ứng dụng dựa trên trò chuyện. Ứng dụng này sử dụng định dạng câu hỏi và trả lời, cho phép nhiều vòng trò chuyện liên tục.',
agentAssistant: 'Trợ lý Mới cho Đại lý',
completeApp: 'Máy Tạo Văn Bản',
completeAppIntro:
'Tôi muốn tạo một ứng dụng tạo ra văn bản chất lượng cao dựa trên các mẫu, như việc tạo bài viết, tóm tắt, dịch thuật và nhiều hơn nữa.',
showTemplates: 'Tôi muốn chọn từ một mẫu',
hideTemplates: 'Quay lại lựa chọn chế độ',
Create: 'Tạo',
Cancel: 'Hủy',
nameNotEmpty: 'Tên không được để trống',
appTemplateNotSelected: 'Vui lòng chọn một mẫu',
appTypeRequired: 'Vui lòng chọn loại ứng dụng',
appCreated: 'Ứng dụng đã được tạo',
appCreateFailed: 'Không thể tạo ứng dụng',
},
editApp: {
startToEdit: 'Chỉnh sửa ứng dụng',
},
emoji: {
ok: 'Đồng ý',
cancel: 'Hủy',
},
}
export default translation

115
web/i18n/vi-VN/billing.ts Normal file
View File

@ -0,0 +1,115 @@
const translation = {
currentPlan: 'Kế hoạch Hiện tại',
upgradeBtn: {
plain: 'Nâng cấp Kế hoạch',
encourage: 'Nâng cấp Ngay',
encourageShort: 'Nâng cấp',
},
viewBilling: 'Quản lý thanh toán và đăng ký',
buyPermissionDeniedTip: 'Vui lòng liên hệ với quản trị viên doanh nghiệp của bạn để đăng ký',
plansCommon: {
title: 'Chọn một kế hoạch phù hợp với bạn',
yearlyTip: 'Nhận 2 tháng miễn phí khi đăng ký hàng năm!',
mostPopular: 'Phổ biến nhất',
planRange: {
monthly: 'Hàng tháng',
yearly: 'Hàng năm',
},
month: 'tháng',
year: 'năm',
save: 'Tiết kiệm ',
free: 'Miễn phí',
currentPlan: 'Kế hoạch Hiện tại',
contractSales: 'Liên hệ bộ phận bán hàng',
contractOwner: 'Liên hệ quản lý nhóm',
startForFree: 'Bắt đầu miễn phí',
getStartedWith: 'Bắt đầu với ',
contactSales: 'Liên hệ Bán hàng',
talkToSales: 'Nói chuyện với Bộ phận Bán hàng',
modelProviders: 'Nhà cung cấp Mô hình',
teamMembers: 'Thành viên Nhóm',
buildApps: 'Xây dựng Ứng dụng',
vectorSpace: 'Không gian Vector',
vectorSpaceBillingTooltip: 'Mỗi 1MB có thể lưu trữ khoảng 1.2 triệu ký tự dữ liệu vector hóa (ước tính sử dụng OpenAI Embeddings, thay đổi tùy theo các mô hình).',
vectorSpaceTooltip: 'Không gian Vector là hệ thống bộ nhớ dài hạn cần thiết cho LLMs để hiểu dữ liệu của bạn.',
documentsUploadQuota: 'Hạn mức Tải lên Tài liệu',
documentProcessingPriority: 'Ưu tiên Xử lý Tài liệu',
documentProcessingPriorityTip: 'Để có ưu tiên xử lý tài liệu cao hơn, vui lòng nâng cấp kế hoạch của bạn.',
documentProcessingPriorityUpgrade: 'Xử lý nhiều dữ liệu với độ chính xác cao và tốc độ nhanh hơn.',
priority: {
'standard': 'Tiêu chuẩn',
'priority': 'Ưu tiên',
'top-priority': 'Ưu tiên Cao nhất',
},
logsHistory: 'Lịch sử Nhật ký',
customTools: 'Công cụ Tùy chỉnh',
unavailable: 'Không có sẵn',
days: 'ngày',
unlimited: 'Không giới hạn',
support: 'Hỗ trợ',
supportItems: {
communityForums: 'Diễn đàn cộng đồng',
emailSupport: 'Hỗ trợ qua email',
priorityEmail: 'Hỗ trợ qua email & chat ưu tiên',
logoChange: 'Thay đổi Logo',
SSOAuthentication: 'Xác thực SSO',
personalizedSupport: 'Hỗ trợ cá nhân hóa',
dedicatedAPISupport: 'Hỗ trợ API dành riêng',
customIntegration: 'Tích hợp và hỗ trợ tùy chỉnh',
ragAPIRequest: 'Yêu cầu API RAG',
bulkUpload: 'Tải lên tài liệu hàng loạt',
agentMode: 'Chế độ Đại lý',
workflow: 'Quy trình làm việc',
},
comingSoon: 'Sắp ra mắt',
member: 'Thành viên',
memberAfter: 'Thành viên',
messageRequest: {
title: 'Số Lượng Tin Nhắn',
tooltip: 'Hạn mức triệu hồi tin nhắn cho các kế hoạch sử dụng mô hình OpenAI (ngoại trừ gpt4). Các tin nhắn vượt quá giới hạn sẽ sử dụng Khóa API OpenAI của bạn.',
},
annotatedResponse: {
title: 'Hạn Mức Quota Phản hồi Đã được Ghi chú',
tooltip: 'Chỉnh sửa và ghi chú thủ công các phản hồi cung cấp khả năng trả lời câu hỏi chất lượng cao có thể tùy chỉnh cho các ứng dụng. (Chỉ áp dụng trong các ứng dụng trò chuyện)',
},
ragAPIRequestTooltip: 'Đề cập đến số lượng cuộc gọi API triệu hồi chỉ khả năng xử lý cơ sở kiến thức của Dify.',
receiptInfo: 'Chỉ chủ nhóm và quản trị viên nhóm có thể đăng ký và xem thông tin thanh toán',
},
plans: {
sandbox: {
name: 'Hộp Cát',
description: 'Thử nghiệm miễn phí 200 lần GPT',
includesTitle: 'Bao gồm:',
},
professional: {
name: 'Chuyên nghiệp',
description: 'Dành cho cá nhân và các nhóm nhỏ để mở khóa nhiều sức mạnh với giá cả phải chăng.',
includesTitle: 'Tất cả trong kế hoạch miễn phí, cộng thêm:',
},
team: {
name: 'Nhóm',
description: 'Hợp tác mà không giới hạn và tận hưởng hiệu suất hạng nhất.',
includesTitle: 'Tất cả trong kế hoạch Chuyên nghiệp, cộng thêm:',
},
enterprise: {
name: 'Doanh nghiệp',
description: 'Nhận toàn bộ khả năng và hỗ trợ cho các hệ thống quan trọng cho nhiệm vụ quy mô lớn.',
includesTitle: 'Tất cả trong kế hoạch Nhóm, cộng thêm:',
},
},
vectorSpace: {
fullTip: 'Không gian Vector đã đầy.',
fullSolution: 'Nâng cấp kế hoạch của bạn để có thêm không gian.',
},
apps: {
fullTipLine1: 'Nâng cấp kế hoạch của bạn để',
fullTipLine2: 'xây dựng thêm ứng dụng.',
},
annotatedResponse: {
fullTipLine1: 'Nâng cấp kế hoạch của bạn để',
fullTipLine2: 'ghi chú thêm cuộc trò chuyện.',
quotaTitle: 'Hạn Mức Quota Phản hồi Đã được Ghi chú',
},
}
export default translation

505
web/i18n/vi-VN/common.ts Normal file
View File

@ -0,0 +1,505 @@
const translation = {
api: {
success: 'Thành công',
actionSuccess: 'Thành công',
saved: 'Đã lưu',
create: 'Tạo',
remove: 'Xóa',
},
operation: {
create: 'Tạo mới',
confirm: 'Xác nhận',
cancel: 'Hủy bỏ',
clear: 'Xóa',
save: 'Lưu',
edit: 'Chỉnh sửa',
add: 'Thêm',
added: 'Đã thêm',
refresh: 'Làm mới',
reset: 'Đặt lại',
search: 'Tìm kiếm',
change: 'Thay đổi',
remove: 'Xóa',
send: 'Gửi',
copy: 'Sao chép',
lineBreak: 'Ngắt dòng',
sure: 'Tôi chắc chắn',
download: 'Tải xuống',
delete: 'Xóa',
settings: 'Cài đặt',
setup: 'Thiết lập',
getForFree: 'Nhận miễn phí',
reload: 'Tải lại',
ok: 'OK',
log: 'Nhật ký',
learnMore: 'Tìm hiểu thêm',
params: 'Tham số',
},
placeholder: {
input: 'Vui lòng nhập',
select: 'Vui lòng chọn',
},
voice: {
language: {
zhHans: 'Tiếng Trung',
enUS: 'Tiếng Anh',
deDE: 'Tiếng Đức',
frFR: 'Tiếng Pháp',
esES: 'Tiếng Tây Ban Nha',
itIT: 'Tiếng Ý',
thTH: 'Tiếng Thái',
idID: 'Tiếng Indonesia',
jaJP: 'Tiếng Nhật',
koKR: 'Tiếng Hàn',
ptBR: 'Tiếng Bồ Đào Nha',
ruRU: 'Tiếng Nga',
ukUA: 'Tiếng Ukraina',
},
},
unit: {
char: 'ký tự',
},
actionMsg: {
noModification: 'Hiện không có sự thay đổi.',
modifiedSuccessfully: 'Chỉnh sửa thành công',
modifiedUnsuccessfully: 'Chỉnh sửa không thành công',
copySuccessfully: 'Đã sao chép thành công',
paySucceeded: 'Thanh toán thành công',
payCancelled: 'Thanh toán đã hủy',
generatedSuccessfully: 'Tạo thành công',
generatedUnsuccessfully: 'Tạo không thành công',
},
model: {
params: {
temperature: 'Nhiệt độ',
temperatureTip:
'Kiểm soát sự ngẫu nhiên: Giảm nhiệt độ dẫn đến ít kết quả hoàn thành ngẫu nhiên hơn. Khi nhiệt độ tiến gần về không, mô hình sẽ trở nên xác định và lặp lại.',
top_p: 'Top P',
top_pTip:
'Kiểm soát đa dạng thông qua lấy mẫu nhân nhóm: 0.5 có nghĩa là nửa số tùy chọn có khả năng cao được xem xét.',
presence_penalty: 'Phạt sự hiện diện',
presence_penaltyTip:
'Độ lớn của sự phạt cho các token mới dựa trên việc chúng có xuất hiện trong văn bản cho đến nay hay không.\nTăng khả năng của mô hình để nói về các chủ đề mới.',
frequency_penalty: 'Phạt tần suất',
frequency_penaltyTip:
'Độ lớn của sự phạt cho các token mới dựa trên tần suất hiện tại của chúng trong văn bản cho đến nay.\nGiảm khả năng của mô hình để lặp lại cùng một dòng văn bản.',
max_tokens: 'Max token',
max_tokensTip:
'Sử dụng để giới hạn độ dài tối đa của câu trả lời, theo token. \nGiá trị lớn có thể giới hạn không gian còn lại cho từ khóa khởi đầu, nhật ký trò chuyện và Kiến thức. \nKhuyến nghị đặt giá trị dưới hai phần ba của gpt-4-1106-preview, gpt-4-vision-preview max token (đầu vào 128k đầu ra 4k)',
maxTokenSettingTip: 'Cài đặt max token của bạn quá cao, có thể hạn chế không gian cho từ khóa, truy vấn và dữ liệu. Xem xét đặt nó dưới 2/3.',
setToCurrentModelMaxTokenTip: 'Max token được cập nhật đến 80% token tối đa của mô hình hiện tại {{maxToken}}.',
stop_sequences: 'Chuỗi dừng',
stop_sequencesTip: 'Lên đến bốn chuỗi nơi API sẽ dừng việc tạo ra các token tiếp theo. Văn bản được trả về sẽ không chứa chuỗi dừng.',
stop_sequencesPlaceholder: 'Nhập chuỗi và nhấn Tab',
},
tone: {
Creative: 'Sáng tạo',
Balanced: 'Cân bằng',
Precise: 'Chính xác',
Custom: 'Tùy chỉnh',
},
addMoreModel: 'Điều chỉnh cài đặt để thêm mô hình',
},
menus: {
status: 'beta',
explore: 'Khám phá',
apps: 'Studio',
plugins: 'Plugins',
pluginsTips: 'Tích hợp các plugin bên thứ ba hoặc tạo ra các AI-Plugin tương thích với ChatGPT.',
datasets: 'Kiến thức',
datasetsTips: 'SẮP RA MẮT: Nhập dữ liệu văn bản của bạn hoặc viết dữ liệu theo thời gian thực thông qua Webhook để cải thiện ngữ cảnh LLM.',
newApp: 'Ứng dụng mới',
newDataset: 'Tạo Kiến thức',
tools: 'Công cụ',
},
userProfile: {
settings: 'Cài đặt',
workspace: 'Không gian làm việc',
createWorkspace: 'Tạo Không gian làm việc',
helpCenter: 'Trung tâm trợ giúp',
roadmapAndFeedback: 'Lộ trình & Phản hồi',
community: 'Cộng đồng',
about: 'Về chúng tôi',
logout: 'Đăng xuất',
},
settings: {
accountGroup: 'ACCOUNT',
workplaceGroup: 'WORKSPACE',
account: 'Tài khoản của tôi',
members: 'Thành viên',
billing: 'Thanh toán',
integrations: 'Tích hợp',
language: 'Ngôn ngữ',
provider: 'Nhà cung cấp mô hình',
dataSource: 'Nguồn dữ liệu',
plugin: 'Plugins',
apiBasedExtension: 'Mở rộng dựa trên API',
},
account: {
avatar: 'Ảnh đại diện',
name: 'Tên',
email: 'Email',
password: 'Mật khẩu',
passwordTip: 'Bạn có thể đặt một mật khẩu cố định nếu bạn không muốn sử dụng mã đăng nhập tạm thời',
setPassword: 'Đặt mật khẩu',
resetPassword: 'Đặt lại mật khẩu',
currentPassword: 'Mật khẩu hiện tại',
newPassword: 'Mật khẩu mới',
confirmPassword: 'Xác nhận mật khẩu',
notEqual: 'Hai mật khẩu không giống nhau.',
langGeniusAccount: 'Tài khoản Dify',
langGeniusAccountTip: 'Tài khoản Dify của bạn và dữ liệu người dùng liên quan.',
editName: 'Chỉnh sửa Tên',
showAppLength: 'Hiển thị {{length}} ứng dụng',
},
members: {
team: 'Nhóm',
invite: 'Mời',
name: 'TÊN',
lastActive: 'HOẠT ĐỘNG GẦN ĐÂY',
role: 'VAI TRÒ',
pending: 'Đang chờ...',
owner: 'Chủ sở hữu',
admin: 'Quản trị viên',
adminTip: 'Có thể xây dựng ứng dụng và quản lý cài đặt nhóm',
normal: 'Bình thường',
normalTip: 'Chỉ có thể sử dụng ứng dụng, không thể xây dựng ứng dụng',
inviteTeamMember: 'Mời thành viên nhóm',
inviteTeamMemberTip: 'Sau khi đăng nhập, họ có thể truy cập trực tiếp vào dữ liệu nhóm của bạn.',
email: 'Email',
emailInvalid: 'Định dạng Email không hợp lệ',
emailPlaceholder: 'Vui lòng nhập email',
sendInvite: 'Gửi Lời mời',
invitedAsRole: 'Được mời với vai trò {{role}}',
invitationSent: 'Lời mời đã được gửi',
invitationSentTip: 'Lời mời đã được gửi, và họ có thể đăng nhập vào Dify để truy cập vào dữ liệu nhóm của bạn.',
invitationLink: 'Liên kết Lời mời',
failedinvitationEmails: 'Dưới đây là danh sách email không gửi được lời mời',
ok: 'OK',
removeFromTeam: 'Xóa khỏi nhóm',
removeFromTeamTip: 'Sẽ xóa quyền truy cập nhóm',
setAdmin: 'Đặt làm quản trị viên',
setMember: 'Đặt thành viên bình thường',
disinvite: 'Hủy lời mời',
deleteMember: 'Xóa thành viên',
you: '(Bạn)',
},
integrations: {
connected: 'Đã kết nối',
google: 'Google',
googleAccount: 'Đăng nhập bằng tài khoản Google',
github: 'GitHub',
githubAccount: 'Đăng nhập bằng tài khoản GitHub',
connect: 'Kết nối',
},
language: {
displayLanguage: 'Ngôn ngữ hiển thị',
timezone: 'Múi giờ',
},
provider: {
apiKey: 'Khóa API',
enterYourKey: 'Nhập khóa API của bạn ở đây',
invalidKey: 'Khóa API OpenAI không hợp lệ',
validatedError: 'Xác minh thất bại: ',
validating: 'Đang xác minh khóa...',
saveFailed: 'Lưu khóa API thất bại',
apiKeyExceedBill: 'Khóa API này không có lượng truy vấn khả dụng, vui lòng đọc',
addKey: 'Thêm Khóa',
comingSoon: 'Sắp Ra Mắt',
editKey: 'Chỉnh sửa',
invalidApiKey: 'Khóa API không hợp lệ',
azure: {
apiBase: 'Cơ sở API',
apiBasePlaceholder: 'URL cơ sở API của điểm cuối Azure OpenAI của bạn.',
apiKey: 'Khóa API',
apiKeyPlaceholder: 'Nhập khóa API của bạn ở đây',
helpTip: 'Tìm hiểu Dịch vụ Azure OpenAI',
},
openaiHosted: {
openaiHosted: 'OpenAI đang lưu trữ',
onTrial: 'TRIÊN DÙNG THỬ',
exhausted: 'HẾT QUOTA',
desc: 'Dịch vụ lưu trữ OpenAI được cung cấp bởi Dify cho phép bạn sử dụng các mô hình như GPT-3.5. Trước khi hết lượng truy vấn dùng thử, bạn cần thiết lập các nhà cung cấp mô hình khác.',
callTimes: 'Số lần gọi',
usedUp: 'Quota dùng thử đã hết. Thêm nhà cung cấp Mô hình của riêng bạn.',
useYourModel: 'Hiện đang sử dụng nhà cung cấp Mô hình của riêng bạn.',
close: 'Đóng',
},
anthropicHosted: {
anthropicHosted: 'Anthropic Claude',
onTrial: 'TRIÊN DÙNG THỬ',
exhausted: 'HẾT QUOTA',
desc: 'Mô hình mạnh mẽ, vượt trội trong một loạt các nhiệm vụ từ trò chuyện phức tạp và tạo nội dung sáng tạo đến hướng dẫn chi tiết.',
callTimes: 'Số lần gọi',
usedUp: 'Quota dùng thử đã hết. Thêm nhà cung cấp Mô hình của riêng bạn.',
useYourModel: 'Hiện đang sử dụng nhà cung cấp Mô hình của riêng bạn.',
close: 'Đóng',
},
anthropic: {
using: 'Khả năng nhúng đang sử dụng',
enableTip: 'Để kích hoạt mô hình Anthrop, bạn cần ràng buộc với Dịch vụ OpenAI hoặc Azure OpenAI trước.',
notEnabled: 'Chưa được kích hoạt',
keyFrom: 'Nhận khóa API của bạn từ Anthrop',
},
encrypted: {
front: 'Khóa API của bạn sẽ được mã hóa và lưu trữ bằng',
back: ' công nghệ.',
},
},
modelProvider: {
notConfigured: 'Mô hình hệ thống vẫn chưa được cấu hình hoàn toàn và một số chức năng có thể không khả dụng.',
systemModelSettings: 'Cài đặt Mô hình Hệ thống',
systemModelSettingsLink: 'Tại sao cần thiết phải thiết lập mô hình hệ thống?',
selectModel: 'Chọn mô hình của bạn',
setupModelFirst: 'Vui lòng thiết lập mô hình của bạn trước',
systemReasoningModel: {
key: 'Mô hình lập luận hệ thống',
tip: 'Thiết lập mô hình suy luận mặc định sẽ được sử dụng để tạo ứng dụng, cũng như các tính năng như việc tạo tên cuộc trò chuyện và đề xuất câu hỏi tiếp theo cũng sẽ sử dụng mô hình suy luận mặc định.',
},
embeddingModel: {
key: 'Mô hình nhúng',
tip: 'Thiết lập mô hình mặc định cho việc xử lý nhúng tài liệu của Kiến thức, cả hai phương tiện truy xuất và nhập của Kiến thức đều sử dụng mô hình nhúng này cho xử lý vector hóa. Chuyển đổi sẽ làm cho kích thước vector giữa Kiến thức được nhập và câu hỏi không nhất quán, dẫn đến việc truy xuất thất bại. Để tránh truy xuất thất bại, vui lòng không chuyển đổi mô hình này tùy ý.',
required: 'Mô hình nhúng là bắt buộc',
},
speechToTextModel: {
key: 'Mô hình Chuyển đổi Văn bản thành Tiếng nói',
tip: 'Thiết lập mô hình mặc định cho đầu vào chuyển đổi tiếng nói thành văn bản trong cuộc trò chuyện.',
},
ttsModel: {
key: 'Mô hình Văn bản thành Tiếng nói',
tip: 'Thiết lập mô hình mặc định cho đầu vào văn bản thành tiếng nói trong cuộc trò chuyện.',
},
rerankModel: {
key: 'Mô hình Sắp xếp lại',
tip: 'Mô hình sắp xếp lại sẽ sắp xếp lại danh sách tài liệu ứng cử viên dựa trên sự phù hợp ngữ nghĩa với truy vấn của người dùng, cải thiện kết quả của việc xếp hạng ngữ nghĩa',
},
quota: 'Hạn mức',
searchModel: 'Mô hình tìm kiếm',
noModelFound: 'Không tìm thấy mô hình cho {{model}}',
models: 'Mô hình',
showMoreModelProvider: 'Hiển thị thêm nhà cung cấp mô hình',
selector: {
tip: 'Mô hình này đã bị xóa. Vui lòng thêm một mô hình hoặc chọn mô hình khác.',
emptyTip: 'Không có mô hình khả dụng',
emptySetting: 'Vui lòng vào cài đặt để cấu hình',
rerankTip: 'Vui lòng thiết lập mô hình sắp xếp lại',
},
card: {
quota: 'QUOTA',
onTrial: 'Thử nghiệm',
paid: 'Đã thanh toán',
quotaExhausted: 'Quota đã hết',
callTimes: 'Số lần gọi',
tokens: 'Tokens',
buyQuota: 'Mua Quota',
priorityUse: 'Ưu tiên sử dụng',
removeKey: 'Remove API Key',
tip: 'Ưu tiên sẽ được trao cho hạn ngạch đã thanh toán. Hạn ngạch dùng thử sẽ được sử dụng sau khi hết hạn ngạch trả phí.',
},
item: {
deleteDesc: 'Các mô hình {{modelName}} đang được sử dụng như là các mô hình lập luận hệ thống. Một số chức năng sẽ không khả dụng sau khi loại bỏ. Vui lòng xác nhận.',
freeQuota: 'QUYỀN LỢI MIỄN PHÍ',
},
addApiKey: 'Thêm khóa API của bạn',
invalidApiKey: 'Khóa API không hợp lệ',
encrypted: {
front: 'Khóa API CỦA BẠN sẽ được mã hóa và lưu trữ bằng',
back: ' công nghệ.',
},
freeQuota: {
howToEarn: 'Cách kiếm',
},
addMoreModelProvider: 'THÊM NHÀ CUNG CẤP MÔ HÌNH',
addModel: 'Thêm Mô hình',
modelsNum: '{{num}} Mô hình',
showModels: 'Hiện Mô hình',
showModelsNum: 'Hiện {{num}} Mô hình',
collapse: 'Thu gọn',
config: 'Cấu hình',
modelAndParameters: 'Mô hình và Tham số',
model: 'Mô hình',
featureSupported: '{{feature}} được hỗ trợ',
callTimes: 'Số lần gọi',
credits: 'Tín dụng Tin nhắn',
buyQuota: 'Mua Quyền lợi',
getFreeTokens: 'Nhận mã thông báo miễn phí',
priorityUsing: 'Ưu tiên sử dụng',
deprecated: 'Đã lỗi thời',
confirmDelete: 'Xác nhận xóa?',
quotaTip: 'Số lượng mã thông báo miễn phí còn lại',
loadPresets: 'Tải Cài đặt trước',
parameters: 'THAM SỐ',
},
dataSource: {
add: 'Thêm nguồn dữ liệu',
connect: 'Kết nối',
notion: {
title: 'Notion',
description: 'Sử dụng Notion như một nguồn dữ liệu cho Kiến thức.',
connectedWorkspace: 'Không gian làm việc đã kết nối',
addWorkspace: 'Thêm không gian làm việc',
connected: 'Đã kết nối',
disconnected: 'Đã ngắt kết nối',
changeAuthorizedPages: 'Thay đổi trang được ủy quyền',
pagesAuthorized: 'Các trang được ủy quyền',
sync: 'Đồng bộ',
remove: 'Xóa',
selector: {
pageSelected: 'Các trang đã chọn',
searchPages: 'Tìm kiếm trang...',
noSearchResult: 'Không có kết quả tìm kiếm',
addPages: 'Thêm trang',
preview: 'Xem trước',
},
},
},
plugin: {
serpapi: {
apiKey: 'Khóa API',
apiKeyPlaceholder: 'Nhập khóa API của bạn',
keyFrom: 'Nhận khóa SerpAPI của bạn từ Trang tài khoản SerpAPI',
},
},
apiBasedExtension: {
title: 'Các tiện ích API cung cấp quản lý API tập trung, giúp cấu hình dễ dàng sử dụng trên các ứng dụng của Dify.',
link: 'Tìm hiểu cách phát triển Phần mở rộng API của riêng bạn.',
linkUrl: 'https://docs.dify.ai/features/extension/api_based_extension',
add: 'Thêm Phần mở rộng API',
selector: {
title: 'Phần mở rộng API',
placeholder: 'Vui lòng chọn phần mở rộng API',
manage: 'Quản lý Phần mở rộng API',
},
modal: {
title: 'Thêm Phần mở rộng API',
editTitle: 'Chỉnh sửa Phần mở rộng API',
name: {
title: 'Tên',
placeholder: 'Vui lòng nhập tên',
},
apiEndpoint: {
title: 'Điểm cuối API',
placeholder: 'Vui lòng nhập điểm cuối API',
},
apiKey: {
title: 'Khóa API',
placeholder: 'Vui lòng nhập khóa API',
lengthError: 'Độ dài khóa API không được nhỏ hơn 5 ký tự',
},
},
type: 'Loại',
},
about: {
changeLog: 'Nhật ký thay đổi',
updateNow: 'Cập nhật ngay',
nowAvailable: 'Dify {{version}} hiện đã có sẵn.',
latestAvailable: 'Dify {{version}} là phiên bản mới nhất hiện có.',
},
appMenus: {
overview: 'Tổng quan',
promptEng: 'Orchestrate',
apiAccess: 'Truy cập API',
logAndAnn: 'Nhật ký & Thông báo',
},
environment: {
testing: 'TESTING',
development: 'DEVELOPMENT',
},
appModes: {
completionApp: 'Ứng dụng Tạo văn bản',
chatApp: 'Ứng dụng Trò chuyện',
},
datasetMenus: {
documents: 'Tài liệu',
hitTesting: 'Kiểm tra truy vấn',
settings: 'Cài đặt',
emptyTip: 'Kiến thức chưa được liên kết, vui lòng đi đến ứng dụng hoặc plug-in để hoàn thành liên kết.',
viewDoc: 'Xem tài liệu',
relatedApp: 'các ứng dụng liên kết',
},
voiceInput: {
speaking: 'Hãy nói...',
converting: 'Chuyển đổi thành văn bản...',
notAllow: 'micro không được ủy quyền',
},
modelName: {
'gpt-3.5-turbo': 'GPT-3.5-Turbo',
'gpt-3.5-turbo-16k': 'GPT-3.5-Turbo-16K',
'gpt-4': 'GPT-4',
'gpt-4-32k': 'GPT-4-32K',
'text-davinci-003': 'Text-Davinci-003',
'text-embedding-ada-002': 'Text-Embedding-Ada-002',
'whisper-1': 'Whisper-1',
'claude-instant-1': 'Claude-Instant',
'claude-2': 'Claude-2',
},
chat: {
renameConversation: 'Đổi tên Cuộc trò chuyện',
conversationName: 'Tên cuộc trò chuyện',
conversationNamePlaceholder: 'Vui lòng nhập tên cuộc trò chuyện',
conversationNameCanNotEmpty: 'Yêu cầu nhập tên cuộc trò chuyện',
citation: {
title: 'THAM KHẢO',
linkToDataset: 'Liên kết tới Kiến thức',
characters: 'Ký tự:',
hitCount: 'Số lượt truy xuất:',
vectorHash: 'Vector hash:',
hitScore: 'Điểm truy xuất:',
},
},
promptEditor: {
placeholder: 'Viết từ khóa của bạn ở đây, nhập \'{\' để chèn một biến, nhập \'/\' để chèn một khối nội dung nhắc nhở',
context: {
item: {
title: 'Bối cảnh',
desc: 'Chèn mẫu bối cảnh',
},
modal: {
title: '{{num}} Kiến thức trong Bối cảnh',
add: 'Thêm Bối cảnh',
footer: 'Bạn có thể quản lý các bối cảnh trong phần Bối cảnh bên dưới.',
},
},
history: {
item: {
title: 'Lịch sử Cuộc trò chuyện',
desc: 'Chèn mẫu tin nhắn lịch sử',
},
modal: {
title: 'VÍ DỤ',
user: 'Xin chào',
assistant: 'Xin chào! Tôi có thể giúp gì cho bạn hôm nay?',
edit: 'Chỉnh sửa Tên Vai trò Cuộc trò chuyện',
},
},
variable: {
item: {
title: 'Biến & Công cụ Bên ngoài',
desc: 'Chèn Biến & Công cụ Bên ngoài',
},
modal: {
add: 'Biến mới',
addTool: 'Công cụ mới',
},
},
query: {
item: {
title: 'Truy vấn',
desc: 'Chèn mẫu truy vấn người dùng',
},
},
existed: 'Đã tồn tại trong tin nhắn',
},
imageUploader: {
uploadFromComputer: 'Tải lên từ Máy tính',
uploadFromComputerReadError: 'Đọc ảnh thất bại, vui lòng thử lại.',
uploadFromComputerUploadError: 'Tải ảnh lên thất bại, vui lòng tải lên lại.',
uploadFromComputerLimit: 'Ảnh tải lên không được vượt quá {{size}} MB',
pasteImageLink: 'Dán liên kết ảnh',
pasteImageLinkInputPlaceholder: 'Dán liên kết ảnh ở đây',
pasteImageLinkInvalid: 'Liên kết ảnh không hợp lệ',
imageUpload: 'Tải ảnh lên',
},
}
export default translation

30
web/i18n/vi-VN/custom.ts Normal file
View File

@ -0,0 +1,30 @@
const translation = {
custom: 'Tùy chỉnh',
upgradeTip: {
prefix: 'Nâng cấp gói của bạn để',
suffix: 'tùy chỉnh thương hiệu của bạn.',
},
webapp: {
title: 'Tùy chỉnh thương hiệu WebApp',
removeBrand: 'Xóa Được hỗ trợ bởi Dify',
changeLogo: 'Thay đổi Hình ảnh Thương hiệu Được hỗ trợ bởi',
changeLogoTip: 'Định dạng SVG hoặc PNG với kích thước tối thiểu là 40x40px',
},
app: {
title: 'Tùy chỉnh thương hiệu tiêu đề ứng dụng',
changeLogoTip: 'Định dạng SVG hoặc PNG với kích thước tối thiểu là 80x80px',
},
upload: 'Tải lên',
uploading: 'Đang tải lên',
uploadedFail: 'Tải ảnh lên thất bại, vui lòng tải lên lại.',
change: 'Thay đổi',
apply: 'Áp dụng',
restore: 'Khôi phục Mặc định',
customize: {
contactUs: ' liên hệ với chúng tôi ',
prefix: 'Để tùy chỉnh logo thương hiệu trong ứng dụng, vui lòng',
suffix: 'để nâng cấp lên phiên bản Doanh nghiệp.',
},
}
export default translation

View File

@ -0,0 +1,130 @@
const translation = {
steps: {
header: {
creation: 'Tạo Kiến thức',
update: 'Thêm dữ liệu',
},
one: 'Chọn nguồn dữ liệu',
two: 'Tiền xử lý và làm sạch văn bản',
three: 'Thực hiện và hoàn thành',
},
error: {
unavailable: 'Kiến thức này không khả dụng',
},
stepOne: {
filePreview: 'Xem trước tệp',
pagePreview: 'Xem trước trang',
dataSourceType: {
file: 'Nhập từ tệp văn bản',
notion: 'Đồng bộ từ Notion',
web: 'Đồng bộ từ trang web',
},
uploader: {
title: 'Tải lên tệp văn bản',
button: 'Kéo và thả tệp, hoặc',
browse: 'Duyệt',
tip: 'Hỗ trợ {{supportTypes}}. Tối đa {{size}}MB mỗi tệp.',
validation: {
typeError: 'Loại tệp không được hỗ trợ',
size: 'Tệp quá lớn. Tối đa là {{size}}MB',
count: 'Không hỗ trợ tải lên nhiều tệp',
filesNumber: 'Bạn đã đạt đến giới hạn tải lên lô của {{filesNumber}} tệp.',
},
cancel: 'Hủy bỏ',
change: 'Thay đổi',
failed: 'Tải lên thất bại',
},
notionSyncTitle: 'Notion chưa được kết nối',
notionSyncTip: 'Để đồng bộ với Notion, trước tiên cần thiết lập kết nối với Notion.',
connect: 'Đi đến kết nối',
button: 'tiếp theo',
emptyDatasetCreation: 'Tôi muốn tạo Kiến thức trống',
modal: {
title: 'Tạo Kiến thức trống',
tip: 'Một Kiến thức trống sẽ không chứa tài liệu nào, và bạn có thể tải lên tài liệu bất kỳ lúc nào.',
input: 'Tên Kiến thức',
placeholder: 'Vui lòng nhập',
nameNotEmpty: 'Tên không thể để trống',
nameLengthInvaild: 'Tên phải từ 1 đến 40 ký tự',
cancelButton: 'Hủy bỏ',
confirmButton: 'Tạo',
failed: 'Tạo thất bại',
},
},
stepTwo: {
segmentation: 'Cài đặt đoạn',
auto: 'Tự động',
autoDescription: 'Tự động thiết lập quy tắc đoạn và tiền xử lý. Người dùng không quen thuộc được khuyến nghị chọn điều này.',
custom: 'Tùy chỉnh',
customDescription: 'Tùy chỉnh quy tắc đoạn, độ dài đoạn và quy tắc tiền xử lý, v.v.',
separator: 'Bộ phận xác định đoạn',
separatorPlaceholder: 'Ví dụ, dòng mới (\\\\n) hoặc bộ phận phân cách đặc biệt (như "***")',
maxLength: 'Độ dài tối đa của đoạn',
overlap: 'Chồng lấn đoạn',
overlapTip: 'Thiết lập chồng lấn đoạn có thể duy trì sự liên quan ngữ nghĩa giữa chúng, tăng cường hiệu ứng truy xuất. Đề xuất thiết lập từ 10% đến 25% của kích thước đoạn tối đa.',
overlapCheck: 'Chồng lấn đoạn không nên lớn hơn độ dài tối đa của đoạn',
rules: 'Quy tắc tiền xử lý văn bản',
removeExtraSpaces: 'Thay thế khoảng trắng liên tục, dòng mới và tab',
removeUrlEmails: 'Xóa tất cả URL và địa chỉ email',
removeStopwords: 'Loại bỏ các từ dừng như "một", "một", "những"',
preview: 'Xác nhận & Xem trước',
reset: 'Đặt lại',
indexMode: 'Chế độ chỉ số',
qualified: 'Chất lượng cao',
recommend: 'Khuyến nghị',
qualifiedTip: 'Gọi giao diện nhúng hệ thống mặc định để xử lý để cung cấp độ chính xác cao hơn khi người dùng truy vấn.',
warning: 'Vui lòng thiết lập khóa API nhà cung cấp mô hình trước.',
click: 'Đi đến cài đặt',
economical: 'Tiết kiệm',
economicalTip: 'Sử dụng các động cơ vector ngoại tuyến, chỉ số từ khóa, v.v. để giảm chính xác mà không tốn token',
QATitle: 'Phân đoạn theo định dạng Câu hỏi & Trả lời',
QATip: 'Bật tùy chọn này sẽ tiêu tốn thêm token',
QALanguage: 'Phân đoạn bằng',
emstimateCost: 'Ước lượng',
emstimateSegment: 'Đoạn ước tính',
segmentCount: 'đoạn',
calculating: 'Đang tính toán...',
fileSource: 'Tiền xử lý tài liệu',
notionSource: 'Tiền xử lý trang',
other: 'và những ',
fileUnit: ' tệp',
notionUnit: ' trang',
previousStep: 'Bước trước',
nextStep: 'Lưu & Xử lý',
save: 'Lưu & Xử lý',
cancel: 'Hủy bỏ',
sideTipTitle: 'Tại sao phải phân đoạn và tiền xử lý?',
sideTipP1: 'Khi xử lý dữ liệu văn bản, phân đoạn và làm sạch là hai bước tiền xử lý quan trọng.',
sideTipP2: 'Phân đoạn chia nhỏ văn bản dài thành đoạn để mô hình hiểu được tốt hơn. Điều này cải thiện chất lượng và tính liên quan của kết quả mô hình.',
sideTipP3: 'Làm sạch loại bỏ các ký tự và định dạng không cần thiết, làm cho Kiến thức trở nên sạch sẽ và dễ dàng phân tích hơn.',
sideTipP4: 'Phân đoạn và làm sạch đúng cách cải thiện hiệu suất của mô hình, cung cấp kết quả chính xác và có giá trị hơn.',
previewTitle: 'Xem trước',
previewTitleButton: 'Xem trước',
previewButton: 'Chuyển sang dạng Câu hỏi & Trả lời',
previewSwitchTipStart: 'Xem trước đoạn hiện tại đang ở định dạng văn bản, chuyển sang xem trước dạng câu hỏi và trả lời sẽ',
previewSwitchTipEnd: ' tiêu tốn thêm token',
characters: 'ký tự',
indexSettedTip: 'Để thay đổi phương pháp chỉ số, vui lòng đi tới ',
retrivalSettedTip: 'Để thay đổi phương pháp chỉ số, vui lòng đi tới ',
datasetSettingLink: 'cài đặt Kiến thức.',
},
stepThree: {
creationTitle: '🎉 Kiến thức đã được tạo',
creationContent: 'Chúng tôi đã tự động đặt tên cho Kiến thức, bạn có thể sửa đổi nó bất kỳ lúc nào',
label: 'Tên Kiến thức',
additionTitle: '🎉 Tài liệu đã được tải lên',
additionP1: 'Tài liệu đã được tải lên Kiến thức',
additionP2: ', bạn có thể tìm thấy nó trong danh sách tài liệu của Kiến thức.',
stop: 'Dừng xử lý',
resume: 'Tiếp tục xử lý',
navTo: 'Đi đến tài liệu',
sideTipTitle: 'Tiếp theo là gì',
sideTipContent: 'Sau khi tài liệu hoàn thành chỉ mục, Kiến thức có thể được tích hợp vào ứng dụng như một ngữ cảnh, bạn có thể tìm cài đặt ngữ cảnh trong trang chỉ đạo đoạn. Bạn cũng có thể tạo nó như một plugin chỉ mục ChatGPT độc lập để phát hành.',
modelTitle: 'Bạn có chắc chắn muốn dừng việc nhúng?',
modelContent: 'Nếu bạn cần tiếp tục xử lý sau này, bạn sẽ tiếp tục từ vị trí bạn đã dừng lại.',
modelButtonConfirm: 'Xác nhận',
modelButtonCancel: 'Hủy bỏ',
},
}
export default translation

View File

@ -0,0 +1,349 @@
const translation = {
list: {
title: 'Tài liệu',
desc: 'Tất cả các tệp của Kiến thức được hiển thị ở đây, và toàn bộ Kiến thức có thể được liên kết với trích dẫn của Dify hoặc được lập chỉ mục thông qua plugin Chat.',
addFile: 'Thêm tệp',
addPages: 'Thêm Trang',
table: {
header: {
fileName: 'TÊN TỆP',
words: 'TỪ',
hitCount: 'SỐ LẦN TRUY VẤN',
uploadTime: 'THỜI GIAN TẢI LÊN',
status: 'TRẠNG THÁI',
action: 'HÀNH ĐỘNG',
},
},
action: {
uploadFile: 'Tải lên tệp mới',
settings: 'Cài đặt phân đoạn',
addButton: 'Thêm đoạn',
add: 'Thêm một đoạn',
batchAdd: 'Thêm hàng loạt',
archive: 'Lưu trữ',
unarchive: 'Khôi phục',
delete: 'Xóa',
enableWarning: 'Tệp được lưu trữ không thể được kích hoạt',
sync: 'Đồng bộ',
},
index: {
enable: 'Kích hoạt',
disable: 'Vô hiệu hóa',
all: 'Tất cả',
enableTip: 'Tệp có thể được lập chỉ mục',
disableTip: 'Tệp không thể được lập chỉ mục',
},
status: {
queuing: 'Đang chờ',
indexing: 'Đang lập chỉ mục',
paused: 'Tạm dừng',
error: 'Lỗi',
available: 'Có sẵn',
enabled: 'Đã kích hoạt',
disabled: 'Đã vô hiệu hóa',
archived: 'Đã lưu trữ',
},
empty: {
title: 'Chưa có tài liệu',
upload: {
tip: 'Bạn có thể tải lên tệp, đồng bộ từ trang web, hoặc từ ứng dụng web như Notion, GitHub, v.v.',
},
sync: {
tip: 'Dify sẽ định kỳ tải xuống tệp từ Notion của bạn và hoàn tất xử lý.',
},
},
delete: {
title: 'Bạn có chắc chắn muốn xóa?',
content: 'Nếu bạn cần tiếp tục xử lý sau này, bạn sẽ tiếp tục từ vị trí bạn đã dừng lại',
},
batchModal: {
title: 'Thêm đoạn hàng loạt',
csvUploadTitle: 'Kéo và thả tệp CSV của bạn vào đây, hoặc ',
browse: 'duyệt',
tip: 'Tệp CSV phải tuân thủ cấu trúc sau:',
question: 'câu hỏi',
answer: 'trả lời',
contentTitle: 'nội dung đoạn',
content: 'nội dung',
template: 'Tải mẫu ở đây',
cancel: 'Hủy bỏ',
run: 'Chạy Hàng loạt',
runError: 'Chạy hàng loạt thất bại',
processing: 'Đang xử lý hàng loạt',
completed: 'Nhập đã hoàn thành',
error: 'Lỗi nhập',
ok: 'OK',
},
},
metadata: {
title: 'Siêu dữ liệu',
desc: 'Gắn nhãn siêu dữ liệu cho các tài liệu cho phép trí tuệ nhân tạo truy cập chúng một cách kịp thời và tiết lộ nguồn của các tài liệu tham chiếu cho người dùng.',
dateTimeFormat: 'D MMMM, YYYY hh:mm A',
docTypeSelectTitle: 'Vui lòng chọn loại tài liệu',
docTypeChangeTitle: 'Thay đổi loại tài liệu',
docTypeSelectWarning:
'Nếu thay đổi loại tài liệu, các siêu dữ liệu hiện tại sẽ không được bảo toàn nữa',
firstMetaAction: 'Bắt đầu',
placeholder: {
add: 'Thêm ',
select: 'Chọn ',
},
source: {
upload_file: 'Tải lên Tệp',
notion: 'Đồng bộ từ Notion',
github: 'Đồng bộ từ Github',
},
type: {
book: 'Sách',
webPage: 'Trang Web',
paper: 'Bài báo',
socialMediaPost: 'Bài viết trên Mạng xã hội',
personalDocument: 'Tài liệu cá nhân',
businessDocument: 'Tài liệu doanh nghiệp',
IMChat: 'Trò chuyện qua tin nhắn',
wikipediaEntry: 'Bài viết Wikipedia',
notion: 'Đồng bộ từ Notion',
github: 'Đồng bộ từ Github',
technicalParameters: 'Tham số kỹ thuật',
},
field: {
processRule: {
processDoc: 'Xử lý Tài liệu',
segmentRule: 'Quy tắc phân đoạn',
segmentLength: 'Chiều dài các đoạn',
processClean: 'Quy tắc làm sạch Văn bản',
},
book: {
title: 'Tiêu đề',
language: 'Ngôn ngữ',
author: 'Tác giả',
publisher: 'Nhà xuất bản',
publicationDate: 'Ngày xuất bản',
ISBN: 'ISBN',
category: 'Danh mục',
},
webPage: {
title: 'Tiêu đề',
url: 'URL',
language: 'Ngôn ngữ',
authorPublisher: 'Tác giả/Nhà xuất bản',
publishDate: 'Ngày xuất bản',
topicsKeywords: 'Chủ đề/Từ khóa',
description: 'Mô tả',
},
paper: {
title: 'Tiêu đề',
language: 'Ngôn ngữ',
author: 'Tác giả',
publishDate: 'Ngày xuất bản',
journalConferenceName: 'Tên tạp chí/Hội nghị',
volumeIssuePage: 'Số/Trang',
DOI: 'DOI',
topicsKeywords: 'Chủ đề/Từ khóa',
abstract: 'Tóm tắt',
},
socialMediaPost: {
platform: 'Nền tảng',
authorUsername: 'Tác giả/Tên người dùng',
publishDate: 'Ngày đăng',
postURL: 'URL Bài viết',
topicsTags: 'Chủ đề/Thẻ',
},
personalDocument: {
title: 'Tiêu đề',
author: 'Tác giả',
creationDate: 'Ngày tạo',
lastModifiedDate: 'Ngày sửa đổi cuối cùng',
documentType: 'Loại tài liệu',
tagsCategory: 'Thẻ/Danh mục',
},
businessDocument: {
title: 'Tiêu đề',
author: 'Tác giả',
creationDate: 'Ngày tạo',
lastModifiedDate: 'Ngày sửa đổi cuối cùng',
documentType: 'Loại tài liệu',
departmentTeam: 'Phòng ban/Nhóm',
},
IMChat: {
chatPlatform: 'Nền tảng Trò chuyện',
chatPartiesGroupName: 'Đối tác Trò chuyện/Tên nhóm',
participants: 'Tham gia viên',
startDate: 'Ngày bắt đầu',
endDate: 'Ngày kết thúc',
topicsKeywords: 'Chủ đề/Từ khóa',
fileType: 'Loại tệp',
},
wikipediaEntry: {
title: 'Tiêu đề',
language: 'Ngôn ngữ',
webpageURL: 'URL trang web',
editorContributor: 'Biên tập viên/Đóng góp viên',
lastEditDate: 'Ngày chỉnh sửa cuối cùng',
summaryIntroduction: 'Tóm tắt/Giới thiệu',
},
notion: {
title: 'Tiêu đề',
language: 'Ngôn ngữ',
author: 'Tác giả',
createdTime: 'Thời gian tạo',
lastModifiedTime: 'Thời gian chỉnh sửa cuối cùng',
url: 'URL',
tag: 'Thẻ',
description: 'Mô tả',
},
github: {
repoName: 'Tên kho lưu trữ',
repoDesc: 'Mô tả kho lưu trữ',
repoOwner: 'Chủ sở hữu kho lưu trữ',
fileName: 'Tên tệp',
filePath: 'Đường dẫn tệp',
programmingLang: 'Ngôn ngữ lập trình',
url: 'URL',
license: 'Giấy phép',
lastCommitTime: 'Thời gian commit cuối cùng',
lastCommitAuthor: 'Tác giả commit cuối cùng',
},
originInfo: {
originalFilename: 'Tên tệp gốc',
originalFileSize: 'Kích thước tệp gốc',
uploadDate: 'Ngày tải lên',
lastUpdateDate: 'Ngày cập nhật cuối cùng',
source: 'Nguồn',
},
technicalParameters: {
segmentSpecification: 'Đặc tả các đoạn',
segmentLength: 'Chiều dài các đoạn',
avgParagraphLength: 'Độ dài trung bình của đoạn',
paragraphs: 'Các đoạn',
hitCount: 'Số lần truy vấn',
embeddingTime: 'Thời gian nhúng',
embeddedSpend: 'Chi phí nhúng',
},
},
languageMap: {
zh: 'Tiếng Trung',
en: 'Tiếng Anh',
es: 'Tiếng Tây Ban Nha',
fr: 'Tiếng Pháp',
de: 'Tiếng Đức',
ja: 'Tiếng Nhật',
ko: 'Tiếng Hàn',
ru: 'Tiếng Nga',
ar: 'Tiếng Ả Rập',
pt: 'Tiếng Bồ Đào Nha',
it: 'Tiếng Ý',
nl: 'Tiếng Hà Lan',
pl: 'Tiếng Ba Lan',
sv: 'Tiếng Thụy Điển',
tr: 'Tiếng Thổ Nhĩ Kỳ',
he: 'Tiếng Do Thái',
hi: 'Tiếng Hindi',
da: 'Tiếng Đan Mạch',
fi: 'Tiếng Phần Lan',
no: 'Tiếng Na Uy',
hu: 'Tiếng Hungary',
el: 'Tiếng Hy Lạp',
cs: 'Tiếng Séc',
th: 'Tiếng Thái',
id: 'Tiếng Indonesia',
},
categoryMap: {
book: {
fiction: 'Hư cấu',
biography: 'Tiểu sử',
history: 'Lịch sử',
science: 'Khoa học',
technology: 'Công nghệ',
education: 'Giáo dục',
philosophy: 'Triết học',
religion: 'Tôn giáo',
socialSciences: 'Khoa học xã hội',
art: 'Nghệ thuật',
travel: 'Du lịch',
health: 'Sức khỏe',
selfHelp: 'Tự giúp bản thân',
businessEconomics: 'Kinh doanh và kinh tế',
cooking: 'Nấu ăn',
childrenYoungAdults: 'Trẻ em và thanh thiếu niên',
comicsGraphicNovels: 'Truyện tranh và tiểu thuyết đồ họa',
poetry: 'Thơ',
drama: 'Kịch',
other: 'Khác',
},
personalDoc: {
notes: 'Ghi chú',
blogDraft: 'Nháp Blog',
diary: 'Nhật ký',
researchReport: 'Báo cáo nghiên cứu',
bookExcerpt: 'Trích đoạn sách',
schedule: 'Lịch trình',
list: 'Danh sách',
projectOverview: 'Tổng quan dự án',
photoCollection: 'Bộ sưu tập ảnh',
creativeWriting: 'Viết sáng tạo',
codeSnippet: 'Đoạn mã',
designDraft: 'Bản dựng thiết kế',
personalResume: 'Sơ yếu lý lịch cá nhân',
other: 'Khác',
},
businessDoc: {
meetingMinutes: 'Biên bản cuộc họp',
researchReport: 'Báo cáo nghiên cứu',
proposal: 'Đề xuất',
employeeHandbook: 'Sổ tay nhân viên',
trainingMaterials: 'Tài liệu đào tạo',
requirementsDocument: 'Tài liệu yêu cầu',
designDocument: 'Tài liệu thiết kế',
productSpecification: 'Thông số sản phẩm',
financialReport: 'Báo cáo tài chính',
marketAnalysis: 'Phân tích thị trường',
projectPlan: 'Kế hoạch dự án',
teamStructure: 'Cấu trúc nhóm',
policiesProcedures: 'Chính sách và quy trình',
contractsAgreements: 'Hợp đồng và thoả thuận',
emailCorrespondence: 'Thư tín',
other: 'Khác',
},
},
},
embedding: {
processing: 'Đang nhúng...',
paused: 'Đã tạm dừng việc nhúng',
completed: 'Hoàn tất việc nhúng',
error: 'Lỗi khi nhúng',
docName: 'Đang xử lý văn bản',
mode: 'Quy tắc phân đoạn',
segmentLength: 'Chiều dài các đoạn',
textCleaning: 'Định nghĩa và làm sạch Văn bản',
segments: 'Đoạn',
highQuality: 'Chế độ chất lượng cao',
economy: 'Chế độ tiết kiệm',
estimate: 'Ước lượng tiêu thụ',
stop: 'Dừng xử lý',
resume: 'Tiếp tục xử lý',
automatic: 'Tự động',
custom: 'Tùy chỉnh',
previewTip: 'Xem trước đoạn sẽ có sẵn sau khi việc nhúng hoàn tất',
},
segment: {
paragraphs: 'Đoạn',
keywords: 'Từ khóa',
addKeyWord: 'Thêm từ khóa',
keywordError: 'Độ dài tối đa của từ khóa là 20',
characters: 'ký tự',
hitCount: 'Số lần truy vấn',
vectorHash: 'Băm vector: ',
questionPlaceholder: 'thêm câu hỏi ở đây',
questionEmpty: 'Câu hỏi không thể trống',
answerPlaceholder: 'thêm câu trả lời ở đây',
answerEmpty: 'Câu trả lời không thể trống',
contentPlaceholder: 'thêm nội dung ở đây',
contentEmpty: 'Nội dung không thể trống',
newTextSegment: 'Đoạn văn mới',
newQaSegment: 'Đoạn câu hỏi & trả lời mới',
delete: 'Xóa đoạn này?',
},
}
export default translation

View File

@ -0,0 +1,28 @@
const translation = {
title: 'Kiểm Tra Truy Vấn',
desc: 'Kiểm tra hiệu ứng đánh trúng của Kiến thức dựa trên văn bản truy vấn đã cho.',
dateTimeFormat: 'MM/DD/YYYY hh:mm A',
recents: 'Gần đây',
table: {
header: {
source: 'Nguồn',
text: 'Văn bản',
time: 'Thời gian',
},
},
input: {
title: 'Văn bản nguồn',
placeholder: 'Vui lòng nhập một văn bản, một câu khẳng định ngắn được khuyến nghị.',
countWarning: 'Tối đa 200 ký tự.',
indexWarning: 'Chỉ có trong Kiến thức chất lượng cao.',
testing: 'Kiểm tra',
},
hit: {
title: 'RETRIEVAL PARAGRAPHS',
emptyTip: 'Kết quả Kiểm Tra Truy Vấn sẽ hiển thị ở đây',
},
noRecentTip: 'Không có kết quả truy vấn gần đây ở đây',
viewChart: 'Xem VECTOR CHART',
}
export default translation

View File

@ -0,0 +1,33 @@
const translation = {
title: 'Cài đặt Kiến thức',
desc: 'Ở đây, bạn có thể sửa đổi các thuộc tính và phương pháp làm việc của Kiến thức.',
form: {
name: 'Tên Kiến thức',
namePlaceholder: 'Vui lòng nhập tên Kiến thức',
nameError: 'Tên không thể trống',
desc: 'Mô tả Kiến thức',
descInfo: 'Vui lòng viết mô tả văn bản rõ ràng để chỉ rõ nội dung của Kiến thức. Mô tả này sẽ được sử dụng làm cơ sở cho việc kết hợp khi lựa chọn từ nhiều Kiến thức cho sự suy luận.',
descPlaceholder: 'Miêu tả những gì có trong Kiến thức này. Một mô tả chi tiết cho phép AI truy cập nội dung của Kiến thức một cách kịp thời. Nếu trống, Dify sẽ sử dụng chiến lược hit mặc định.',
descWrite: 'Tìm hiểu cách viết mô tả Kiến thức tốt.',
permissions: 'Quyền hạn',
permissionsOnlyMe: 'Chỉ mình tôi',
permissionsAllMember: 'Tất cả thành viên nhóm',
indexMethod: 'Phương pháp chỉ mục',
indexMethodHighQuality: 'Chất lượng cao',
indexMethodHighQualityTip: 'Gọi giao diện nhúng của OpenAI để xử lý để cung cấp độ chính xác cao hơn khi người dùng truy vấn.',
indexMethodEconomy: 'Tiết kiệm',
indexMethodEconomyTip: 'Sử dụng các công cụ nhúng vector ngoại tuyến, chỉ mục từ khóa, v.v. để giảm độ chính xác mà không cần chi tiêu token',
embeddingModel: 'Mô hình nhúng',
embeddingModelTip: 'Để thay đổi mô hình nhúng, vui lòng đi tới ',
embeddingModelTipLink: 'Cài đặt',
retrievalSetting: {
title: 'Cài đặt truy vấn',
learnMore: 'Tìm hiểu thêm',
description: ' về phương pháp truy vấn.',
longDescription: ' về phương pháp truy vấn, bạn có thể thay đổi điều này bất kỳ lúc nào trong cài đặt Kiến thức.',
},
save: 'Lưu',
},
}
export default translation

47
web/i18n/vi-VN/dataset.ts Normal file
View File

@ -0,0 +1,47 @@
const translation = {
knowledge: 'Kiến thức',
documentCount: ' tài liệu',
wordCount: 'k từ',
appCount: ' ứng dụng liên kết',
createDataset: 'Tạo Kiến thức',
createDatasetIntro: 'Nhập dữ liệu văn bản của bạn hoặc viết dữ liệu theo thời gian thực qua Webhook để tăng cường ngữ cảnh LLM.',
deleteDatasetConfirmTitle: 'Xóa Kiến thức này?',
deleteDatasetConfirmContent:
'Xóa Kiến thức là không thể đảo ngược. Người dùng sẽ không còn có khả năng truy cập Kiến thức của bạn nữa, và tất cả các cấu hình và nhật ký nhắc nhở sẽ bị xóa vĩnh viễn.',
datasetDeleted: 'Kiến thức đã bị xóa',
datasetDeleteFailed: 'Xóa Kiến thức không thành công',
didYouKnow: 'Bạn đã biết chưa?',
intro1: 'Kiến thức có thể được tích hợp vào ứng dụng Dify ',
intro2: 'như một ngữ cảnh',
intro3: ',',
intro4: 'hoặc nó ',
intro5: 'có thể được tạo',
intro6: ' dưới dạng một phần cắm chỉ mục ChatGPT độc lập để xuất bản',
unavailable: 'Không khả dụng',
unavailableTip: 'Mô hình nhúng không khả dụng, mô hình nhúng mặc định cần được cấu hình',
datasets: 'KIẾN THỨC',
datasetsApi: 'API',
retrieval: {
semantic_search: {
title: 'Tìm kiếm Vector',
description: 'Tạo các nhúng truy vấn và tìm kiếm phần văn bản giống nhất với biểu diễn vector của nó.',
},
full_text_search: {
title: 'Tìm kiếm Toàn văn bản',
description: 'Chỉ mục tất cả các thuật ngữ trong tài liệu, cho phép người dùng tìm kiếm bất kỳ thuật ngữ nào và truy xuất phần văn bản liên quan chứa các thuật ngữ đó.',
},
hybrid_search: {
title: 'Tìm kiếm Hybrid',
description: 'Thực hiện tìm kiếm toàn văn bản và tìm kiếm vector đồng thời, sắp xếp lại để chọn lựa phù hợp nhất với truy vấn của người dùng. Cấu hình của API mô hình Rerank là cần thiết.',
recommend: 'Gợi ý',
},
invertedIndex: {
title: 'Chỉ mục Nghịch đảo',
description: 'Chỉ mục Nghịch đảo là một cấu trúc được sử dụng cho việc truy xuất hiệu quả. Tổ chức theo thuật ngữ, mỗi thuật ngữ trỏ đến tài liệu hoặc trang web chứa nó.',
},
change: 'Thay đổi',
changeRetrievalMethod: 'Thay đổi phương pháp truy xuất',
},
}
export default translation

41
web/i18n/vi-VN/explore.ts Normal file
View File

@ -0,0 +1,41 @@
const translation = {
title: 'Khám phá',
sidebar: {
discovery: 'Khám phá',
chat: 'Chat',
workspace: 'Kho lưu trữ',
action: {
pin: 'Ghim',
unpin: 'Bỏ ghim',
rename: 'Đổi tên',
delete: 'Xóa',
},
delete: {
title: 'Xóa ứng dụng',
content: 'Bạn có chắc chắn muốn xóa ứng dụng này không?',
},
},
apps: {
title: 'Khám phá Ứng dụng bởi Dify',
description: 'Sử dụng ngay các ứng dụng mẫu này hoặc tùy chỉnh các ứng dụng của bạn dựa trên các mẫu.',
allCategories: 'Tất cả Danh mục',
},
appCard: {
addToWorkspace: 'Thêm vào Kho lưu trữ',
customize: 'Tùy chỉnh',
},
appCustomize: {
title: 'Tạo ứng dụng từ {{name}}',
subTitle: 'Biểu tượng và tên ứng dụng',
nameRequired: 'Tên ứng dụng là bắt buộc',
},
category: {
Assistant: 'Trợ lý',
Writing: 'Viết',
Translate: 'Dịch',
Programming: 'Lập trình',
HR: 'Nhân sự',
},
}
export default translation

4
web/i18n/vi-VN/layout.ts Normal file
View File

@ -0,0 +1,4 @@
const translation = {
}
export default translation

59
web/i18n/vi-VN/login.ts Normal file
View File

@ -0,0 +1,59 @@
const translation = {
pageTitle: 'Xin chào, hãy bắt đầu!👋',
welcome: 'Chào mừng bạn đến với Dify, vui lòng đăng nhập để tiếp tục.',
email: 'Địa chỉ Email',
emailPlaceholder: 'Email của bạn',
password: 'Mật khẩu',
passwordPlaceholder: 'Mật khẩu của bạn',
name: 'Tên người dùng',
namePlaceholder: 'Tên người dùng của bạn',
forget: 'Quên mật khẩu?',
signBtn: 'Đăng nhập',
installBtn: 'Cài đặt',
setAdminAccount: 'Thiết lập tài khoản quản trị',
setAdminAccountDesc: 'Quyền tối đa cho tài khoản quản trị, có thể được sử dụng để tạo ứng dụng và quản lý các nhà cung cấp LLM, v.v.',
createAndSignIn: 'Tạo và đăng nhập',
oneMoreStep: 'Một bước nữa',
createSample: 'Dựa trên thông tin này, chúng tôi sẽ tạo một ứng dụng mẫu cho bạn',
invitationCode: 'Mã mời',
invitationCodePlaceholder: 'Mã mời của bạn',
interfaceLanguage: 'Ngôn ngữ giao diện',
timezone: 'Múi giờ',
go: 'Đi đến Dify',
sendUsMail: 'Gửi email giới thiệu của bạn cho chúng tôi, và chúng tôi sẽ xử lý yêu cầu mời.',
acceptPP: 'Tôi đã đọc và chấp nhận chính sách bảo mật',
reset: 'Vui lòng chạy lệnh sau để đặt lại mật khẩu của bạn',
withGitHub: 'Tiếp tục với GitHub',
withGoogle: 'Tiếp tục với Google',
rightTitle: 'Mở khóa tiềm năng đầy đủ của LLM',
rightDesc: 'Dễ dàng xây dựng ứng dụng AI hấp dẫn mắt, có thể vận hành và cải thiện được.',
tos: 'Điều khoản dịch vụ',
pp: 'Chính sách bảo mật',
tosDesc: 'Bằng cách đăng ký, bạn đồng ý với',
donthave: 'Chưa có?',
invalidInvitationCode: 'Mã mời không hợp lệ',
accountAlreadyInited: 'Tài khoản đã được khởi tạo',
error: {
emailEmpty: 'Địa chỉ Email là bắt buộc',
emailInValid: 'Vui lòng nhập một địa chỉ email hợp lệ',
nameEmpty: 'Tên là bắt buộc',
passwordEmpty: 'Mật khẩu là bắt buộc',
passwordInvalid: 'Mật khẩu phải chứa chữ và số, và độ dài phải lớn hơn 8',
},
license: {
tip: 'Trước khi bắt đầu Phiên bản Cộng đồng của Dify, hãy đọc',
link: 'Giấy phép mã nguồn mở trên GitHub',
},
join: 'Tham gia',
joinTipStart: 'Mời bạn tham gia',
joinTipEnd: 'đội tại Dify',
invalid: 'Liên kết đã hết hạn',
explore: 'Khám phá Dify',
activatedTipStart: 'Bạn đã tham gia',
activatedTipEnd: 'đội',
activated: 'Đăng nhập ngay',
adminInitPassword: 'Mật khẩu khởi tạo quản trị viên',
validate: 'Xác thực',
}
export default translation

View File

@ -0,0 +1,4 @@
const translation = {
}
export default translation

View File

@ -0,0 +1,74 @@
const translation = {
common: {
welcome: 'Chào mừng đến với',
appUnavailable: 'Ứng dụng không khả dụng',
appUnkonwError: 'Ứng dụng không khả dụng',
},
chat: {
newChat: 'Trò chuyện mới',
pinnedTitle: 'Đã ghim',
unpinnedTitle: 'Trò chuyện',
newChatDefaultName: 'Cuộc trò chuyện mới',
resetChat: 'Đặt lại cuộc trò chuyện',
powerBy: 'Được cung cấp bởi',
prompt: 'Lời nhắc',
privatePromptConfigTitle: 'Cài đặt cuộc trò chuyện',
publicPromptConfigTitle: 'Lời nhắc ban đầu',
configStatusDes: 'Trước khi bắt đầu, bạn có thể chỉnh sửa cài đặt cuộc trò chuyện',
configDisabled:
'Cài đặt của phiên trước đã được sử dụng cho phiên này.',
startChat: 'Bắt đầu trò chuyện',
privacyPolicyLeft:
'Vui lòng đọc ',
privacyPolicyMiddle:
'chính sách bảo mật',
privacyPolicyRight:
' được cung cấp bởi nhà phát triển ứng dụng.',
deleteConversation: {
title: 'Xóa cuộc trò chuyện',
content: 'Bạn có chắc muốn xóa cuộc trò chuyện này không?',
},
tryToSolve: 'Thử giải quyết',
temporarySystemIssue: 'Xin lỗi, có sự cố tạm thời của hệ thống.',
},
generation: {
tabs: {
create: 'Chạy Một lần',
batch: 'Chạy Theo Lô',
saved: 'Đã Lưu',
},
savedNoData: {
title: 'Bạn chưa lưu kết quả nào!',
description: 'Bắt đầu tạo nội dung và tìm kết quả đã lưu của bạn ở đây.',
startCreateContent: 'Bắt đầu tạo nội dung',
},
title: 'Hoàn Thiện AI',
queryTitle: 'Nội dung truy vấn',
completionResult: 'Kết quả hoàn thiện',
queryPlaceholder: 'Viết nội dung truy vấn của bạn...',
run: 'Thực thi',
copy: 'Sao chép',
resultTitle: 'Hoàn Thiện AI',
noData: 'AI sẽ đưa ra điều bạn muốn ở đây.',
csvUploadTitle: 'Kéo và thả tệp CSV của bạn vào đây, hoặc ',
browse: 'duyệt',
csvStructureTitle: 'Tệp CSV phải tuân thủ cấu trúc sau:',
downloadTemplate: 'Tải xuống mẫu tại đây',
field: 'Trường',
batchFailed: {
info: '{{num}} thực thi thất bại',
retry: 'Thử lại',
outputPlaceholder: 'Không có nội dung đầu ra',
},
errorMsg: {
empty: 'Vui lòng nhập nội dung vào tệp đã tải lên.',
fileStructNotMatch: 'Tệp CSV tải lên không khớp cấu trúc.',
emptyLine: 'Hàng {{rowIndex}} trống',
invalidLine: 'Hàng {{rowIndex}}: {{varName}} không thể để trống',
moreThanMaxLengthLine: 'Hàng {{rowIndex}}: {{varName}} không thể chứa nhiều hơn {{maxLength}} ký tự',
atLeastOne: 'Vui lòng nhập ít nhất một hàng vào tệp đã tải lên.',
},
},
}
export default translation

115
web/i18n/vi-VN/tools.ts Normal file
View File

@ -0,0 +1,115 @@
const translation = {
title: 'Công cụ',
createCustomTool: 'Tạo Công cụ Tùy chỉnh',
type: {
all: 'Tất cả',
builtIn: 'Tích hợp sẵn',
custom: 'Tùy chỉnh',
},
contribute: {
line1: 'Tôi quan tâm đến việc ',
line2: 'đóng góp công cụ cho Dify.',
viewGuide: 'Xem hướng dẫn',
},
author: 'Bởi',
auth: {
unauthorized: 'Chưa xác thực',
authorized: 'Đã xác thực',
setup: 'Thiết lập xác thực để sử dụng',
setupModalTitle: 'Thiết lập Xác thực',
setupModalTitleDescription: 'Sau khi cấu hình thông tin đăng nhập, tất cả các thành viên trong không gian làm việc có thể sử dụng công cụ này khi triển khai ứng dụng.',
},
includeToolNum: 'Bao gồm {{num}} công cụ',
addTool: 'Thêm Công cụ',
createTool: {
title: 'Tạo Công cụ Tùy chỉnh',
editAction: 'Cấu hình',
editTitle: 'Chỉnh sửa Công cụ Tùy chỉnh',
name: 'Tên',
toolNamePlaceHolder: 'Nhập tên công cụ',
schema: 'Schema',
schemaPlaceHolder: 'Nhập schema OpenAPI của bạn vào đây',
viewSchemaSpec: 'Xem Chi tiết OpenAPI-Swagger',
importFromUrl: 'Nhập từ URL',
importFromUrlPlaceHolder: 'https://...',
urlError: 'Vui lòng nhập URL hợp lệ',
examples: 'Ví dụ',
exampleOptions: {
json: 'Thời tiết (JSON)',
yaml: 'Pet Store (YAML)',
blankTemplate: 'Mẫu Trống',
},
availableTools: {
title: 'Công cụ Hiện có',
name: 'Tên',
description: 'Mô tả',
method: 'Phương thức',
path: 'Đường dẫn',
action: 'Hành động',
test: 'Kiểm tra',
},
authMethod: {
title: 'Phương thức Xác thực',
type: 'Loại xác thực',
keyTooltip: 'Khóa Tiêu đề HTTP, Bạn có thể để trống nếu không biết là gì hoặc đặt nó thành một giá trị tùy chỉnh',
types: {
none: 'Không',
api_key: 'Khóa API',
apiKeyPlaceholder: 'Tên tiêu đề HTTP cho Khóa API',
apiValuePlaceholder: 'Nhập Khóa API',
},
key: 'Khóa',
value: 'Giá trị',
},
authHeaderPrefix: {
title: 'Loại Xác thực',
types: {
basic: 'Cơ bản',
bearer: 'Bearer',
custom: 'Tùy chỉnh',
},
},
privacyPolicy: 'Chính sách bảo mật',
privacyPolicyPlaceholder: 'Vui lòng nhập chính sách bảo mật',
},
test: {
title: 'Kiểm tra',
parametersValue: 'Tham số & Giá trị',
parameters: 'Tham số',
value: 'Giá trị',
testResult: 'Kết quả Kiểm tra',
testResultPlaceholder: 'Kết quả kiểm tra sẽ hiển thị ở đây',
},
thought: {
using: 'Sử dụng',
used: 'Đã sử dụng',
requestTitle: 'Yêu cầu đến',
responseTitle: 'Phản hồi từ',
},
setBuiltInTools: {
info: 'Thông tin',
setting: 'Cài đặt',
toolDescription: 'Mô tả Công cụ',
parameters: 'Tham số',
string: 'chuỗi',
number: 'số',
required: 'Bắt buộc',
infoAndSetting: 'Thông tin & Cài đặt',
},
noCustomTool: {
title: 'Không có công cụ tùy chỉnh!',
content: 'Thêm và quản lý các công cụ tùy chỉnh của bạn ở đây để xây dựng ứng dụng AI.',
createTool: 'Tạo Công cụ',
},
noSearchRes: {
title: 'Xin lỗi, không có kết quả!',
content: 'Chúng tôi không thể tìm thấy bất kỳ công cụ nào phù hợp với tìm kiếm của bạn.',
reset: 'Thiết lập lại Tìm kiếm',
},
builtInPromptTitle: 'Lời nhắc',
toolRemoved: 'Công cụ đã được loại bỏ',
notAuthorized: 'Công cụ chưa được xác thực',
howToGet: 'Cách nhận',
}
export default translation

View File

@ -1,6 +1,6 @@
{
"name": "dify-web",
"version": "0.5.8",
"version": "0.5.9",
"private": true,
"scripts": {
"dev": "next dev",
@ -11,7 +11,8 @@
"eslint-fix": "eslint --fix",
"prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install ./web/.husky",
"gen-icons": "node ./app/components/base/icons/script.js",
"uglify-embed": "node ./bin/uglify-embed"
"uglify-embed": "node ./bin/uglify-embed",
"check-i18n": "node ./i18n/script.js"
},
"dependencies": {
"@babel/runtime": "^7.22.3",