Add i18n support with language selector on login page (#1410)

* feat: add i18n support with language selector on login page

Co-Authored-By: Junyan Qin <Chin> <rockchinq@gmail.com>

* feat: complete i18n implementation for all webui components

Co-Authored-By: Junyan Qin <Chin> <rockchinq@gmail.com>

* feat: complete all hardcoded text

* feat: dynamic label i18n

* fix: lint errors

* fix: lint errors

* delete sh fils

* fix: edit model dialog title

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Junyan Qin <Chin> <rockchinq@gmail.com>
This commit is contained in:
devin-ai-integration[bot]
2025-05-13 22:39:19 +08:00
committed by GitHub
parent 91cd8cf380
commit 2bf94539bd
25 changed files with 898 additions and 233 deletions
@@ -5,6 +5,7 @@ import styles from '@/app/home/plugins/plugins.module.css';
import { PluginMarketCardVO } from '@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO';
import PluginMarketCardComponent from '@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardComponent';
import { spaceClient } from '@/app/infra/http/HttpClient';
import { useTranslation } from 'react-i18next';
import { Input } from '@/components/ui/input';
import {
Pagination,
@@ -27,6 +28,7 @@ export default function PluginMarketComponent({
}: {
askInstallPlugin: (githubURL: string) => void;
}) {
const { t } = useTranslation();
const [marketPluginList, setMarketPluginList] = useState<
PluginMarketCardVO[]
>([]);
@@ -105,7 +107,7 @@ export default function PluginMarketComponent({
console.log('market plugins:', res);
})
.catch((error) => {
console.error('获取插件列表失败:', error);
console.error(t('plugins.getPluginListError'), error);
setLoading(false);
});
}
@@ -131,7 +133,7 @@ export default function PluginMarketComponent({
width: '300px',
}}
value={searchKeyword}
placeholder="搜索插件"
placeholder={t('plugins.searchPlugin')}
onChange={(e) => onInputSearchKeyword(e.target.value)}
/>
@@ -140,12 +142,16 @@ export default function PluginMarketComponent({
onValueChange={handleSortChange}
>
<SelectTrigger className="w-[180px] ml-2 cursor-pointer">
<SelectValue placeholder="排序方式" />
<SelectValue placeholder={t('plugins.sortBy')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="stars,DESC"></SelectItem>
<SelectItem value="created_at,DESC"></SelectItem>
<SelectItem value="pushed_at,DESC"></SelectItem>
<SelectItem value="stars,DESC">{t('plugins.mostStars')}</SelectItem>
<SelectItem value="created_at,DESC">
{t('plugins.recentlyAdded')}
</SelectItem>
<SelectItem value="pushed_at,DESC">
{t('plugins.recentlyUpdated')}
</SelectItem>
</SelectContent>
</Select>
@@ -221,11 +227,11 @@ export default function PluginMarketComponent({
<div className={`${styles.pluginListContainer}`}>
{loading ? (
<div style={{ textAlign: 'center', padding: '20px' }}>
{/* 加载中... */}
{t('plugins.loading')}
</div>
) : marketPluginList.length === 0 ? (
<div style={{ textAlign: 'center', padding: '20px' }}>
{/* 没有找到匹配的插件 */}
{t('plugins.noMatchingPlugins')}
</div>
) : (
marketPluginList.map((vo, index) => (