Skip to content

Commit 35859c4

Browse files
authored
feat: VNDB Tag Translation zh_CN (#10)
* feat: VNDB Tag Translation zh_CN * feat(settings): add tag translation settings in multiple languages
1 parent a5b7122 commit 35859c4

10 files changed

Lines changed: 5560 additions & 3 deletions

File tree

src/locales/VndbTag_zh_CN.json

Lines changed: 5448 additions & 0 deletions
Large diffs are not rendered by default.

src/locales/en_US.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
"filter": "Filter NSFW content",
5353
"coverReplace": "NSFW cover replace"
5454
},
55+
"tagTranslation": {
56+
"title": "TAG Translation",
57+
"description": "Enable Chinese translation for game tags"
58+
},
5559
"cardClickMode": {
5660
"title": "Card Click Mode",
5761
"navigate": "Navigation Mode (Single click to view details)",

src/locales/ja_JP.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
"filter": "NSFWコンテンツのフィルタリング",
5353
"coverReplace": "NSFW表紙の置き換え"
5454
},
55+
"tagTranslation": {
56+
"title": "TAG翻訳",
57+
"description": "ゲームタグの中国語翻訳を有効にする"
58+
},
5559
"cardClickMode": {
5660
"title": "カードクリックモード",
5761
"navigate": "ナビゲーションモード(シングルクリックで詳細表示)",

src/locales/zh_CN.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
"filter": "过滤 NSFW 内容",
5353
"coverReplace": "NSFW 封面替换"
5454
},
55+
"tagTranslation": {
56+
"title": "TAG翻译",
57+
"description": "开启后将使用中文翻译显示游戏标签"
58+
},
5559
"cardClickMode": {
5660
"title": "卡片点击模式",
5761
"navigate": "导航模式(单击跳转详情页)",

src/locales/zh_TW.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
"filter": "過濾NSFW内容",
5353
"coverReplace": "模糊NSFW替換"
5454
},
55+
"tagTranslation": {
56+
"title": "TAG翻譯",
57+
"description": "開啟後將使用中文翻譯顯示遊戲標籤"
58+
},
5559
"cardClickMode": {
5660
"title": "卡片點擊模式",
5761
"navigate": "導航模式(單擊跳轉詳情頁)",

src/pages/Detail/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { Backup } from './Backup';
3131
import { getGameById } from '@/utils/repository';
3232
import i18n from '@/utils/i18n';
3333
import { getGameDisplayName } from '@/utils';
34+
import { translateTags } from '@/utils/tagTranslation';
3435

3536

3637
// Tab面板组件
@@ -70,7 +71,7 @@ const TabPanel = (props: TabPanelProps) => {
7071
export const Detail: React.FC = () => {
7172
const id = Number(useLocation().pathname.split('/').pop());
7273
const { t } = useTranslation();
73-
const { setSelectedGameId, selectedGame, fetchGame } = useStore();
74+
const { setSelectedGameId, selectedGame, fetchGame, tagTranslation } = useStore();
7475
const [tabIndex, setTabIndex] = useState(0);
7576
const [isLoading, setIsLoading] = useState(true); // 添加加载状态
7677
const [currentId, setCurrentId] = useState<number | null>(null); // 跟踪当前显示的游戏ID
@@ -190,8 +191,8 @@ export const Detail: React.FC = () => {
190191
<Box className="mt-2">
191192
<Typography variant="subtitle2" fontWeight="bold" gutterBottom component="div">{t('pages.Detail.gameTags')}</Typography>
192193
<Stack direction="row" className="flex-wrap gap-1">
193-
{selectedGame.tags?.map(tag => (
194-
<Chip key={tag} label={tag} size="small" variant="outlined" />
194+
{translateTags(selectedGame.tags || [], tagTranslation).map((tag, index) => (
195+
<Chip key={`${selectedGame.tags?.[index] || tag}-${index}`} label={tag} size="small" variant="outlined" />
195196
))}
196197
</Stack>
197198
</Box>

src/pages/Settings/index.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,31 @@ const NsfwSettings = () => {
277277
);
278278
};
279279

280+
const TagTranslationSettings = () => {
281+
const { t } = useTranslation();
282+
const { tagTranslation, setTagTranslation } = useStore();
283+
284+
return (
285+
<Box className="mb-6">
286+
<Stack direction="row" alignItems="center" className="min-w-60">
287+
<Box>
288+
<InputLabel className="font-semibold mb-1">
289+
{t('pages.Settings.tagTranslation.title')}
290+
</InputLabel>
291+
<Typography variant="caption" color="text.secondary">
292+
{t('pages.Settings.tagTranslation.description')}
293+
</Typography>
294+
</Box>
295+
<Switch
296+
checked={tagTranslation}
297+
onChange={(e) => setTagTranslation(e.target.checked)}
298+
color="primary"
299+
/>
300+
</Stack>
301+
</Box>
302+
);
303+
};
304+
280305
const CardClickModeSettings = () => {
281306
const { t } = useTranslation();
282307
const { cardClickMode, setCardClickMode, doubleClickLaunch, setDoubleClickLaunch, longPressLaunch, setLongPressLaunch } = useStore();
@@ -745,6 +770,10 @@ export const Settings: React.FC = () => {
745770
<LanguageSelect />
746771
<Divider sx={{ my: 3 }} />
747772

773+
{/* TAG翻译设置 */}
774+
<TagTranslationSettings />
775+
<Divider sx={{ my: 3 }} />
776+
748777
{/* NSFW设置 */}
749778
<NsfwSettings />
750779
<Divider sx={{ my: 3 }} />

src/store/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ export interface AppState {
131131
longPressLaunch: boolean;
132132
setLongPressLaunch: (enabled: boolean) => void;
133133

134+
// TAG翻译功能
135+
tagTranslation: boolean;
136+
setTagTranslation: (enabled: boolean) => void;
137+
134138
// 更新游戏通关状态
135139
updateGameClearStatusInStore: (gameId: number, newClearStatus: 1 | 0) => void;
136140

@@ -207,6 +211,13 @@ export const useStore = create<AppState>()(
207211
setSetting('longPressLaunch', enabled);
208212
},
209213

214+
// TAG翻译功能(默认关闭)
215+
tagTranslation: false,
216+
setTagTranslation: (enabled: boolean) => {
217+
set({tagTranslation: enabled});
218+
setSetting('tagTranslation', enabled);
219+
},
220+
210221
// 优化刷新数据的方法,减少状态更新
211222
refreshGameData: async (customSortOption?: string, customSortOrder?: 'asc' | 'desc') => {
212223
set({loading: true});
@@ -604,12 +615,14 @@ export const useStore = create<AppState>()(
604615
const cardClickMode = getSetting('cardClickMode') ?? 'navigate';
605616
const doubleClickLaunch = getSetting('doubleClickLaunch') ?? false;
606617
const longPressLaunch = getSetting('longPressLaunch') ?? false;
618+
const tagTranslation = getSetting('tagTranslation') ?? false;
607619
set({
608620
nsfwFilter,
609621
nsfwCoverReplace,
610622
cardClickMode,
611623
doubleClickLaunch,
612624
longPressLaunch,
625+
tagTranslation,
613626
});
614627

615628
// 然后并行加载其他数据

src/utils/localStorage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ interface Settings {
3838
doubleClickLaunch?: boolean;
3939
// 新增:长按启动游戏功能
4040
longPressLaunch?: boolean;
41+
// 新增:TAG翻译功能
42+
tagTranslation?: boolean;
4143
}
4244

4345
// 默认设置
@@ -50,6 +52,7 @@ const DEFAULT_SETTINGS: Settings = {
5052
cardClickMode: 'navigate', // 默认使用导航模式
5153
doubleClickLaunch: false, // 默认关闭双击启动
5254
longPressLaunch: false, // 默认关闭长按启动
55+
tagTranslation: false, // 默认关闭TAG翻译
5356
};
5457

5558
// 获取所有游戏数据(增加排序功能)

src/utils/tagTranslation.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @file TAG翻译工具
3+
* @description 提供VNDB TAG的中文翻译功能
4+
* @module src/utils/tagTranslation
5+
* @author Pysio<qq593277393@outlook.com>
6+
* @copyright AGPL-3.0
7+
*/
8+
9+
import vndbTagTranslationsRaw from '@/locales/VndbTag_zh_CN.json';
10+
11+
// 过滤掉元数据字段,只保留翻译内容
12+
const vndbTagTranslations = Object.fromEntries(
13+
Object.entries(vndbTagTranslationsRaw).filter(([key]) => !key.startsWith('_'))
14+
) as Record<string, string>;
15+
16+
/**
17+
* 翻译单个TAG
18+
* @param tag 原始英文TAG
19+
* @returns 翻译后的中文TAG,如果没有找到翻译则返回原TAG
20+
*/
21+
export function translateTag(tag: string): string {
22+
// 直接从翻译对象中查找翻译
23+
const translation = vndbTagTranslations[tag];
24+
return translation || tag;
25+
}
26+
27+
/**
28+
* 翻译TAG数组
29+
* @param tags 原始英文TAG数组
30+
* @param enableTranslation 是否启用翻译,默认为true
31+
* @returns 翻译后的TAG数组
32+
*/
33+
export function translateTags(tags: string[], enableTranslation: boolean = true): string[] {
34+
if (!enableTranslation || !tags) {
35+
return tags || [];
36+
}
37+
38+
return tags.map(tag => translateTag(tag));
39+
}
40+
41+
/**
42+
* 获取TAG翻译对象(用于调试或其他用途)
43+
* @returns VNDB TAG翻译对象
44+
*/
45+
export function getTagTranslations(): Record<string, string> {
46+
return vndbTagTranslations;
47+
}

0 commit comments

Comments
 (0)