mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 03:32:23 +08:00
feat: add internationalization support for plugin categories and update translations
This commit is contained in:
parent
1573f6f6aa
commit
a1719c49b7
|
@ -87,3 +87,42 @@ export const useTags = (translateFromOut?: TFunction) => {
|
|||
tagsMap,
|
||||
}
|
||||
}
|
||||
|
||||
type Category = {
|
||||
name: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export const useCategories = (translateFromOut?: TFunction) => {
|
||||
const { t: translation } = useTranslation()
|
||||
const t = translateFromOut || translation
|
||||
|
||||
const categories = [
|
||||
{
|
||||
name: 'model',
|
||||
label: t('pluginCategories.categories.model'),
|
||||
},
|
||||
{
|
||||
name: 'tool',
|
||||
label: t('pluginCategories.categories.tool'),
|
||||
},
|
||||
{
|
||||
name: 'extension',
|
||||
label: t('pluginCategories.categories.extension'),
|
||||
},
|
||||
{
|
||||
name: 'bundle',
|
||||
label: t('pluginCategories.categories.bundle'),
|
||||
},
|
||||
]
|
||||
|
||||
const categoriesMap = categories.reduce((acc, category) => {
|
||||
acc[category.name] = category
|
||||
return acc
|
||||
}, {} as Record<string, Category>)
|
||||
|
||||
return {
|
||||
categories,
|
||||
categoriesMap,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ const PluginItem: FC<Props> = ({
|
|||
}}
|
||||
>
|
||||
<div className={cn('relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs', className)}>
|
||||
<CornerMark text={category} />
|
||||
<CornerMark text={t(`pluginCategories.categories.${category}`)} />
|
||||
{/* Header */}
|
||||
<div className="flex">
|
||||
<div className='flex items-center justify-center w-10 h-10 overflow-hidden border-components-panel-border-subtle border-[1px] rounded-xl'>
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import cn from '@/utils/classnames'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { useCategories } from '../../hooks'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type CategoriesFilterProps = {
|
||||
value: string[]
|
||||
|
@ -22,27 +24,11 @@ const CategoriesFilter = ({
|
|||
value,
|
||||
onChange,
|
||||
}: CategoriesFilterProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [open, setOpen] = useState(false)
|
||||
const [searchText, setSearchText] = useState('')
|
||||
const options = [
|
||||
{
|
||||
value: 'model',
|
||||
text: 'Model',
|
||||
},
|
||||
{
|
||||
value: 'tool',
|
||||
text: 'Tool',
|
||||
},
|
||||
{
|
||||
value: 'extension',
|
||||
text: 'Extension',
|
||||
},
|
||||
{
|
||||
value: 'bundle',
|
||||
text: 'Bundle',
|
||||
},
|
||||
]
|
||||
const filteredOptions = options.filter(option => option.text.toLowerCase().includes(searchText.toLowerCase()))
|
||||
const { categories: options, categoriesMap } = useCategories()
|
||||
const filteredOptions = options.filter(option => option.name.toLowerCase().includes(searchText.toLowerCase()))
|
||||
const handleCheck = (id: string) => {
|
||||
if (value.includes(id))
|
||||
onChange(value.filter(tag => tag !== id))
|
||||
|
@ -70,10 +56,10 @@ const CategoriesFilter = ({
|
|||
'flex items-center p-1 system-sm-medium',
|
||||
)}>
|
||||
{
|
||||
!selectedTagsLength && 'All Categories'
|
||||
!selectedTagsLength && t('pluginCategories.allCategories')
|
||||
}
|
||||
{
|
||||
!!selectedTagsLength && value.slice(0, 2).join(',')
|
||||
!!selectedTagsLength && value.map(val => categoriesMap[val].label).slice(0, 2).join(',')
|
||||
}
|
||||
{
|
||||
selectedTagsLength > 2 && (
|
||||
|
@ -110,23 +96,23 @@ const CategoriesFilter = ({
|
|||
showLeftIcon
|
||||
value={searchText}
|
||||
onChange={e => setSearchText(e.target.value)}
|
||||
placeholder='Search categories'
|
||||
placeholder={t('pluginCategories.searchCategories')}
|
||||
/>
|
||||
</div>
|
||||
<div className='p-1 max-h-[448px] overflow-y-auto'>
|
||||
{
|
||||
filteredOptions.map(option => (
|
||||
<div
|
||||
key={option.value}
|
||||
key={option.name}
|
||||
className='flex items-center px-2 py-1.5 h-7 rounded-lg cursor-pointer hover:bg-state-base-hover'
|
||||
onClick={() => handleCheck(option.value)}
|
||||
onClick={() => handleCheck(option.name)}
|
||||
>
|
||||
<Checkbox
|
||||
className='mr-1'
|
||||
checked={value.includes(option.value)}
|
||||
checked={value.includes(option.name)}
|
||||
/>
|
||||
<div className='px-1 system-sm-medium text-text-secondary'>
|
||||
{option.text}
|
||||
{option.label}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use client'
|
||||
|
||||
import Input from '@/app/components/base/input'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
type SearchBoxProps = {
|
||||
searchQuery: string
|
||||
onChange: (query: string) => void
|
||||
|
@ -10,13 +11,15 @@ const SearchBox: React.FC<SearchBoxProps> = ({
|
|||
searchQuery,
|
||||
onChange,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Input
|
||||
wrapperClassName='flex w-[200px] items-center rounded-lg'
|
||||
className='bg-components-input-bg-normal'
|
||||
showLeftIcon
|
||||
value={searchQuery}
|
||||
placeholder='Search'
|
||||
placeholder={t('plugin.search')}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value)
|
||||
}}
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import cn from '@/utils/classnames'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { useTags } from '../../hooks'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type TagsFilterProps = {
|
||||
value: string[]
|
||||
|
@ -22,19 +24,11 @@ const TagsFilter = ({
|
|||
value,
|
||||
onChange,
|
||||
}: TagsFilterProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [open, setOpen] = useState(false)
|
||||
const [searchText, setSearchText] = useState('')
|
||||
const options = [
|
||||
{
|
||||
value: 'search',
|
||||
text: 'Search',
|
||||
},
|
||||
{
|
||||
value: 'image',
|
||||
text: 'Image',
|
||||
},
|
||||
]
|
||||
const filteredOptions = options.filter(option => option.text.toLowerCase().includes(searchText.toLowerCase()))
|
||||
const { tags: options, tagsMap } = useTags()
|
||||
const filteredOptions = options.filter(option => option.name.toLowerCase().includes(searchText.toLowerCase()))
|
||||
const handleCheck = (id: string) => {
|
||||
if (value.includes(id))
|
||||
onChange(value.filter(tag => tag !== id))
|
||||
|
@ -62,10 +56,10 @@ const TagsFilter = ({
|
|||
'flex items-center p-1 system-sm-medium',
|
||||
)}>
|
||||
{
|
||||
!selectedTagsLength && 'All Tags'
|
||||
!selectedTagsLength && t('pluginTags.allTags')
|
||||
}
|
||||
{
|
||||
!!selectedTagsLength && value.slice(0, 2).join(',')
|
||||
!!selectedTagsLength && value.map(val => tagsMap[val].label).slice(0, 2).join(',')
|
||||
}
|
||||
{
|
||||
selectedTagsLength > 2 && (
|
||||
|
@ -97,23 +91,23 @@ const TagsFilter = ({
|
|||
showLeftIcon
|
||||
value={searchText}
|
||||
onChange={e => setSearchText(e.target.value)}
|
||||
placeholder='Search tags'
|
||||
placeholder={t('pluginTags.searchTags')}
|
||||
/>
|
||||
</div>
|
||||
<div className='p-1 max-h-[448px] overflow-y-auto'>
|
||||
{
|
||||
filteredOptions.map(option => (
|
||||
<div
|
||||
key={option.value}
|
||||
key={option.name}
|
||||
className='flex items-center px-2 py-1.5 h-7 rounded-lg cursor-pointer hover:bg-state-base-hover'
|
||||
onClick={() => handleCheck(option.value)}
|
||||
onClick={() => handleCheck(option.name)}
|
||||
>
|
||||
<Checkbox
|
||||
className='mr-1'
|
||||
checked={value.includes(option.value)}
|
||||
checked={value.includes(option.name)}
|
||||
/>
|
||||
<div className='px-1 system-sm-medium text-text-secondary'>
|
||||
{option.text}
|
||||
{option.label}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
|
4
web/i18n/de-DE/plugin-categories.ts
Normal file
4
web/i18n/de-DE/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
12
web/i18n/en-US/plugin-categories.ts
Normal file
12
web/i18n/en-US/plugin-categories.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
const translation = {
|
||||
allCategories: 'All Categories',
|
||||
searchCategories: 'Search categories',
|
||||
categories: {
|
||||
model: 'Model',
|
||||
tool: 'Tool',
|
||||
extension: 'Extension',
|
||||
bundle: 'Bundle',
|
||||
},
|
||||
}
|
||||
|
||||
export default translation
|
|
@ -6,6 +6,7 @@ const translation = {
|
|||
extensions: 'extensions',
|
||||
bundles: 'bundles',
|
||||
},
|
||||
search: 'Search',
|
||||
searchPlugins: 'Search plugins',
|
||||
from: 'From',
|
||||
findMoreInMarketplace: 'Find more in Marketplace',
|
||||
|
|
4
web/i18n/es-ES/plugin-categories.ts
Normal file
4
web/i18n/es-ES/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/fa-IR/plugin-categories.ts
Normal file
4
web/i18n/fa-IR/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/fr-FR/plugin-categories.ts
Normal file
4
web/i18n/fr-FR/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/hi-IN/plugin-categories.ts
Normal file
4
web/i18n/hi-IN/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
|
@ -30,6 +30,7 @@ const loadLangResources = (lang: string) => ({
|
|||
runLog: require(`./${lang}/run-log`).default,
|
||||
plugin: require(`./${lang}/plugin`).default,
|
||||
pluginTags: require(`./${lang}/plugin-tags`).default,
|
||||
pluginCategories: require(`./${lang}/plugin-categories`).default,
|
||||
},
|
||||
})
|
||||
|
||||
|
|
4
web/i18n/it-IT/plugin-categories.ts
Normal file
4
web/i18n/it-IT/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/ja-JP/plugin-categories.ts
Normal file
4
web/i18n/ja-JP/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/ko-KR/plugin-categories.ts
Normal file
4
web/i18n/ko-KR/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/pl-PL/plugin-categories.ts
Normal file
4
web/i18n/pl-PL/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/pt-BR/plugin-categories.ts
Normal file
4
web/i18n/pt-BR/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/ro-RO/plugin-categories.ts
Normal file
4
web/i18n/ro-RO/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/ru-RU/plugin-categories.ts
Normal file
4
web/i18n/ru-RU/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/tr-TR/plugin-categories.ts
Normal file
4
web/i18n/tr-TR/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/uk-UA/plugin-categories.ts
Normal file
4
web/i18n/uk-UA/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
4
web/i18n/vi-VN/plugin-categories.ts
Normal file
4
web/i18n/vi-VN/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
12
web/i18n/zh-Hans/plugin-categories.ts
Normal file
12
web/i18n/zh-Hans/plugin-categories.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
const translation = {
|
||||
allCategories: '所有类型',
|
||||
searchCategories: '搜索类型',
|
||||
categories: {
|
||||
model: '模型',
|
||||
tool: '工具',
|
||||
extension: '扩展',
|
||||
bundle: '捆绑包',
|
||||
},
|
||||
}
|
||||
|
||||
export default translation
|
|
@ -6,6 +6,7 @@ const translation = {
|
|||
extensions: '扩展',
|
||||
bundles: '捆绑包',
|
||||
},
|
||||
search: '搜索',
|
||||
searchPlugins: '搜索插件',
|
||||
from: '来自',
|
||||
findMoreInMarketplace: '在 Marketplace 中查找更多',
|
||||
|
|
4
web/i18n/zh-Hant/plugin-categories.ts
Normal file
4
web/i18n/zh-Hant/plugin-categories.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
const translation = {
|
||||
}
|
||||
|
||||
export default translation
|
Loading…
Reference in New Issue
Block a user