feat: add internationalization support for plugin categories and update translations

This commit is contained in:
twwu 2024-11-13 16:55:43 +08:00
parent 1573f6f6aa
commit a1719c49b7
26 changed files with 159 additions and 46 deletions

View File

@ -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,
}
}

View File

@ -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'>

View File

@ -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>
))

View File

@ -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)
}}

View File

@ -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>
))

View File

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

View 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

View File

@ -6,6 +6,7 @@ const translation = {
extensions: 'extensions',
bundles: 'bundles',
},
search: 'Search',
searchPlugins: 'Search plugins',
from: 'From',
findMoreInMarketplace: 'Find more in Marketplace',

View File

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

View File

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

View File

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

View File

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

View File

@ -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,
},
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,12 @@
const translation = {
allCategories: '所有类型',
searchCategories: '搜索类型',
categories: {
model: '模型',
tool: '工具',
extension: '扩展',
bundle: '捆绑包',
},
}
export default translation

View File

@ -6,6 +6,7 @@ const translation = {
extensions: '扩展',
bundles: '捆绑包',
},
search: '搜索',
searchPlugins: '搜索插件',
from: '来自',
findMoreInMarketplace: '在 Marketplace 中查找更多',

View File

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