Merge remote-tracking branch 'origin/main' into feat/support-agent-sandbox

# Conflicts:
#	web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx
#	web/package.json
This commit is contained in:
yyh
2026-01-21 10:52:43 +08:00
282 changed files with 1329 additions and 1002 deletions

View File

@ -134,6 +134,9 @@ jobs:
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
# Allow github-actions bot to trigger this workflow via repository_dispatch
# See: https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
allowed_bots: 'github-actions[bot]'
prompt: |
You are a professional i18n synchronization engineer for the Dify project.
Your task is to keep all language translations in sync with the English source (en-US).
@ -285,6 +288,22 @@ jobs:
- `${variable}` - Template literal
- `<tag>content</tag>` - HTML tags
- `_one`, `_other` - Pluralization suffixes (these are KEY suffixes, not values)
**CRITICAL: Variable names and tag names MUST stay in English - NEVER translate them**
✅ CORRECT examples:
- English: "{{count}} items" → Japanese: "{{count}} 個のアイテム"
- English: "{{name}} updated" → Korean: "{{name}} 업데이트됨"
- English: "<email>{{email}}</email>" → Chinese: "<email>{{email}}</email>"
- English: "<CustomLink>Marketplace</CustomLink>" → Japanese: "<CustomLink>マーケットプレイス</CustomLink>"
❌ WRONG examples (NEVER do this - will break the application):
- "{{count}}" → "{{カウント}}" ❌ (variable name translated to Japanese)
- "{{name}}" → "{{이름}}" ❌ (variable name translated to Korean)
- "{{email}}" → "{{邮箱}}" ❌ (variable name translated to Chinese)
- "<email>" → "<メール>" ❌ (tag name translated)
- "<CustomLink>" → "<自定义链接>" ❌ (component name translated)
- Use appropriate language register (formal/informal) based on existing translations
- Match existing translation style in each language
- Technical terms: check existing conventions per language

1
web/.npmrc Normal file
View File

@ -0,0 +1 @@
save-exact=true

View File

@ -71,7 +71,7 @@ const DatasetInfo: FC<DatasetInfoProps> = ({
</div>
<div className="system-2xs-medium-uppercase text-text-tertiary">
{isExternalProvider && t('externalTag', { ns: 'dataset' })}
{!isExternalProvider && isPipelinePublished && dataset.doc_form && dataset.indexing_technique && (
{!!(!isExternalProvider && isPipelinePublished && dataset.doc_form && dataset.indexing_technique) && (
<div className="flex items-center gap-x-2">
<span>{t(`chunkingMode.${DOC_FORM_TEXT[dataset.doc_form]}`, { ns: 'dataset' })}</span>
<span>{formatIndexingTechniqueAndMethod(dataset.indexing_technique, dataset.retrieval_model_dict?.search_method)}</span>

View File

@ -114,7 +114,7 @@ const DatasetSidebarDropdown = ({
</div>
<div className="system-2xs-medium-uppercase text-text-tertiary">
{isExternalProvider && t('externalTag', { ns: 'dataset' })}
{!isExternalProvider && dataset.doc_form && dataset.indexing_technique && (
{!!(!isExternalProvider && dataset.doc_form && dataset.indexing_technique) && (
<div className="flex items-center gap-x-2">
<span>{t(`chunkingMode.${DOC_FORM_TEXT[dataset.doc_form]}`, { ns: 'dataset' })}</span>
<span>{formatIndexingTechniqueAndMethod(dataset.indexing_technique, dataset.retrieval_model_dict?.search_method)}</span>

View File

@ -144,7 +144,7 @@ const EditAnnotationModal: FC<Props> = ({
<MessageCheckRemove />
<div>{t('editModal.removeThisCache', { ns: 'appAnnotation' })}</div>
</div>
{createdAt && (
{!!createdAt && (
<div>
{t('editModal.createdAt', { ns: 'appAnnotation' })}
&nbsp;

View File

@ -28,16 +28,16 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({
<div className={cn('px-3 pt-2', hasHeaderBottomBorder && 'border-b border-divider-subtle')} data-testid="feature-panel-header">
<div className="flex h-8 items-center justify-between">
<div className="flex shrink-0 items-center space-x-1">
{headerIcon && <div className="flex h-6 w-6 items-center justify-center">{headerIcon}</div>}
{!!headerIcon && <div className="flex h-6 w-6 items-center justify-center">{headerIcon}</div>}
<div className="system-sm-semibold text-text-secondary">{title}</div>
</div>
<div className="flex items-center gap-2">
{headerRight && <div>{headerRight}</div>}
{!!headerRight && <div>{headerRight}</div>}
</div>
</div>
</div>
{/* Body */}
{children && (
{!!children && (
<div className={cn(!noBodySpacing && 'mt-1 px-3')} data-testid="feature-panel-body">
{children}
</div>

View File

@ -91,7 +91,7 @@ const Item: FC<ItemProps> = ({
</ActionButton>
</div>
{
config.indexing_technique && (
!!config.indexing_technique && (
<Badge
className="shrink-0 group-hover:hidden"
text={formatIndexingTechniqueAndMethod(config.indexing_technique, config.retrieval_model_dict?.search_method)}

View File

@ -175,7 +175,7 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
</div>
)}
{
item.indexing_technique && (
!!item.indexing_technique && (
<Badge
className="shrink-0"
text={formatIndexingTechniqueAndMethod(item.indexing_technique, item.retrieval_model_dict?.search_method)}

View File

@ -247,7 +247,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
/>
</div>
</div>
{currentDataset && currentDataset.indexing_technique && (
{!!(currentDataset && currentDataset.indexing_technique) && (
<div className={cn(rowClass)}>
<div className={labelClass}>
<div className="system-sm-semibold text-text-secondary">{t('form.indexMethod', { ns: 'datasetSettings' })}</div>

View File

@ -465,8 +465,8 @@ vi.mock('@/app/components/base/chat/chat', () => ({
</div>
))}
</div>
{questionIcon && <div data-testid="question-icon">{questionIcon}</div>}
{answerIcon && <div data-testid="answer-icon">{answerIcon}</div>}
{!!questionIcon && <div data-testid="question-icon">{questionIcon}</div>}
{!!answerIcon && <div data-testid="answer-icon">{answerIcon}</div>}
<textarea
data-testid="chat-input"
placeholder="Type a message"

View File

@ -72,7 +72,7 @@ const ToolCallItem: FC<Props> = ({ toolCall, isLLM = false, isFinal, tokens, obs
{toolName}
</div>
<div className="shrink-0 text-xs leading-[18px] text-text-tertiary">
{toolCall.time_cost && (
{!!toolCall.time_cost && (
<span>{getTime(toolCall.time_cost || 0)}</span>
)}
{isLLM && (

View File

@ -219,7 +219,7 @@ const Answer: FC<AnswerProps> = ({
)
}
{
item.siblingCount && item.siblingCount > 1 && item.siblingIndex !== undefined && (
!!(item.siblingCount && item.siblingCount > 1 && item.siblingIndex !== undefined) && (
<ContentSwitch
count={item.siblingCount}
currentIndex={item.siblingIndex}

View File

@ -29,7 +29,7 @@ const More: FC<MoreProps> = ({
>
{`${t('detail.tokenCost', { ns: 'appLog' })} ${formatNumber(more.tokens)}`}
</div>
{more.tokens_per_second && (
{!!more.tokens_per_second && (
<div
className="mr-2 max-w-[25%] shrink-0 truncate"
title={`${more.tokens_per_second} tokens/s`}

View File

@ -146,7 +146,7 @@ const Popup: FC<PopupProps> = ({
icon={<BezierCurve03 className="mr-1 h-3 w-3" />}
/>
{
source.score && (
!!source.score && (
<ProgressTooltip data={Number(source.score.toFixed(2))} />
)
}

View File

@ -90,7 +90,7 @@ const UploaderButton: FC<UploaderButtonProps> = ({
<PortalToFollowElemContent className="z-50">
<div className="w-[260px] rounded-lg border-[0.5px] border-gray-200 bg-white p-2 shadow-lg">
<ImageLinkInput onUpload={handleUpload} disabled={disabled} />
{hasUploadFromLocal && (
{!!hasUploadFromLocal && (
<>
<div className="mt-2 flex items-center px-2 text-xs font-medium text-gray-400">
<div className="mr-3 h-px w-[93px] bg-gradient-to-l from-[#F3F4F6]" />

View File

@ -109,7 +109,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(({
disabled={disabled}
{...props}
/>
{showClearIcon && value && !disabled && !destructive && (
{!!(showClearIcon && value && !disabled && !destructive) && (
<div
className={cn('group absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer p-[1px]')}
onClick={onClear}

View File

@ -52,7 +52,7 @@ export default function Modal({
<div className={cn('flex min-h-full items-center justify-center p-4 text-center', containerClassName)}>
<TransitionChild>
<DialogPanel className={cn('relative w-full max-w-[480px] rounded-2xl bg-components-panel-bg p-6 text-left align-middle shadow-xl transition-all', overflowVisible ? 'overflow-visible' : 'overflow-hidden', 'duration-100 ease-in data-[closed]:scale-95 data-[closed]:opacity-0', 'data-[enter]:scale-100 data-[enter]:opacity-100', 'data-[enter]:scale-95 data-[leave]:opacity-0', className)}>
{title && (
{!!title && (
<DialogTitle
as="h3"
className="title-2xl-semi-bold text-text-primary"
@ -60,7 +60,7 @@ export default function Modal({
{title}
</DialogTitle>
)}
{description && (
{!!description && (
<div className="body-md-regular mt-2 text-text-secondary">
{description}
</div>

View File

@ -87,7 +87,7 @@ const Modal = ({
</div>
</div>
{
children && (
!!children && (
<div className="min-h-0 flex-1 overflow-y-auto px-6 py-3">{children}</div>
)
}
@ -126,7 +126,7 @@ const Modal = ({
</Button>
</div>
</div>
{bottomSlot && (
{!!bottomSlot && (
<div className="shrink-0">
{bottomSlot}
</div>

View File

@ -56,7 +56,7 @@ const RadioCard: FC<Props> = ({
</div>
)}
</div>
{((isChosen && chosenConfig) || noRadio) && (
{!!((isChosen && chosenConfig) || noRadio) && (
<div className="mt-2 flex gap-x-2">
<div className="size-8 shrink-0"></div>
<div className={cn(chosenConfigWrapClassName, 'grow')}>

View File

@ -52,7 +52,7 @@ export default function Radio({
)}
onClick={() => handleChange(value)}
>
{children && (
{!!children && (
<label
className={
cn(labelClassName, 'cursor-pointer text-sm')

View File

@ -130,7 +130,7 @@ export const SegmentedControl = <T extends string | number | symbol>({
{text && (
<div className={cn('inline-flex items-center gap-x-1', ItemTextWrapperVariants({ size }))}>
<span>{text}</span>
{count && size === 'large' && (
{!!(count && size === 'large') && (
<div className="system-2xs-medium-uppercase inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-[5px] border border-divider-deep bg-components-badge-bg-dimm px-[5px] text-text-tertiary">
{count}
</div>

View File

@ -379,7 +379,7 @@ const PortalSelect: FC<PortalSelectProps> = ({
{selectedItem?.name ?? localPlaceholder}
</span>
<div className="mx-0.5">
{installedValue && selectedItem && selectedItem.value !== installedValue && (
{!!(installedValue && selectedItem && selectedItem.value !== installedValue) && (
<Badge>
{installedValue}
{' '}

View File

@ -80,7 +80,7 @@ const Toast = ({
<div className="system-sm-semibold text-text-primary [word-break:break-word]">{message}</div>
{customComponent}
</div>
{children && (
{!!children && (
<div className="system-xs-regular text-text-secondary">
{children}
</div>

View File

@ -12,11 +12,11 @@ export const ToolTipContent: FC<ToolTipContentProps> = ({
}) => {
return (
<div className="w-[180px]">
{title && (
{!!title && (
<div className="mb-1.5 font-semibold text-text-secondary">{title}</div>
)}
<div className="mb-1.5 text-text-tertiary">{children}</div>
{action && <div className="cursor-pointer text-text-accent">{action}</div>}
{!!action && <div className="cursor-pointer text-text-accent">{action}</div>}
</div>
)
}

View File

@ -109,7 +109,7 @@ const Tooltip: FC<TooltipProps> = ({
<PortalToFollowElemContent
className={cn('z-[9999]', portalContentClassName || '')}
>
{popupContent && (
{!!popupContent && (
<div
className={cn(
!noDecoration && 'system-xs-regular relative max-w-[300px] break-words rounded-md bg-components-panel-bg px-3 py-2 text-left text-text-tertiary shadow-lg',

View File

@ -87,10 +87,10 @@ export const OptionCard: FC<OptionCardProps> = (
disabled={disabled}
/>
{/** Body */}
{isActive && (children || actions) && (
{!!(isActive && (children || actions)) && (
<div className="rounded-b-xl bg-components-panel-bg px-4 py-3">
{children}
{actions && (
{!!actions && (
<div className="mt-4 flex gap-2">
{actions}
</div>

View File

@ -508,7 +508,7 @@ const DocumentList: FC<IDocumentListProps> = ({
/>
)}
{/* Show Pagination only if the total is more than the limit */}
{pagination.total && (
{!!pagination.total && (
<Pagination
{...pagination}
className="w-full shrink-0"

View File

@ -24,7 +24,7 @@ vi.mock('@/app/components/datasets/documents/detail/metadata', () => ({
<div data-testid="field-info" data-label={label}>
<span data-testid="field-label">{label}</span>
<span data-testid="field-value">{displayedValue}</span>
{valueIcon && <span data-testid="field-icon">{valueIcon}</span>}
{!!valueIcon && <span data-testid="field-icon">{valueIcon}</span>}
</div>
),
}))

View File

@ -49,7 +49,7 @@ const DocModeInfo = ({
return (
<div className="system-2xs-medium-uppercase flex items-center gap-x-3 text-text-tertiary">
{dataset.doc_form && (
{!!dataset.doc_form && (
<span
className="min-w-0 max-w-full truncate"
title={t(`chunkingMode.${DOC_FORM_TEXT[dataset.doc_form]}`, { ns: 'dataset' })}

View File

@ -27,7 +27,7 @@ vi.mock('../../../base/modal-like-wrap', () => ({
default: ({ children, title, onClose, onConfirm, beforeHeader }: ModalLikeWrapProps) => (
<div data-testid="modal-wrap">
<div data-testid="modal-title">{title}</div>
{beforeHeader && <div data-testid="before-header">{beforeHeader}</div>}
{!!beforeHeader && <div data-testid="before-header">{beforeHeader}</div>}
<div data-testid="modal-content">{children}</div>
<button data-testid="close-btn" onClick={onClose}>Close</button>
<button data-testid="confirm-btn" onClick={onConfirm}>Confirm</button>

View File

@ -265,7 +265,7 @@ const Form = () => {
</div>
</div>
{
currentDataset?.doc_form && (
!!currentDataset?.doc_form && (
<>
<Divider
type="horizontal"
@ -298,13 +298,13 @@ const Form = () => {
</>
)
}
{(isShowIndexMethod || indexMethod === 'high_quality') && (
{!!(isShowIndexMethod || indexMethod === 'high_quality') && (
<Divider
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
)}
{isShowIndexMethod && (
{!!isShowIndexMethod && (
<div className={rowClass}>
<div className={labelClass}>
<div className="system-sm-semibold text-text-secondary">{t('form.indexMethod', { ns: 'datasetSettings' })}</div>

View File

@ -77,7 +77,7 @@ const OptionCard = <T,>({
)
}
{
icon && (
!!icon && (
<div className={cn(
'flex size-6 shrink-0 items-center justify-center text-text-tertiary',
isActive && iconActiveColor,
@ -110,7 +110,7 @@ const OptionCard = <T,>({
</div>
</div>
{
children && showChildren && (
!!(children && showChildren) && (
<div className="relative rounded-b-xl bg-components-panel-bg p-4">
<ArrowShape className="absolute left-[14px] top-[-11px] size-4 text-components-panel-bg" />
{children}

View File

@ -48,21 +48,21 @@ const ModelName: FC<ModelNameProps> = ({
</div>
<div className="flex items-center gap-0.5">
{
showModelType && modelItem.model_type && (
!!(showModelType && modelItem.model_type) && (
<ModelBadge className={modelTypeClassName}>
{modelTypeFormat(modelItem.model_type)}
</ModelBadge>
)
}
{
modelItem.model_properties.mode && showMode && (
!!(modelItem.model_properties.mode && showMode) && (
<ModelBadge className={modeClassName}>
{(modelItem.model_properties.mode as string).toLocaleUpperCase()}
</ModelBadge>
)
}
{
showContextSize && modelItem.model_properties.context_size && (
!!(showContextSize && modelItem.model_properties.context_size) && (
<ModelBadge>
{sizeFormat(modelItem.model_properties.context_size as number)}
</ModelBadge>

View File

@ -104,17 +104,17 @@ const PopupItem: FC<PopupItemProps> = ({
/>
)
}
{modelItem.model_type && (
{!!modelItem.model_type && (
<ModelBadge>
{modelTypeFormat(modelItem.model_type)}
</ModelBadge>
)}
{modelItem.model_properties.mode && (
{!!modelItem.model_properties.mode && (
<ModelBadge>
{(modelItem.model_properties.mode as string).toLocaleUpperCase()}
</ModelBadge>
)}
{modelItem.model_properties.context_size && (
{!!modelItem.model_properties.context_size && (
<ModelBadge>
{sizeFormat(modelItem.model_properties.context_size as number)}
</ModelBadge>

View File

@ -5,7 +5,7 @@ import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { AnthropicShortLight, Deepseek, Gemini, Grok, OpenaiSmall, Tongyi } from '@/app/components/base/icons/src/public/llm'
import { OpenaiSmall } from '@/app/components/base/icons/src/public/llm'
import Loading from '@/app/components/base/loading'
import Tooltip from '@/app/components/base/tooltip'
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
@ -19,11 +19,11 @@ import { modelNameMap, ModelProviderQuotaGetPaid } from '../utils'
const allProviders = [
{ key: ModelProviderQuotaGetPaid.OPENAI, Icon: OpenaiSmall },
{ key: ModelProviderQuotaGetPaid.ANTHROPIC, Icon: AnthropicShortLight },
{ key: ModelProviderQuotaGetPaid.GEMINI, Icon: Gemini },
{ key: ModelProviderQuotaGetPaid.X, Icon: Grok },
{ key: ModelProviderQuotaGetPaid.DEEPSEEK, Icon: Deepseek },
{ key: ModelProviderQuotaGetPaid.TONGYI, Icon: Tongyi },
// { key: ModelProviderQuotaGetPaid.ANTHROPIC, Icon: AnthropicShortLight },
// { key: ModelProviderQuotaGetPaid.GEMINI, Icon: Gemini },
// { key: ModelProviderQuotaGetPaid.X, Icon: Grok },
// { key: ModelProviderQuotaGetPaid.DEEPSEEK, Icon: Deepseek },
// { key: ModelProviderQuotaGetPaid.TONGYI, Icon: Tongyi },
] as const
// Map provider key to plugin ID

View File

@ -81,7 +81,7 @@ vi.mock('@/app/components/base/app-icon', () => ({
data-size={size}
data-icon-type={iconType}
>
{innerIcon && <div data-testid="inner-icon">{innerIcon}</div>}
{!!innerIcon && <div data-testid="inner-icon">{innerIcon}</div>}
</div>
),
}))

View File

@ -95,7 +95,7 @@ const Card = ({
text={getLocalizedText(brief)}
descriptionLineRows={descriptionLineRows}
/>
{footer && <div>{footer}</div>}
{!!footer && <div>{footer}</div>}
</div>
{limitedInstall
&& (

View File

@ -32,7 +32,7 @@ vi.mock('../../../card', () => ({
default: ({ payload, titleLeft }: { payload: Plugin, titleLeft?: React.ReactNode }) => (
<div data-testid="plugin-card">
<span data-testid="card-name">{payload.name}</span>
{titleLeft && <span data-testid="title-left">{titleLeft}</span>}
{!!titleLeft && <span data-testid="title-left">{titleLeft}</span>}
</div>
),
}))

View File

@ -118,7 +118,7 @@ vi.mock('../../../card', () => ({
<div data-testid="plugin-card">
<span data-testid="card-payload-name">{payload?.name}</span>
<span data-testid="card-limited-install">{limitedInstall ? 'true' : 'false'}</span>
{titleLeft && <div data-testid="card-title-left">{titleLeft}</div>}
{!!titleLeft && <div data-testid="card-title-left">{titleLeft}</div>}
</div>
),
}))

View File

@ -279,7 +279,7 @@ vi.mock('@/app/components/plugins/card', () => ({
default: ({ payload, footer }: { payload: Plugin, footer?: React.ReactNode }) => (
<div data-testid={`card-${payload.name}`}>
<div data-testid="card-name">{payload.name}</div>
{footer && <div data-testid="card-footer">{footer}</div>}
{!!footer && <div data-testid="card-footer">{footer}</div>}
</div>
),
}))

View File

@ -126,7 +126,7 @@ vi.mock('@/app/components/plugins/card', () => ({
<div data-testid={`card-${payload.name}`}>
<div data-testid="card-name">{payload.name}</div>
<div data-testid="card-label">{payload.label?.['en-US'] || payload.name}</div>
{footer && <div data-testid="card-footer">{footer}</div>}
{!!footer && <div data-testid="card-footer">{footer}</div>}
</div>
),
}))

View File

@ -229,7 +229,7 @@ const DetailHeader = ({
<div className="flex h-5 items-center">
<Title title={label[locale]} />
{verified && !isReadmeView && <Verified className="ml-0.5 h-4 w-4" text={t('marketplace.verifiedTip', { ns: 'plugin' })} />}
{version && (
{!!version && (
<PluginVersionPicker
disabled={!isFromMarketplace || isReadmeView}
isShow={isShow}
@ -297,7 +297,7 @@ const DetailHeader = ({
orgName={author}
packageName={name?.includes('/') ? (name.split('/').pop() || '') : name}
/>
{source && (
{!!source && (
<>
<div className="system-xs-regular ml-1 mr-0.5 text-text-quaternary">·</div>
{source === PluginSource.marketplace && (

View File

@ -196,7 +196,7 @@ vi.mock('@/app/components/base/modal/modal', () => ({
{extraButtonText}
</button>
)}
{bottomSlot && <div data-testid="modal-bottom-slot">{bottomSlot}</div>}
{!!bottomSlot && <div data-testid="modal-bottom-slot">{bottomSlot}</div>}
</div>
),
}))

View File

@ -78,7 +78,7 @@ vi.mock('@/app/components/base/app-icon', () => ({
data-size={size}
data-icon-type={iconType}
>
{innerIcon && <div data-testid="inner-icon">{innerIcon}</div>}
{!!innerIcon && <div data-testid="inner-icon">{innerIcon}</div>}
</div>
),
}))

View File

@ -41,7 +41,7 @@ const Empty = ({
<div className="mb-1 mt-2 text-[13px] font-medium leading-[18px] text-text-primary">
{(hasTitle && renderType) ? t(`addToolModal.${renderType}.title`, { ns: 'tools' }) : 'No tools available'}
</div>
{(!isAgent && hasTitle && renderType) && (
{!!(!isAgent && hasTitle && renderType) && (
<Comp className={cn('flex items-center text-[13px] leading-[18px] text-text-tertiary', hasLink && 'cursor-pointer hover:text-text-accent')} {...linkProps}>
{t(`addToolModal.${renderType}.tip`, { ns: 'tools' })}
{' '}

View File

@ -95,7 +95,7 @@ const Base: FC<Props> = ({
}}
>
{headerRight}
{showCodeGenerator && codeLanguages && (
{!!(showCodeGenerator && codeLanguages) && (
<div className="ml-1">
<CodeGeneratorButton
onGenerated={onGenerated}
@ -119,7 +119,7 @@ const Base: FC<Props> = ({
</div>
</div>
</div>
{tip && <div className="px-1 py-0.5">{tip}</div>}
{!!tip && <div className="px-1 py-0.5">{tip}</div>}
<PromptEditorHeightResizeWrap
height={isExpand ? editorExpandHeight : editorContentHeight}
minHeight={editorContentMinHeight}

View File

@ -46,7 +46,7 @@ const Field: FC<Props> = ({
{' '}
{required && <span className="text-text-destructive">*</span>}
</div>
{tooltip && (
{!!tooltip && (
<Tooltip
popupContent={tooltip}
popupClassName="ml-1"
@ -55,13 +55,13 @@ const Field: FC<Props> = ({
)}
</div>
<div className="flex">
{operations && <div>{operations}</div>}
{!!operations && <div>{operations}</div>}
{supportFold && (
<RiArrowDownSLine className="h-4 w-4 cursor-pointer text-text-tertiary transition-transform" style={{ transform: fold ? 'rotate(-90deg)' : 'rotate(0deg)' }} />
)}
</div>
</div>
{children && (!supportFold || (supportFold && !fold)) && <div className={cn(!inline && 'mt-1')}>{children}</div>}
{!!(children && (!supportFold || (supportFold && !fold))) && <div className={cn(!inline && 'mt-1')}>{children}</div>}
</div>
)
}

View File

@ -167,7 +167,7 @@ const Editor: FC<Props> = ({
{' '}
{required && <span className="text-text-destructive">*</span>}
</div>
{titleTooltip && <Tooltip popupContent={titleTooltip} />}
{!!titleTooltip && <Tooltip popupContent={titleTooltip} />}
</div>
<div className="flex items-center">
<div className="text-xs font-medium leading-[18px] text-text-tertiary">{value?.length || 0}</div>

View File

@ -61,7 +61,7 @@ const VariableLabel = ({
notShowFullPath={notShowFullPath}
/>
{
variableType && (
!!variableType && (
<div className="system-xs-regular shrink-0 text-text-tertiary">
{capitalize(variableType)}
</div>

View File

@ -322,7 +322,7 @@ const BaseNode: FC<BaseNodeProps> = ({
}
</div>
{
data._iterationLength && data._iterationIndex && data._runningStatus === NodeRunningStatus.Running && (
!!(data._iterationLength && data._iterationIndex && data._runningStatus === NodeRunningStatus.Running) && (
<div className="mr-1.5 text-xs font-medium text-text-accent">
{data._iterationIndex > data._iterationLength ? data._iterationLength : data._iterationIndex}
/
@ -331,7 +331,7 @@ const BaseNode: FC<BaseNodeProps> = ({
)
}
{
data.type === BlockEnum.Loop && data._loopIndex && LoopIndex
!!(data.type === BlockEnum.Loop && data._loopIndex) && LoopIndex
}
{
isLoading
@ -374,7 +374,7 @@ const BaseNode: FC<BaseNodeProps> = ({
)
}
{
data.desc && data.type !== BlockEnum.Iteration && data.type !== BlockEnum.Loop && (
!!(data.desc && data.type !== BlockEnum.Iteration && data.type !== BlockEnum.Loop) && (
<div className="system-xs-regular whitespace-pre-line break-words px-3 pb-2 pt-1 text-text-tertiary">
{data.desc}
</div>

View File

@ -178,7 +178,7 @@ const VarList: FC<Props> = ({
className="w-full"
/>
)}
{item.operation === WriteMode.set && assignedVarType && (
{!!(item.operation === WriteMode.set && assignedVarType) && (
<>
{assignedVarType === 'number' && (
<Input

View File

@ -51,7 +51,7 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
nodeType={node?.data.type}
nodeTitle={node?.data.title}
rightSlot={
value.operation && <Badge className="!ml-auto shrink-0" text={t(`${i18nPrefix}.operations.${value.operation}`, { ns: 'workflow' })} />
!!value.operation && <Badge className="!ml-auto shrink-0" text={t(`${i18nPrefix}.operations.${value.operation}`, { ns: 'workflow' })} />
}
/>
)

View File

@ -41,7 +41,7 @@ const ChunkStructure = ({
}}
>
{
chunkStructure && (
!!chunkStructure && (
<OptionCard
{...optionMap[chunkStructure]}
selectedId={chunkStructure}

View File

@ -100,7 +100,7 @@ const OptionCard = memo(({
>
{effectElement}
{
icon && (
!!icon && (
<div className="mr-1 flex h-[18px] w-[18px] shrink-0 items-center justify-center">
{typeof icon === 'function' ? icon(isActive) : icon}
</div>
@ -139,7 +139,7 @@ const OptionCard = memo(({
</div>
</div>
{
children && isActive && (
!!(children && isActive) && (
<div className="relative rounded-b-xl bg-components-panel-bg p-3">
<ArrowShape className="absolute left-[14px] top-[-11px] h-4 w-4 text-components-panel-bg" />
{children}

View File

@ -118,7 +118,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
/>
</Group>
{
data.chunk_structure && (
!!data.chunk_structure && (
<>
<BoxGroupField
boxGroupProps={{

View File

@ -110,7 +110,7 @@ const DatasetItem: FC<Props> = ({
</div>
)}
{
payload.indexing_technique && (
!!payload.indexing_technique && (
<Badge
className="shrink-0 group-hover/dataset-item:hidden"
text={formatIndexingTechniqueAndMethod(payload.indexing_technique, payload.retrieval_model_dict?.search_method)}

View File

@ -46,7 +46,7 @@ const ConditionDate = ({
}
</div>
{
value && (
!!value && (
<RiCloseCircleFill
className={cn(
'hidden h-4 w-4 shrink-0 cursor-pointer hover:text-components-input-text-filled group-hover:block',

View File

@ -123,7 +123,7 @@ const ConfigPromptItem: FC<Props> = ({
<Tooltip
popupContent={
<div className="max-w-[180px]">{payload.role && t(`${i18nPrefix}.roleDescription.${payload.role}`, { ns: 'workflow' })}</div>
<div className="max-w-[180px]">{!!payload.role && t(`${i18nPrefix}.roleDescription.${payload.role}`, { ns: 'workflow' })}</div>
}
triggerClassName="w-4 h-4"
/>

View File

@ -86,7 +86,7 @@ const ConditionList = ({
className="absolute right-1 top-1/2 flex h-[21px] -translate-y-1/2 cursor-pointer select-none items-center rounded-md border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-1 text-[10px] font-semibold text-text-accent-secondary shadow-xs"
onClick={() => doToggleConditionLogicalOperator(conditionId)}
>
{logicalOperator && logicalOperator.toUpperCase()}
{!!logicalOperator && logicalOperator.toUpperCase()}
<RiLoopLeftLine className="ml-0.5 h-3 w-3" />
</div>
</div>

View File

@ -115,7 +115,7 @@ const ConversationVariableModal = ({
}}
>
</div>
{latestValueTimestampMap[currentVar.id] && (
{!!latestValueTimestampMap[currentVar.id] && (
<div className="system-xs-regular shrink-0 text-text-tertiary">
{t('chatVariable.updatedAt', { ns: 'workflow' })}
{formatTime(latestValueTimestampMap[currentVar.id], t('dateTimeFormat', { ns: 'appLog' }) as string)}

View File

@ -79,7 +79,7 @@ const AgentLogItem = ({
{label}
</div>
{
metadata?.elapsed_time && (
!!metadata?.elapsed_time && (
<div className="system-xs-regular mr-2 shrink-0 text-text-tertiary">
{metadata?.elapsed_time?.toFixed(3)}
s

View File

@ -1,6 +1,8 @@
import consistentPlaceholders from './rules/consistent-placeholders.js'
import noAsAnyInT from './rules/no-as-any-in-t.js'
import noExtraKeys from './rules/no-extra-keys.js'
import noLegacyNamespacePrefix from './rules/no-legacy-namespace-prefix.js'
import noVersionPrefix from './rules/no-version-prefix.js'
import requireNsOption from './rules/require-ns-option.js'
import validI18nKeys from './rules/valid-i18n-keys.js'
@ -11,9 +13,11 @@ const plugin = {
version: '1.0.0',
},
rules: {
'consistent-placeholders': consistentPlaceholders,
'no-as-any-in-t': noAsAnyInT,
'no-extra-keys': noExtraKeys,
'no-legacy-namespace-prefix': noLegacyNamespacePrefix,
'no-version-prefix': noVersionPrefix,
'require-ns-option': requireNsOption,
'valid-i18n-keys': validI18nKeys,
},

View File

@ -0,0 +1,109 @@
import fs from 'node:fs'
import path, { normalize, sep } from 'node:path'
import { cleanJsonText } from '../utils.js'
/**
* Extract placeholders from a string
* Matches patterns like {{name}}, {{count}}, etc.
* @param {string} str
* @returns {string[]} Sorted array of placeholder names
*/
function extractPlaceholders(str) {
const matches = str.match(/\{\{\w+\}\}/g) || []
return matches.map(m => m.slice(2, -2)).sort()
}
/**
* Compare two arrays and return if they're equal
* @param {string[]} arr1
* @param {string[]} arr2
* @returns {boolean} True if arrays contain the same elements in the same order
*/
function arraysEqual(arr1, arr2) {
if (arr1.length !== arr2.length)
return false
return arr1.every((val, i) => val === arr2[i])
}
/** @type {import('eslint').Rule.RuleModule} */
export default {
meta: {
type: 'problem',
docs: {
description: 'Ensure placeholders in translations match the en-US source',
},
},
create(context) {
return {
Program(node) {
const { filename, sourceCode } = context
if (!filename.endsWith('.json'))
return
const parts = normalize(filename).split(sep)
const jsonFile = parts.at(-1)
const lang = parts.at(-2)
// Skip English files - they are the source of truth
if (lang === 'en-US')
return
let currentJson = {}
let englishJson = {}
try {
currentJson = JSON.parse(cleanJsonText(sourceCode.text))
const englishFilePath = path.join(path.dirname(filename), '..', 'en-US', jsonFile ?? '')
englishJson = JSON.parse(fs.readFileSync(englishFilePath, 'utf8'))
}
catch (error) {
context.report({
node,
message: `Error parsing JSON: ${error instanceof Error ? error.message : String(error)}`,
})
return
}
// Check each key in the current translation
for (const key of Object.keys(currentJson)) {
// Skip if the key doesn't exist in English (handled by no-extra-keys rule)
if (!Object.prototype.hasOwnProperty.call(englishJson, key))
continue
const currentValue = currentJson[key]
const englishValue = englishJson[key]
// Skip non-string values
if (typeof currentValue !== 'string' || typeof englishValue !== 'string')
continue
const currentPlaceholders = extractPlaceholders(currentValue)
const englishPlaceholders = extractPlaceholders(englishValue)
if (!arraysEqual(currentPlaceholders, englishPlaceholders)) {
const missing = englishPlaceholders.filter(p => !currentPlaceholders.includes(p))
const extra = currentPlaceholders.filter(p => !englishPlaceholders.includes(p))
let message = `Placeholder mismatch in "${key}": `
const details = []
if (missing.length > 0)
details.push(`missing {{${missing.join('}}, {{')}}}`)
if (extra.length > 0)
details.push(`extra {{${extra.join('}}, {{')}}}`)
message += details.join('; ')
message += `. Expected: {{${englishPlaceholders.join('}}, {{') || 'none'}}}`
context.report({
node,
message,
})
}
}
},
}
},
}

View File

@ -0,0 +1,45 @@
const DEPENDENCY_KEYS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']
const VERSION_PREFIXES = ['^', '~']
/** @type {import('eslint').Rule.RuleModule} */
export default {
meta: {
type: 'problem',
docs: {
description: `Ensure package.json dependencies do not use version prefixes (${VERSION_PREFIXES.join(' or ')})`,
},
fixable: 'code',
},
create(context) {
const { filename } = context
if (!filename.endsWith('package.json'))
return {}
const selector = `JSONProperty:matches(${DEPENDENCY_KEYS.map(k => `[key.value="${k}"]`).join(', ')}) > JSONObjectExpression > JSONProperty`
return {
[selector](node) {
const versionNode = node.value
if (versionNode && versionNode.type === 'JSONLiteral' && typeof versionNode.value === 'string') {
const version = versionNode.value
const foundPrefix = VERSION_PREFIXES.find(prefix => version.startsWith(prefix))
if (foundPrefix) {
const packageName = node.key.value || node.key.name
const cleanVersion = version.substring(1)
const canAutoFix = /^\d+\.\d+\.\d+$/.test(cleanVersion)
context.report({
node: versionNode,
message: `Dependency "${packageName}" has version prefix "${foundPrefix}" that should be removed (found: "${version}", expected: "${cleanVersion}")`,
fix: canAutoFix
? fixer => fixer.replaceText(versionNode, `"${cleanVersion}"`)
: undefined,
})
}
}
},
}
},
}

View File

@ -131,6 +131,17 @@ export default antfu(
'dify-i18n/valid-i18n-keys': 'error',
'dify-i18n/no-extra-keys': 'error',
'dify-i18n/consistent-placeholders': 'error',
},
},
// package.json version prefix validation
{
files: ['**/package.json'],
plugins: {
'dify-i18n': difyI18n,
},
rules: {
'dify-i18n/no-version-prefix': 'error',
},
},
)

View File

@ -61,6 +61,7 @@
"account.workspaceName": "اسم مساحة العمل",
"account.workspaceNamePlaceholder": "أدخل اسم مساحة العمل",
"actionMsg.copySuccessfully": "تم النسخ بنجاح",
"actionMsg.downloadUnsuccessfully": "فشل التنزيل. يرجى المحاولة مرة أخرى لاحقًا.",
"actionMsg.generatedSuccessfully": "تم الإنشاء بنجاح",
"actionMsg.generatedUnsuccessfully": "فشل الإنشاء",
"actionMsg.modifiedSuccessfully": "تم التعديل بنجاح",
@ -91,6 +92,7 @@
"apiBasedExtension.title": "توفر ملحقات API إدارة مركزية لواجهة برمجة التطبيقات، مما يبسط التكوين لسهولة الاستخدام عبر تطبيقات Dify.",
"apiBasedExtension.type": "النوع",
"appMenus.apiAccess": "وصول API",
"appMenus.apiAccessTip": "يمكن الوصول إلى قاعدة المعرفة هذه عبر واجهة برمجة تطبيقات الخدمة",
"appMenus.logAndAnn": "السجلات والتعليقات التوضيحية",
"appMenus.logs": "السجلات",
"appMenus.overview": "المراقبة",

View File

@ -26,6 +26,7 @@
"list.action.archive": "أرشيف",
"list.action.batchAdd": "إضافة دفعة",
"list.action.delete": "حذف",
"list.action.download": "تحميل",
"list.action.enableWarning": "لا يمكن تمكين الملف المؤرشف",
"list.action.pause": "إيقاف مؤقت",
"list.action.resume": "استئناف",

View File

@ -7,6 +7,7 @@
"batchAction.cancel": "إلغاء",
"batchAction.delete": "حذف",
"batchAction.disable": "تعطيل",
"batchAction.download": "تحميل",
"batchAction.enable": "تمكين",
"batchAction.reIndex": "إعادة الفهرسة",
"batchAction.selected": "محدد",

View File

@ -236,7 +236,7 @@
"task.installSuccess": "تم تثبيت {{successLength}} من الإضافات بنجاح",
"task.installed": "مثبت",
"task.installedError": "{{errorLength}} إضافات فشل تثبيتها",
"task.installing": "تثبيت {{installingLength}} إضافات، 0 تم.",
"task.installing": "جارٍ تثبيت الإضافات.",
"task.installingWithError": "تثبيت {{installingLength}} إضافات، {{successLength}} نجاح، {{errorLength}} فشل",
"task.installingWithSuccess": "تثبيت {{installingLength}} إضافات، {{successLength}} نجاح.",
"task.runningPlugins": "تثبيت الإضافات",

View File

@ -251,10 +251,10 @@
"openingStatement.notIncludeKey": "Das Anfangsprompt enthält nicht die Variable: {{key}}. Bitte fügen Sie sie dem Anfangsprompt hinzu.",
"openingStatement.openingQuestion": "Eröffnungsfragen",
"openingStatement.openingQuestionPlaceholder": "Sie können Variablen verwenden, versuchen Sie {{variable}} einzugeben.",
"openingStatement.placeholder": "Schreiben Sie hier Ihre Eröffnungsnachricht, Sie können Variablen verwenden, versuchen Sie {{Variable}} zu tippen.",
"openingStatement.placeholder": "Schreiben Sie hier Ihre Eröffnungsnachricht, Sie können Variablen verwenden, versuchen Sie {{variable}} zu tippen.",
"openingStatement.title": "Gesprächseröffner",
"openingStatement.tooShort": "Für die Erzeugung von Eröffnungsbemerkungen für das Gespräch werden mindestens 20 Wörter des Anfangsprompts benötigt.",
"openingStatement.varTip": "Sie können Variablen verwenden, versuchen Sie {{Variable}} zu tippen",
"openingStatement.varTip": "Sie können Variablen verwenden, versuchen Sie {{variable}} zu tippen",
"openingStatement.writeOpener": "Eröffnung schreiben",
"operation.addFeature": "Funktion hinzufügen",
"operation.agree": "gefällt mir",

View File

@ -83,7 +83,7 @@
"gotoAnything.emptyState.noKnowledgeBasesFound": "Keine Wissensdatenbanken gefunden",
"gotoAnything.emptyState.noPluginsFound": "Keine Plugins gefunden",
"gotoAnything.emptyState.noWorkflowNodesFound": "Keine Workflow-Knoten gefunden",
"gotoAnything.emptyState.tryDifferentTerm": "Versuchen Sie einen anderen Suchbegriff oder entfernen Sie den {{mode}}-Filter",
"gotoAnything.emptyState.tryDifferentTerm": "Versuchen Sie einen anderen Suchbegriff",
"gotoAnything.emptyState.trySpecificSearch": "Versuchen Sie {{shortcuts}} für spezifische Suchen",
"gotoAnything.groups.apps": "Apps",
"gotoAnything.groups.commands": "Befehle",

View File

@ -65,7 +65,7 @@
"plansCommon.annotatedResponse.title": "Kontingentgrenzen für Annotationen",
"plansCommon.annotatedResponse.tooltip": "Manuelle Bearbeitung und Annotation von Antworten bieten anpassbare, hochwertige Frage-Antwort-Fähigkeiten für Apps. (Nur anwendbar in Chat-Apps)",
"plansCommon.annotationQuota": "Kontingent für Anmerkungen",
"plansCommon.annualBilling": "Jährliche Abrechnung",
"plansCommon.annualBilling": "Jährliche Abrechnung, sparen Sie {{percent}}%",
"plansCommon.apiRateLimit": "API-Datenlimit",
"plansCommon.apiRateLimitTooltip": "Die API-Datenbeschränkung gilt für alle Anfragen, die über die Dify-API gemacht werden, einschließlich Textgenerierung, Chat-Konversationen, Workflow-Ausführungen und Dokumentenverarbeitung.",
"plansCommon.apiRateLimitUnit": "{{count,number}}",
@ -91,7 +91,7 @@
"plansCommon.freeTrialTipPrefix": "Melden Sie sich an und erhalten Sie ein",
"plansCommon.freeTrialTipSuffix": "Keine Kreditkarte erforderlich",
"plansCommon.getStarted": "Loslegen",
"plansCommon.logsHistory": "Protokollverlauf",
"plansCommon.logsHistory": "{{days}} Protokollverlauf",
"plansCommon.member": "Mitglied",
"plansCommon.memberAfter": "Mitglied",
"plansCommon.messageRequest.title": "Nachrichtenguthaben",
@ -144,7 +144,7 @@
"plansCommon.unavailable": "Nicht verfügbar",
"plansCommon.unlimited": "Unbegrenzt",
"plansCommon.unlimitedApiRate": "Keine API-Ratebeschränkung",
"plansCommon.vectorSpace": "Vektorraum",
"plansCommon.vectorSpace": "{{size}} Vektorraum",
"plansCommon.vectorSpaceTooltip": "Vektorraum ist das Langzeitspeichersystem, das erforderlich ist, damit LLMs Ihre Daten verstehen können.",
"plansCommon.workflowExecution.faster": "Schnellere Arbeitsablauf-Ausführung",
"plansCommon.workflowExecution.priority": "Prioritäts-Workflow-Ausführung",

View File

@ -61,6 +61,7 @@
"account.workspaceName": "Arbeitsbereichsname",
"account.workspaceNamePlaceholder": "Arbeitsbereichnamen eingeben",
"actionMsg.copySuccessfully": "Erfolgreich kopiert",
"actionMsg.downloadUnsuccessfully": "Download fehlgeschlagen. Bitte versuchen Sie es später erneut.",
"actionMsg.generatedSuccessfully": "Erfolgreich generiert",
"actionMsg.generatedUnsuccessfully": "Generierung nicht erfolgreich",
"actionMsg.modifiedSuccessfully": "Erfolgreich geändert",
@ -91,6 +92,7 @@
"apiBasedExtension.title": "API-Erweiterungen bieten zentralisiertes API-Management und vereinfachen die Konfiguration für eine einfache Verwendung in Difys Anwendungen.",
"apiBasedExtension.type": "Typ",
"appMenus.apiAccess": "API-Zugriff",
"appMenus.apiAccessTip": "Diese Wissensdatenbank ist über die Service-API zugänglich",
"appMenus.logAndAnn": "Protokolle & Ank.",
"appMenus.logs": "Baumstämme",
"appMenus.overview": "Übersicht",
@ -172,7 +174,7 @@
"fileUploader.pasteFileLinkInvalid": "Ungültiger Dateilink",
"fileUploader.uploadDisabled": "Datei-Upload ist deaktiviert",
"fileUploader.uploadFromComputer": "Lokaler Upload",
"fileUploader.uploadFromComputerLimit": "Datei hochladen darf {{size}} nicht überschreiten",
"fileUploader.uploadFromComputerLimit": "Der Upload von {{type}} darf {{size}} nicht überschreiten",
"fileUploader.uploadFromComputerReadError": "Lesen der Datei fehlgeschlagen, bitte versuchen Sie es erneut.",
"fileUploader.uploadFromComputerUploadError": "Datei-Upload fehlgeschlagen, bitte erneut hochladen.",
"imageInput.browse": "blättern",

View File

@ -140,7 +140,7 @@
"stepTwo.preview": "Bestätigen & Vorschau",
"stepTwo.previewButton": "Umschalten zum Frage-und-Antwort-Format",
"stepTwo.previewChunk": "Vorschau Chunk",
"stepTwo.previewChunkCount": "{{Anzahl}} Geschätzte Chunks",
"stepTwo.previewChunkCount": "{{count}} Geschätzte Chunks",
"stepTwo.previewChunkTip": "Klicken Sie auf die Schaltfläche \"Preview Chunk\" auf der linken Seite, um die Vorschau zu laden",
"stepTwo.previewSwitchTipEnd": " zusätzliche Tokens verbrauchen",
"stepTwo.previewSwitchTipStart": "Die aktuelle Chunk-Vorschau ist im Textformat, ein Wechsel zur Vorschau im Frage-und-Antwort-Format wird",

View File

@ -26,6 +26,7 @@
"list.action.archive": "Archivieren",
"list.action.batchAdd": "Batch hinzufügen",
"list.action.delete": "Löschen",
"list.action.download": "Herunterladen",
"list.action.enableWarning": "Archivierte Datei kann nicht aktiviert werden",
"list.action.pause": "Pause",
"list.action.resume": "Fortsetzen",

View File

@ -3,7 +3,7 @@
"dateTimeFormat": "MM/DD/YYYY hh:mm A",
"desc": "Testen Sie die Treffereffektivität des Wissens anhand des gegebenen Abfragetextes.",
"hit.emptyTip": "Ergebnisse des Abruf-Tests werden hier angezeigt",
"hit.title": "ABRUFPARAGRAFEN",
"hit.title": "{{num}} Abgerufene Chunks",
"hitChunks": "Klicken Sie auf {{num}} untergeordnete Chunks",
"imageUploader.dropZoneTip": "Datei hierher ziehen, um sie hochzuladen",
"imageUploader.singleChunkAttachmentLimitTooltip": "Die Anzahl der Einzelblock-Anhänge darf {{limit}} nicht überschreiten",

View File

@ -16,7 +16,7 @@
"form.indexMethod": "Indexierungsmethode",
"form.indexMethodChangeToEconomyDisabledTip": "Nicht verfügbar für ein Downgrade von HQ auf ECO",
"form.indexMethodEconomy": "Ökonomisch",
"form.indexMethodEconomyTip": "Verwendet Offline-Vektor-Engines, Schlagwortindizes usw., um die Genauigkeit ohne Tokenverbrauch zu reduzieren",
"form.indexMethodEconomyTip": "Verwendet {{count}} Schlüsselwörter pro Chunk für den Abruf, ohne Tokenverbrauch, auf Kosten geringerer Genauigkeit.",
"form.indexMethodHighQuality": "Hohe Qualität",
"form.indexMethodHighQualityTip": "Den Embedding-Modell zur Verarbeitung aufrufen, um bei Benutzeranfragen eine höhere Genauigkeit zu bieten.",
"form.me": "(Sie)",

View File

@ -7,6 +7,7 @@
"batchAction.cancel": "Abbrechen",
"batchAction.delete": "Löschen",
"batchAction.disable": "Abschalten",
"batchAction.download": "Herunterladen",
"batchAction.enable": "Ermöglichen",
"batchAction.reIndex": "Neu indexieren",
"batchAction.selected": "Ausgewählt",

View File

@ -81,7 +81,7 @@
"debugInfo.title": "Debuggen",
"debugInfo.viewDocs": "Dokumente anzeigen",
"deprecated": "Abgelehnt",
"detailPanel.actionNum": "{{num}} {{Aktion}} IINKLUSIVE",
"detailPanel.actionNum": "{{num}} {{action}} IINKLUSIVE",
"detailPanel.categoryTip.debugging": "Debuggen-Plugin",
"detailPanel.categoryTip.github": "Installiert von Github",
"detailPanel.categoryTip.local": "Lokales Plugin",
@ -116,7 +116,7 @@
"detailPanel.operation.update": "Aktualisieren",
"detailPanel.operation.viewDetail": "Im Detail sehen",
"detailPanel.serviceOk": "Service in Ordnung",
"detailPanel.strategyNum": "{{num}} {{Strategie}} IINKLUSIVE",
"detailPanel.strategyNum": "{{num}} {{strategy}} IINKLUSIVE",
"detailPanel.switchVersion": "Version wechseln",
"detailPanel.toolSelector.auto": "Auto",
"detailPanel.toolSelector.descriptionLabel": "Beschreibung des Werkzeugs",
@ -236,7 +236,7 @@
"task.installSuccess": "{{successLength}} plugins installed successfully",
"task.installed": "Installed",
"task.installedError": "{{errorLength}} Plugins konnten nicht installiert werden",
"task.installing": "Installation von {{installingLength}} Plugins, 0 erledigt.",
"task.installing": "Plugins werden installiert.",
"task.installingWithError": "Installation von {{installingLength}} Plugins, {{successLength}} erfolgreich, {{errorLength}} fehlgeschlagen",
"task.installingWithSuccess": "Installation von {{installingLength}} Plugins, {{successLength}} erfolgreich.",
"task.runningPlugins": "Installing Plugins",

View File

@ -99,7 +99,7 @@
"createTool.viewSchemaSpec": "Die OpenAPI-Swagger-Spezifikation anzeigen",
"customToolTip": "Erfahren Sie mehr über benutzerdefinierte Dify-Tools",
"howToGet": "Wie erhält man",
"includeToolNum": "{{num}} Werkzeuge inkludiert",
"includeToolNum": "{{num}} {{action}} inkludiert",
"mcp.authorize": "Autorisieren",
"mcp.authorizeTip": "Nach der Autorisierung werden Tools hier angezeigt.",
"mcp.authorizing": "Wird autorisiert...",

View File

@ -363,7 +363,7 @@
"nodes.agent.strategyNotFoundDescAndSwitchVersion": "Die installierte Plugin-Version bietet diese Strategie nicht. Klicken Sie hier, um die Version zu wechseln.",
"nodes.agent.strategyNotInstallTooltip": "{{strategy}} ist nicht installiert",
"nodes.agent.strategyNotSet": "Agentische Strategie nicht festgelegt",
"nodes.agent.toolNotAuthorizedTooltip": "{{Werkzeug}} Nicht autorisiert",
"nodes.agent.toolNotAuthorizedTooltip": "{{tool}} Nicht autorisiert",
"nodes.agent.toolNotInstallTooltip": "{{tool}} ist nicht installiert",
"nodes.agent.toolbox": "Werkzeugkasten",
"nodes.agent.tools": "Werkzeuge",
@ -549,8 +549,8 @@
"nodes.iteration.deleteDesc": "Das Löschen des Iterationsknotens löscht alle untergeordneten Knoten",
"nodes.iteration.deleteTitle": "Iterationsknoten löschen?",
"nodes.iteration.errorResponseMethod": "Methode der Fehlerantwort",
"nodes.iteration.error_one": "{{Anzahl}} Fehler",
"nodes.iteration.error_other": "{{Anzahl}} Irrtümer",
"nodes.iteration.error_one": "{{count}} Fehler",
"nodes.iteration.error_other": "{{count}} Fehler",
"nodes.iteration.flattenOutput": "Ausgabe abflachen",
"nodes.iteration.flattenOutputDesc": "Wenn aktiviert, werden alle Iterationsergebnisse, die Arrays sind, in ein einzelnes Array zusammengeführt. Wenn deaktiviert, behalten die Ergebnisse eine verschachtelte Array-Struktur bei.",
"nodes.iteration.input": "Eingabe",

View File

@ -83,7 +83,7 @@
"gotoAnything.emptyState.noKnowledgeBasesFound": "No se han encontrado bases de conocimiento",
"gotoAnything.emptyState.noPluginsFound": "No se encontraron complementos",
"gotoAnything.emptyState.noWorkflowNodesFound": "No se encontraron nodos de flujo de trabajo",
"gotoAnything.emptyState.tryDifferentTerm": "Intenta un término de búsqueda diferente o elimina el filtro {{mode}}",
"gotoAnything.emptyState.tryDifferentTerm": "Intenta un término de búsqueda diferente",
"gotoAnything.emptyState.trySpecificSearch": "Prueba {{shortcuts}} para búsquedas específicas",
"gotoAnything.groups.apps": "Aplicaciones",
"gotoAnything.groups.commands": "Comandos",
@ -161,8 +161,8 @@
"newApp.dropDSLToCreateApp": "Suelta el archivo DSL aquí para crear la aplicación",
"newApp.forAdvanced": "PARA USUARIOS AVANZADOS",
"newApp.forBeginners": "Tipos de aplicación más básicos",
"newApp.foundResult": "{{conteo}} Resultado",
"newApp.foundResults": "{{conteo}} Resultados",
"newApp.foundResult": "{{count}} Resultado",
"newApp.foundResults": "{{count}} Resultados",
"newApp.hideTemplates": "Volver a la selección de modo",
"newApp.import": "Importación",
"newApp.learnMore": "Aprende más",

View File

@ -65,7 +65,7 @@
"plansCommon.annotatedResponse.title": "Límites de Cuota de Anotación",
"plansCommon.annotatedResponse.tooltip": "Edición manual y anotación de respuestas proporciona habilidades de respuesta a preguntas personalizadas y de alta calidad para aplicaciones (aplicable solo en aplicaciones de chat).",
"plansCommon.annotationQuota": "Cuota de Anotación",
"plansCommon.annualBilling": "Facturación Anual",
"plansCommon.annualBilling": "Facturación anual, ahorra {{percent}}%",
"plansCommon.apiRateLimit": "Límite de tasa de API",
"plansCommon.apiRateLimitTooltip": "El límite de tasa de la API se aplica a todas las solicitudes realizadas a través de la API de Dify, incluidos la generación de texto, las conversaciones de chat, las ejecuciones de flujo de trabajo y el procesamiento de documentos.",
"plansCommon.apiRateLimitUnit": "{{count, número}}",
@ -91,7 +91,7 @@
"plansCommon.freeTrialTipPrefix": "Regístrate y obtén un",
"plansCommon.freeTrialTipSuffix": "No se requiere tarjeta de crédito",
"plansCommon.getStarted": "Comenzar",
"plansCommon.logsHistory": "Historial de Registros",
"plansCommon.logsHistory": "{{days}} Historial de registros",
"plansCommon.member": "Miembro",
"plansCommon.memberAfter": "Miembro",
"plansCommon.messageRequest.title": "Créditos de Mensajes",
@ -144,7 +144,7 @@
"plansCommon.unavailable": "No disponible",
"plansCommon.unlimited": "Ilimitado",
"plansCommon.unlimitedApiRate": "Sin límite de tasa de API",
"plansCommon.vectorSpace": "Espacio Vectorial",
"plansCommon.vectorSpace": "{{size}} Espacio vectorial",
"plansCommon.vectorSpaceTooltip": "El Espacio Vectorial es el sistema de memoria a largo plazo necesario para que los LLMs comprendan tus datos.",
"plansCommon.workflowExecution.faster": "Ejecución de flujo de trabajo más rápida",
"plansCommon.workflowExecution.priority": "Ejecución de flujo de trabajo prioritaria",

View File

@ -61,6 +61,7 @@
"account.workspaceName": "Nombre del espacio de trabajo",
"account.workspaceNamePlaceholder": "Ingrese el nombre del espacio de trabajo",
"actionMsg.copySuccessfully": "Copiado exitosamente",
"actionMsg.downloadUnsuccessfully": "Descarga fallida. Por favor, inténtelo de nuevo más tarde.",
"actionMsg.generatedSuccessfully": "Generado exitosamente",
"actionMsg.generatedUnsuccessfully": "Generación no exitosa",
"actionMsg.modifiedSuccessfully": "Modificado exitosamente",
@ -91,6 +92,7 @@
"apiBasedExtension.title": "Las extensiones basadas en API proporcionan una gestión centralizada de API, simplificando la configuración para su fácil uso en las aplicaciones de Dify.",
"apiBasedExtension.type": "Tipo",
"appMenus.apiAccess": "Acceso API",
"appMenus.apiAccessTip": "Esta base de conocimiento es accesible a través de la API de servicio",
"appMenus.logAndAnn": "Registros y Anuncios",
"appMenus.logs": "Registros",
"appMenus.overview": "Monitoreo",
@ -172,7 +174,7 @@
"fileUploader.pasteFileLinkInvalid": "Enlace de archivo no válido",
"fileUploader.uploadDisabled": "La carga de archivos está deshabilitada",
"fileUploader.uploadFromComputer": "Carga local",
"fileUploader.uploadFromComputerLimit": "El archivo de carga no puede exceder {{size}}",
"fileUploader.uploadFromComputerLimit": "La carga de {{type}} no puede exceder {{size}}",
"fileUploader.uploadFromComputerReadError": "Error en la lectura del archivo, inténtelo de nuevo.",
"fileUploader.uploadFromComputerUploadError": "Error en la carga del archivo, vuelva a cargarlo.",
"imageInput.browse": "navegar",

View File

@ -140,7 +140,7 @@
"stepTwo.preview": "Confirmar y vista previa",
"stepTwo.previewButton": "Cambiar a formato de pregunta y respuesta",
"stepTwo.previewChunk": "Fragmento de vista previa",
"stepTwo.previewChunkCount": "{{conteo}} Fragmentos estimados",
"stepTwo.previewChunkCount": "{{count}} Fragmentos estimados",
"stepTwo.previewChunkTip": "Haga clic en el botón 'Vista previa de fragmento' a la izquierda para cargar la vista previa",
"stepTwo.previewSwitchTipEnd": " consumirá tokens adicionales",
"stepTwo.previewSwitchTipStart": "La vista previa actual del fragmento está en formato de texto, cambiar a una vista previa en formato de pregunta y respuesta",

View File

@ -26,6 +26,7 @@
"list.action.archive": "Archivar",
"list.action.batchAdd": "Agregar en lotes",
"list.action.delete": "Eliminar",
"list.action.download": "Descargar",
"list.action.enableWarning": "El archivo archivado no puede habilitarse",
"list.action.pause": "Pausa",
"list.action.resume": "Reanudar",

View File

@ -3,7 +3,7 @@
"dateTimeFormat": "MM/DD/YYYY hh:mm A",
"desc": "Prueba del efecto de impacto del conocimiento basado en el texto de consulta proporcionado.",
"hit.emptyTip": "Los resultados de la prueba de recuperación se mostrarán aquí",
"hit.title": "PÁRRAFOS DE RECUPERACIÓN",
"hit.title": "{{num}} Párrafos recuperados",
"hitChunks": "Golpea {{num}} fragmentos secundarios",
"imageUploader.dropZoneTip": "Arrastra el archivo aquí para subirlo",
"imageUploader.singleChunkAttachmentLimitTooltip": "El número de archivos adjuntos de un solo bloque no puede superar {{limit}}",

View File

@ -16,7 +16,7 @@
"form.indexMethod": "Método de indexación",
"form.indexMethodChangeToEconomyDisabledTip": "No disponible para degradar de HQ a ECO",
"form.indexMethodEconomy": "Económico",
"form.indexMethodEconomyTip": "Utiliza motores de vectores sin conexión, índices de palabras clave, etc. para reducir la precisión sin gastar tokens.",
"form.indexMethodEconomyTip": "Utiliza {{count}} palabras clave por fragmento para la recuperación, sin consumir tokens a costa de una menor precisión.",
"form.indexMethodHighQuality": "Alta calidad",
"form.indexMethodHighQualityTip": "Llama al modelo de incrustación para procesar y proporcionar una mayor precisión cuando los usuarios realizan consultas.",
"form.me": "(Tú)",

View File

@ -7,6 +7,7 @@
"batchAction.cancel": "Cancelar",
"batchAction.delete": "Borrar",
"batchAction.disable": "Inutilizar",
"batchAction.download": "Descargar",
"batchAction.enable": "Habilitar",
"batchAction.reIndex": "Reindexar",
"batchAction.selected": "Seleccionado",

View File

@ -81,7 +81,7 @@
"debugInfo.title": "Depuración",
"debugInfo.viewDocs": "Ver documentos",
"deprecated": "Obsoleto",
"detailPanel.actionNum": "{{num}} {{acción}} INCLUIDO",
"detailPanel.actionNum": "{{num}} {{action}} INCLUIDO",
"detailPanel.categoryTip.debugging": "Complemento de depuración",
"detailPanel.categoryTip.github": "Instalado desde Github",
"detailPanel.categoryTip.local": "Plugin Local",
@ -96,7 +96,7 @@
"detailPanel.deprecation.reason.noMaintainer": "sin mantenedor",
"detailPanel.deprecation.reason.ownershipTransferred": "propiedad transferida",
"detailPanel.disabled": "Deshabilitado",
"detailPanel.endpointDeleteContent": "¿Te gustaría eliminar {{nombre}}?",
"detailPanel.endpointDeleteContent": "¿Te gustaría eliminar {{name}}?",
"detailPanel.endpointDeleteTip": "Eliminar punto de conexión",
"detailPanel.endpointDisableContent": "¿Te gustaría desactivar {{name}}?",
"detailPanel.endpointDisableTip": "Deshabilitar punto de conexión",
@ -116,7 +116,7 @@
"detailPanel.operation.update": "Actualizar",
"detailPanel.operation.viewDetail": "Ver Detalle",
"detailPanel.serviceOk": "Servicio OK",
"detailPanel.strategyNum": "{{num}} {{estrategia}} INCLUIDO",
"detailPanel.strategyNum": "{{num}} {{strategy}} INCLUIDO",
"detailPanel.switchVersion": "Versión del interruptor",
"detailPanel.toolSelector.auto": "Auto",
"detailPanel.toolSelector.descriptionLabel": "Descripción de la herramienta",
@ -236,7 +236,7 @@
"task.installSuccess": "{{successLength}} plugins installed successfully",
"task.installed": "Installed",
"task.installedError": "Los complementos {{errorLength}} no se pudieron instalar",
"task.installing": "Instalando plugins {{installingLength}}, 0 hecho.",
"task.installing": "Instalando plugins.",
"task.installingWithError": "Instalando plugins {{installingLength}}, {{successLength}} éxito, {{errorLength}} fallido",
"task.installingWithSuccess": "Instalando plugins {{installingLength}}, {{successLength}} éxito.",
"task.runningPlugins": "Installing Plugins",

View File

@ -99,7 +99,7 @@
"createTool.viewSchemaSpec": "Ver la Especificación OpenAPI-Swagger",
"customToolTip": "Aprende más sobre las herramientas personalizadas de Dify",
"howToGet": "Cómo obtener",
"includeToolNum": "{{num}} herramientas incluidas",
"includeToolNum": "{{num}} {{action}} incluidas",
"mcp.authorize": "Autorizar",
"mcp.authorizeTip": "Tras la autorización, las herramientas se mostrarán aquí.",
"mcp.authorizing": "Autorizando...",

View File

@ -303,10 +303,10 @@
"errorMsg.fields.visionVariable": "Variable de visión",
"errorMsg.invalidJson": "{{field}} no es un JSON válido",
"errorMsg.invalidVariable": "Variable no válida",
"errorMsg.noValidTool": "{{campo}} no se ha seleccionado ninguna herramienta válida",
"errorMsg.noValidTool": "{{field}} no se ha seleccionado ninguna herramienta válida",
"errorMsg.rerankModelRequired": "Antes de activar el modelo de reclasificación, confirme que el modelo se ha configurado correctamente en la configuración.",
"errorMsg.startNodeRequired": "Por favor, agregue primero un nodo de inicio antes de {{operation}}",
"errorMsg.toolParameterRequired": "{{campo}}: el parámetro [{{param}}] es obligatorio",
"errorMsg.toolParameterRequired": "{{field}}: el parámetro [{{param}}] es obligatorio",
"globalVar.description": "Las variables del sistema son variables globales que cualquier nodo puede usar sin conexiones cuando el tipo es correcto, como el ID del usuario final y el ID del flujo de trabajo.",
"globalVar.fieldsDescription.appId": "ID de la aplicación",
"globalVar.fieldsDescription.conversationId": "ID de la conversación",
@ -361,10 +361,10 @@
"nodes.agent.strategy.tooltip": "Diferentes estrategias agentic determinan cómo el sistema planifica y ejecuta las llamadas a herramientas de varios pasos",
"nodes.agent.strategyNotFoundDesc": "La versión del plugin instalado no proporciona esta estrategia.",
"nodes.agent.strategyNotFoundDescAndSwitchVersion": "La versión del plugin instalado no proporciona esta estrategia. Haga clic para cambiar de versión.",
"nodes.agent.strategyNotInstallTooltip": "{{estrategia}} no está instalado",
"nodes.agent.strategyNotInstallTooltip": "{{strategy}} no está instalado",
"nodes.agent.strategyNotSet": "Estrategia agentica No establecida",
"nodes.agent.toolNotAuthorizedTooltip": "{{herramienta}} No autorizado",
"nodes.agent.toolNotInstallTooltip": "{{herramienta}} no está instalada",
"nodes.agent.toolNotAuthorizedTooltip": "{{tool}} No autorizado",
"nodes.agent.toolNotInstallTooltip": "{{tool}} no está instalada",
"nodes.agent.toolbox": "caja de herramientas",
"nodes.agent.tools": "Herramientas",
"nodes.agent.unsupportedStrategy": "Estrategia no respaldada",
@ -438,7 +438,7 @@
"nodes.common.retry.retries": "{{num}} Reintentos",
"nodes.common.retry.retry": "Reintentar",
"nodes.common.retry.retryFailed": "Error en el reintento",
"nodes.common.retry.retryFailedTimes": "{{veces}} reintentos fallidos",
"nodes.common.retry.retryFailedTimes": "{{times}} reintentos fallidos",
"nodes.common.retry.retryInterval": "Intervalo de reintento",
"nodes.common.retry.retryOnFailure": "Volver a intentarlo en caso de error",
"nodes.common.retry.retrySuccessful": "Volver a intentarlo correctamente",
@ -453,7 +453,7 @@
"nodes.docExtractor.inputVar": "Variable de entrada",
"nodes.docExtractor.learnMore": "Aprende más",
"nodes.docExtractor.outputVars.text": "Texto extraído",
"nodes.docExtractor.supportFileTypes": "Tipos de archivos de soporte: {{tipos}}.",
"nodes.docExtractor.supportFileTypes": "Tipos de archivos de soporte: {{types}}.",
"nodes.end.output.type": "tipo de salida",
"nodes.end.output.variable": "variable de salida",
"nodes.end.outputs": "Salidas",
@ -549,8 +549,8 @@
"nodes.iteration.deleteDesc": "Eliminar el nodo de iteración eliminará todos los nodos secundarios",
"nodes.iteration.deleteTitle": "¿Eliminar nodo de iteración?",
"nodes.iteration.errorResponseMethod": "Método de respuesta a errores",
"nodes.iteration.error_one": "{{conteo}} Error",
"nodes.iteration.error_other": "{{conteo}} Errores",
"nodes.iteration.error_one": "{{count}} Error",
"nodes.iteration.error_other": "{{count}} Errores",
"nodes.iteration.flattenOutput": "Aplanar salida",
"nodes.iteration.flattenOutputDesc": "Cuando está habilitado, si todas las salidas de la iteración son arrays, se aplanarán en un solo array. Cuando está deshabilitado, las salidas mantendrán una estructura de array anidada.",
"nodes.iteration.input": "Entrada",

View File

@ -83,7 +83,7 @@
"gotoAnything.emptyState.noKnowledgeBasesFound": "هیچ پایگاه دانش یافت نشد",
"gotoAnything.emptyState.noPluginsFound": "هیچ افزونه ای یافت نشد",
"gotoAnything.emptyState.noWorkflowNodesFound": "هیچ گره گردش کاری یافت نشد",
"gotoAnything.emptyState.tryDifferentTerm": "یک عبارت جستجوی متفاوت را امتحان کنید یا فیلتر {{mode}} را حذف کنید",
"gotoAnything.emptyState.tryDifferentTerm": "یک عبارت جستجوی متفاوت را امتحان کنید",
"gotoAnything.emptyState.trySpecificSearch": "{{shortcuts}} را برای جستجوهای خاص امتحان کنید",
"gotoAnything.groups.apps": "برنامه‌ها",
"gotoAnything.groups.commands": "دستورات",

View File

@ -65,7 +65,7 @@
"plansCommon.annotatedResponse.title": "محدودیت‌های سهمیه حاشیه‌نویسی",
"plansCommon.annotatedResponse.tooltip": "ویرایش دستی و حاشیه‌نویسی پاسخ‌ها، قابلیت‌های پرسش و پاسخ با کیفیت بالا و قابل تنظیم برای اپلیکیشن‌ها را فراهم می‌کند. (فقط در اپلیکیشن‌های چت اعمال می‌شود)",
"plansCommon.annotationQuota": "سهمیه حاشیه‌نویسی",
"plansCommon.annualBilling": "صورتحساب سالانه",
"plansCommon.annualBilling": "صورتحساب سالانه، صرفه‌جویی {{percent}}%",
"plansCommon.apiRateLimit": "محدودیت نرخ API",
"plansCommon.apiRateLimitTooltip": "محدودیت نرخ API برای همه درخواست‌های انجام شده از طریق API Dify اعمال می‌شود، از جمله تولید متن، محاوره‌های چت، اجرای گردش‌های کار و پردازش اسناد.",
"plansCommon.apiRateLimitUnit": "{{count,number}}",
@ -91,7 +91,7 @@
"plansCommon.freeTrialTipPrefix": "ثبت‌نام کنید و یک",
"plansCommon.freeTrialTipSuffix": "نیاز به کارت اعتباری نیست",
"plansCommon.getStarted": "شروع کنید",
"plansCommon.logsHistory": "تاریخچه گزارشات",
"plansCommon.logsHistory": "{{days}} تاریخچه گزارشات",
"plansCommon.member": "عضو",
"plansCommon.memberAfter": "عضو",
"plansCommon.messageRequest.title": "اعتبارات پیام",
@ -144,7 +144,7 @@
"plansCommon.unavailable": "غیرقابل دسترس",
"plansCommon.unlimited": "نامحدود",
"plansCommon.unlimitedApiRate": "هیچ محدودیتی برای نرخ API وجود ندارد.",
"plansCommon.vectorSpace": "فضای وکتور",
"plansCommon.vectorSpace": "{{size}} فضای وکتور",
"plansCommon.vectorSpaceTooltip": "فضای وکتور سیستم حافظه بلند مدت است که برای درک داده‌های شما توسط LLMها مورد نیاز است.",
"plansCommon.workflowExecution.faster": "اجرای سریع‌تر جریان کاری",
"plansCommon.workflowExecution.priority": "اجرای جریان کاری اولویت‌دار",

View File

@ -61,6 +61,7 @@
"account.workspaceName": "نام فضای کاری",
"account.workspaceNamePlaceholder": "نام فضای کاری را وارد کنید",
"actionMsg.copySuccessfully": "با موفقیت کپی شد",
"actionMsg.downloadUnsuccessfully": "دانلود ناموفق بود. لطفاً بعداً دوباره امتحان کنید.",
"actionMsg.generatedSuccessfully": "با موفقیت تولید شد",
"actionMsg.generatedUnsuccessfully": "تولید ناموفق بود",
"actionMsg.modifiedSuccessfully": "با موفقیت تغییر یافت",
@ -91,6 +92,7 @@
"apiBasedExtension.title": "افزونه‌های مبتنی بر API مدیریت متمرکز API را فراهم می‌کنند و پیکربندی را برای استفاده آسان در برنامه‌های Dify ساده می‌کنند.",
"apiBasedExtension.type": "نوع",
"appMenus.apiAccess": "دسترسی API",
"appMenus.apiAccessTip": "این پایگاه دانش از طریق API سرویس قابل دسترسی است",
"appMenus.logAndAnn": "گزارش‌ها و اعلانات",
"appMenus.logs": "گزارش‌ها",
"appMenus.overview": "نظارت",
@ -108,7 +110,7 @@
"chat.conversationName": "نام مکالمه",
"chat.conversationNameCanNotEmpty": "نام مکالمه الزامی است",
"chat.conversationNamePlaceholder": "لطفاً نام مکالمه را وارد کنید",
"chat.inputPlaceholder": "با ربات صحبت کنید",
"chat.inputPlaceholder": "با {{botName}} صحبت کنید",
"chat.renameConversation": "تغییر نام مکالمه",
"chat.resend": "دوباره ارسال کنید",
"chat.thinking": "تفکر...",
@ -172,7 +174,7 @@
"fileUploader.pasteFileLinkInvalid": "پیوند فایل نامعتبر",
"fileUploader.uploadDisabled": "بارگذاری فایل غیرفعال است",
"fileUploader.uploadFromComputer": "آپلود محلی",
"fileUploader.uploadFromComputerLimit": "آپلود فایل نمی تواند از {{size}} تجاوز کند",
"fileUploader.uploadFromComputerLimit": "آپلود {{type}} نمی تواند از {{size}} تجاوز کند",
"fileUploader.uploadFromComputerReadError": "خواندن فایل انجام نشد، لطفا دوباره امتحان کنید.",
"fileUploader.uploadFromComputerUploadError": "آپلود فایل انجام نشد، لطفا دوباره آپلود کنید.",
"imageInput.browse": "مرورگر",

View File

@ -140,7 +140,7 @@
"stepTwo.preview": "تأیید و پیشنمایش",
"stepTwo.previewButton": "تغییر به قالب پرسش و پاسخ",
"stepTwo.previewChunk": "پیش نمایش تکه",
"stepTwo.previewChunkCount": "{{تعداد}} تکه های تخمینی",
"stepTwo.previewChunkCount": "{{count}} تکه های تخمینی",
"stepTwo.previewChunkTip": "روی دکمه \"پیش نمایش قطعه\" در سمت چپ کلیک کنید تا پیش نمایش بارگیری شود",
"stepTwo.previewSwitchTipEnd": " توکنهای اضافی مصرف خواهد کرد",
"stepTwo.previewSwitchTipStart": "پیشنمایش بخش فعلی در قالب متن است، تغییر به پیشنمایش قالب پرسش و پاسخ",

View File

@ -26,6 +26,7 @@
"list.action.archive": "بایگانی",
"list.action.batchAdd": "افزودن گروهی",
"list.action.delete": "حذف",
"list.action.download": "دانلود",
"list.action.enableWarning": "فایل بایگانی شده نمی‌تواند فعال شود",
"list.action.pause": "مکث",
"list.action.resume": "ادامه",

View File

@ -3,7 +3,7 @@
"dateTimeFormat": "MM/DD/YYYY hh:mm A",
"desc": "آزمون اثرگذاری دانش بر اساس متن پرسش داده شده.",
"hit.emptyTip": "نتایج آزمون بازیابی اینجا نمایش داده می‌شوند",
"hit.title": "پاراگراف‌های بازیابی",
"hit.title": "{{num}} پاراگراف‌های بازیابی",
"hitChunks": "{{num}} را بزنید تکه های فرزند",
"imageUploader.dropZoneTip": "فایل را اینجا بکشید تا بارگذاری شود",
"imageUploader.singleChunkAttachmentLimitTooltip": "تعداد پیوست‌های تک قطعه‌ای نمی‌تواند از {{limit}} بیشتر باشد",

View File

@ -16,7 +16,7 @@
"form.indexMethod": "روش نمایه‌سازی",
"form.indexMethodChangeToEconomyDisabledTip": "برای تنزل رتبه از HQ به ECO در دسترس نیست",
"form.indexMethodEconomy": "اقتصادی",
"form.indexMethodEconomyTip": "استفاده از موتورهای برداری آفلاین، شاخص‌های کلمات کلیدی و غیره برای کاهش دقت بدون صرف توکن‌ها",
"form.indexMethodEconomyTip": "استفاده از {{count}} کلمه کلیدی برای هر تکه در بازیابی، بدون مصرف توکن‌ها با کاهش دقت.",
"form.indexMethodHighQuality": "کیفیت بالا",
"form.indexMethodHighQualityTip": "مدل تعبیه را برای پردازش فراخوانی کنید تا دقت بالاتری هنگام جستجوی کاربران فراهم شود.",
"form.me": "(شما)",

View File

@ -7,6 +7,7 @@
"batchAction.cancel": "لغو",
"batchAction.delete": "حذف",
"batchAction.disable": "غیر فعال کردن",
"batchAction.download": "دانلود",
"batchAction.enable": "فعال",
"batchAction.reIndex": "بازفهرست‌گذاری",
"batchAction.selected": "انتخاب",
@ -147,7 +148,7 @@
"parentMode.paragraph": "پاراگراف",
"partialEnabled_one": "مجموعاً {{count}} سند، {{num}} موجود",
"partialEnabled_other": "مجموع {{count}} سند، {{num}} موجود",
"preprocessDocument": "{{عدد}} اسناد پیش پردازش",
"preprocessDocument": "{{num}} اسناد پیش پردازش",
"rerankSettings": "تنظیمات دوباره رتبه‌بندی",
"retrieval.change": "تغییر",
"retrieval.changeRetrievalMethod": "تغییر روش بازیابی",

Some files were not shown because too many files have changed in this diff Show More