mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 11:42:29 +08:00
feat: add i18n support for plugin installation and empty states
This commit is contained in:
parent
a0a62db6ad
commit
cd2860deb4
|
@ -9,8 +9,10 @@ import { Group } from '@/app/components/base/icons/src/vender/other'
|
||||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||||
import Line from '../../marketplace/empty/line'
|
import Line from '../../marketplace/empty/line'
|
||||||
import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const Empty = () => {
|
const Empty = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||||
const [selectedAction, setSelectedAction] = useState<string | null>(null)
|
const [selectedAction, setSelectedAction] = useState<string | null>(null)
|
||||||
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||||
|
@ -30,9 +32,9 @@ const Empty = () => {
|
||||||
|
|
||||||
const text = useMemo(() => {
|
const text = useMemo(() => {
|
||||||
if (pluginList?.plugins.length === 0)
|
if (pluginList?.plugins.length === 0)
|
||||||
return 'No plugins installed'
|
return t('plugin.list.noInstalled')
|
||||||
if (filters.categories.length > 0 || filters.tags.length > 0 || filters.searchQuery)
|
if (filters.categories.length > 0 || filters.tags.length > 0 || filters.searchQuery)
|
||||||
return 'No plugins found'
|
return t('plugin.list.notFound')
|
||||||
}, [pluginList, filters])
|
}, [pluginList, filters])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -70,11 +72,11 @@ const Empty = () => {
|
||||||
{[
|
{[
|
||||||
...(
|
...(
|
||||||
(enable_marketplace || true)
|
(enable_marketplace || true)
|
||||||
? [{ icon: MagicBox, text: 'Marketplace', action: 'marketplace' }]
|
? [{ icon: MagicBox, text: t('plugin.list.source.marketplace'), action: 'marketplace' }]
|
||||||
: []
|
: []
|
||||||
),
|
),
|
||||||
{ icon: Github, text: 'GitHub', action: 'github' },
|
{ icon: Github, text: t('plugin.list.source.github'), action: 'github' },
|
||||||
{ icon: FileZip, text: 'Local Package File', action: 'local' },
|
{ icon: FileZip, text: t('plugin.list.source.local'), action: 'local' },
|
||||||
].map(({ icon: Icon, text, action }) => (
|
].map(({ icon: Icon, text, action }) => (
|
||||||
<div
|
<div
|
||||||
key={action}
|
key={action}
|
||||||
|
@ -90,7 +92,7 @@ const Empty = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon className="w-4 h-4 text-text-tertiary" />
|
<Icon className="w-4 h-4 text-text-tertiary" />
|
||||||
<span className='text-text-secondary system-md-regular'>{`Install from ${text}`}</span>
|
<span className='text-text-secondary system-md-regular'>{text}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
} from '@/app/components/base/portal-to-follow-elem'
|
} from '@/app/components/base/portal-to-follow-elem'
|
||||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSwitchToMarketplaceTab: () => void
|
onSwitchToMarketplaceTab: () => void
|
||||||
|
@ -23,6 +24,7 @@ type Props = {
|
||||||
const InstallPluginDropdown = ({
|
const InstallPluginDropdown = ({
|
||||||
onSwitchToMarketplaceTab,
|
onSwitchToMarketplaceTab,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
||||||
const [selectedAction, setSelectedAction] = useState<string | null>(null)
|
const [selectedAction, setSelectedAction] = useState<string | null>(null)
|
||||||
|
@ -65,14 +67,14 @@ const InstallPluginDropdown = ({
|
||||||
className={cn('w-full h-full p-2 text-components-button-secondary-text', isMenuOpen && 'bg-state-base-hover')}
|
className={cn('w-full h-full p-2 text-components-button-secondary-text', isMenuOpen && 'bg-state-base-hover')}
|
||||||
>
|
>
|
||||||
<RiAddLine className='w-4 h-4' />
|
<RiAddLine className='w-4 h-4' />
|
||||||
<span className='pl-1'>Install plugin</span>
|
<span className='pl-1'>{t('plugin.installPlugin')}</span>
|
||||||
<RiArrowDownSLine className='w-4 h-4 ml-1' />
|
<RiArrowDownSLine className='w-4 h-4 ml-1' />
|
||||||
</Button>
|
</Button>
|
||||||
</PortalToFollowElemTrigger>
|
</PortalToFollowElemTrigger>
|
||||||
<PortalToFollowElemContent className='z-[1002]'>
|
<PortalToFollowElemContent className='z-[1002]'>
|
||||||
<div className='flex flex-col p-1 pb-2 items-start w-[200px] bg-components-panel-bg-blur border border-components-panel-border rounded-xl shadows-shadow-lg'>
|
<div className='flex flex-col p-1 pb-2 items-start w-[200px] bg-components-panel-bg-blur border border-components-panel-border rounded-xl shadows-shadow-lg'>
|
||||||
<span className='flex pt-1 pb-0.5 pl-2 pr-3 items-start self-stretch text-text-tertiary system-xs-medium-uppercase'>
|
<span className='flex pt-1 pb-0.5 pl-2 pr-3 items-start self-stretch text-text-tertiary system-xs-medium-uppercase'>
|
||||||
Install From
|
{t('plugin.installFrom')}
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
type='file'
|
type='file'
|
||||||
|
@ -85,11 +87,11 @@ const InstallPluginDropdown = ({
|
||||||
{[
|
{[
|
||||||
...(
|
...(
|
||||||
(enable_marketplace || true)
|
(enable_marketplace || true)
|
||||||
? [{ icon: MagicBox, text: 'Marketplace', action: 'marketplace' }]
|
? [{ icon: MagicBox, text: t('plugin.source.marketplace'), action: 'marketplace' }]
|
||||||
: []
|
: []
|
||||||
),
|
),
|
||||||
{ icon: Github, text: 'GitHub', action: 'github' },
|
{ icon: Github, text: t('plugin.source.github'), action: 'github' },
|
||||||
{ icon: FileZip, text: 'Local Package File', action: 'local' },
|
{ icon: FileZip, text: t('plugin.source.local'), action: 'local' },
|
||||||
].map(({ icon: Icon, text, action }) => (
|
].map(({ icon: Icon, text, action }) => (
|
||||||
<div
|
<div
|
||||||
key={action}
|
key={action}
|
||||||
|
|
|
@ -16,6 +16,22 @@ const translation = {
|
||||||
fromMarketplace: 'From Marketplace',
|
fromMarketplace: 'From Marketplace',
|
||||||
endpointsEnabled: '{{num}} sets of endpoints enabled',
|
endpointsEnabled: '{{num}} sets of endpoints enabled',
|
||||||
searchTools: 'Search tools...',
|
searchTools: 'Search tools...',
|
||||||
|
installPlugin: 'Install plugin',
|
||||||
|
installFrom: 'INSTALL FROM',
|
||||||
|
list: {
|
||||||
|
noInstalled: 'No plugins installed',
|
||||||
|
notFound: 'No plugins found',
|
||||||
|
source: {
|
||||||
|
marketplace: 'Install from Marketplace',
|
||||||
|
github: 'Install from GitHub',
|
||||||
|
local: 'Install from Local Package File',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
marketplace: 'Marketplace',
|
||||||
|
github: 'GitHub',
|
||||||
|
local: 'Local Package File',
|
||||||
|
},
|
||||||
detailPanel: {
|
detailPanel: {
|
||||||
categoryTip: {
|
categoryTip: {
|
||||||
marketplace: 'Installed from Marketplace',
|
marketplace: 'Installed from Marketplace',
|
||||||
|
|
|
@ -16,6 +16,22 @@ const translation = {
|
||||||
fromMarketplace: '来自市场',
|
fromMarketplace: '来自市场',
|
||||||
endpointsEnabled: '{{num}} 组端点已启用',
|
endpointsEnabled: '{{num}} 组端点已启用',
|
||||||
searchTools: '搜索工具...',
|
searchTools: '搜索工具...',
|
||||||
|
installPlugin: '安装插件',
|
||||||
|
installFrom: '安装源',
|
||||||
|
list: {
|
||||||
|
noInstalled: '无已安装的插件',
|
||||||
|
notFound: '未找到插件',
|
||||||
|
source: {
|
||||||
|
marketplace: '从市场安装',
|
||||||
|
github: '从GitHub安装',
|
||||||
|
local: '从本地文件安装',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
marketplace: '市场',
|
||||||
|
github: 'GitHub',
|
||||||
|
local: '本地文件',
|
||||||
|
},
|
||||||
detailPanel: {
|
detailPanel: {
|
||||||
categoryTip: {
|
categoryTip: {
|
||||||
marketplace: '从 Marketplace 安装',
|
marketplace: '从 Marketplace 安装',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user