From e2d0fc792c097e7af7b8eab81e04857c44c93ec3 Mon Sep 17 00:00:00 2001 From: kazukokawagawa <2580099704@qq.com> Date: Fri, 26 Dec 2025 19:05:11 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=96=B0=E5=A2=9Ei18n?= =?UTF-8?q?=E6=94=AF=E6=8C=81=EF=BC=8C=E8=8B=B1=E8=AF=AD=E3=80=81=E6=97=A5?= =?UTF-8?q?=E8=AF=AD=E3=80=81=E9=9F=A9=E8=AF=AD=E3=80=81=E4=BF=84=E8=AF=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 48 +- src/components/Layout/Menu.vue | 43 +- src/components/Layout/Nav.vue | 40 +- src/components/Layout/User.vue | 27 +- src/components/List/ArtistList.vue | 4 +- src/components/List/CommentList.vue | 5 +- src/components/List/CoverList.vue | 3 +- src/components/List/ListDetail.vue | 21 +- src/components/List/SongList.vue | 49 +- src/components/Menu/SongListMenu.vue | 88 +- src/components/Modal/AutoClose.vue | 14 +- src/components/Modal/CopyLyrics.vue | 12 +- src/components/Modal/CreatePlaylist.vue | 33 +- src/components/Modal/DownloadModal.vue | 37 +- src/components/Modal/PlaylistAdd.vue | 25 +- src/components/Modal/Setting/AMLLServer.vue | 21 +- .../Modal/Setting/ExcludeLyrics.vue | 56 +- src/components/Modal/Setting/FontManager.vue | 45 +- .../Modal/Setting/HomePageSectionManager.vue | 5 +- .../Modal/Setting/SidebarHideManager.vue | 30 +- .../Modal/Setting/SongUnlockManager.vue | 7 +- src/components/Player/MainPlayList.vue | 28 +- src/components/Player/MainPlayer.vue | 26 +- src/components/Player/PlayerRightMenu.vue | 19 +- src/components/Search/SearchInp.vue | 19 +- src/components/Setting/AboutSetting.vue | 54 +- src/components/Setting/GeneralSetting.vue | 183 ++-- src/components/Setting/KeyboardSetting.vue | 61 +- src/components/Setting/LocalSetting.vue | 186 ++-- src/components/Setting/LyricsSetting.vue | 282 ++--- src/components/Setting/MainSetting.vue | 103 +- src/components/Setting/OtherSetting.vue | 137 +-- src/components/Setting/PlaySetting.vue | 219 ++-- src/components/Setting/ThirdSetting.vue | 118 ++- src/i18n/index.ts | 40 + src/locales/en-US.ts | 963 ++++++++++++++++++ src/locales/ja-JP.ts | 963 ++++++++++++++++++ src/locales/ko-KR.ts | 963 ++++++++++++++++++ src/locales/ru-RU.ts | 963 ++++++++++++++++++ src/locales/zh-CN.ts | 963 ++++++++++++++++++ src/main.ts | 6 + src/stores/setting.ts | 24 +- src/utils/auth.ts | 69 +- src/utils/helper.ts | 13 +- src/utils/modal.ts | 59 +- src/utils/time.ts | 17 +- src/views/Cloud.vue | 13 +- src/views/DailySongs.vue | 16 +- src/views/Discover/layout.vue | 13 +- src/views/Discover/playlists.vue | 23 +- src/views/Download/layout.vue | 26 +- src/views/Home/HomeOnline.vue | 105 +- src/views/Home/index.vue | 10 +- src/views/Like/albums.vue | 2 +- src/views/Like/artists.vue | 2 +- src/views/Like/layout.vue | 15 +- src/views/Like/playlists.vue | 6 +- src/views/Like/radios.vue | 2 +- src/views/Like/videos.vue | 2 +- src/views/List/liked.vue | 19 +- src/views/Local/layout.vue | 34 +- src/views/Radio/hot.vue | 20 +- src/views/Radio/type.vue | 11 +- src/views/Search/albums.vue | 12 +- src/views/Search/artists.vue | 12 +- src/views/Search/layout.vue | 17 +- src/views/Search/playlists.vue | 12 +- src/views/Search/radios.vue | 12 +- src/views/Search/songs.vue | 12 +- src/views/Search/videos.vue | 12 +- src/views/Status/403.vue | 8 +- src/views/Status/404.vue | 8 +- src/views/Status/500.vue | 8 +- src/views/Video.vue | 78 +- 75 files changed, 6544 insertions(+), 1058 deletions(-) create mode 100644 src/i18n/index.ts create mode 100644 src/locales/en-US.ts create mode 100644 src/locales/ja-JP.ts create mode 100644 src/locales/ko-KR.ts create mode 100644 src/locales/ru-RU.ts create mode 100644 src/locales/zh-CN.ts diff --git a/package.json b/package.json index b31533091..f02e611ff 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "pinia-plugin-persistedstate": "^4.7.1", "plyr": "^3.8.3", "sortablejs": "^1.15.6", + "vue-i18n": "^11.2.7", "ws": "^8.18.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd5290fdc..4e15d51d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -138,6 +138,9 @@ importers: sortablejs: specifier: ^1.15.6 version: 1.15.6 + vue-i18n: + specifier: ^11.2.7 + version: 11.2.7(vue@3.5.25(typescript@5.9.3)) ws: specifier: ^8.18.3 version: 8.18.3 @@ -620,8 +623,8 @@ packages: resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} engines: {node: '>=12'} - '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': - resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2} + '@electron/node-gyp@git+https://git@github.com:electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2': + resolution: {commit: 06b29aafb7708acef8b3669835c8a7857ebc92d2, repo: git@github.com:electron/node-gyp.git, type: git} version: 10.2.0-electron.1 engines: {node: '>=12.13.0'} hasBin: true @@ -1196,6 +1199,18 @@ packages: resolution: {integrity: sha512-sLXkCpdd5L8s0mVNWLaTBNXK4RYLNbEnlZIMT/wml8GCDFYsLLJbpkRraQUlMwpw8SgdmJCCi8T5GCUcfySwRw==} engines: {node: '>=20'} + '@intlify/core-base@11.2.7': + resolution: {integrity: sha512-+Ra9I/LAzXDnmv/IrTO03WMCiLya7pHRmGJvNl9fKwx/W4REJ0xaMk2PxCRqnxcBsX443amEMdebQ3R1geiuIw==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@11.2.7': + resolution: {integrity: sha512-TFamC+GzJAotAFwUNvbtRVBgvuSn2nCwKNresmPUHv3IIVMmXJt7QQJj/DORI1h8hs46ZF6L0Fs2xBohSOE4iQ==} + engines: {node: '>= 16'} + + '@intlify/shared@11.2.7': + resolution: {integrity: sha512-uvlkvc/0uQ4FDlHQZccpUnmcOwNcaI3i+69ck2YJ+GqM35AoVbuS63b+YfirV4G0SZh64Ij2UMcFRMmB4nr95w==} + engines: {node: '>= 16'} + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -5002,6 +5017,12 @@ packages: peerDependencies: eslint: ^8.57.0 || ^9.0.0 + vue-i18n@11.2.7: + resolution: {integrity: sha512-LPv8bAY5OA0UvFEXl4vBQOBqJzRrlExy92tWgRuwW7tbykHf7CH71G2Y4TM2OwGcIS4+hyqKHS2EVBqaYwPY9Q==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + vue-router@4.6.3: resolution: {integrity: sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==} peerDependencies: @@ -5614,7 +5635,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + '@electron/node-gyp@git+https://git@github.com:electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2': dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.3 @@ -5651,7 +5672,7 @@ snapshots: '@electron/rebuild@3.7.0': dependencies: - '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 + '@electron/node-gyp': git+https://git@github.com:electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2 '@malept/cross-spawn-promise': 2.0.0 chalk: 4.1.2 debug: 4.4.3 @@ -6079,6 +6100,18 @@ snapshots: '@material/material-color-utilities': 0.2.7 colorthief: 2.6.0 + '@intlify/core-base@11.2.7': + dependencies: + '@intlify/message-compiler': 11.2.7 + '@intlify/shared': 11.2.7 + + '@intlify/message-compiler@11.2.7': + dependencies: + '@intlify/shared': 11.2.7 + source-map-js: 1.2.1 + + '@intlify/shared@11.2.7': {} + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -10330,6 +10363,13 @@ snapshots: transitivePeerDependencies: - supports-color + vue-i18n@11.2.7(vue@3.5.25(typescript@5.9.3)): + dependencies: + '@intlify/core-base': 11.2.7 + '@intlify/shared': 11.2.7 + '@vue/devtools-api': 6.6.4 + vue: 3.5.25(typescript@5.9.3) + vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)): dependencies: '@vue/devtools-api': 6.6.4 diff --git a/src/components/Layout/Menu.vue b/src/components/Layout/Menu.vue index 902bd33cd..d55f1b189 100644 --- a/src/components/Layout/Menu.vue +++ b/src/components/Layout/Menu.vue @@ -27,6 +27,8 @@ import { NAvatar, NBadge, } from "naive-ui"; +import { useI18n } from "vue-i18n"; + import type { CoverType } from "@/types/main"; import { useStatusStore, useSettingStore, useDataStore, useMusicStore } from "@/stores"; import { useRouter, RouterLink } from "vue-router"; @@ -43,6 +45,8 @@ const musicStore = useMusicStore(); const statusStore = useStatusStore(); const settingStore = useSettingStore(); const player = usePlayerController(); +const { t } = useI18n(); + // 菜单数据 const menuRef = ref(null); @@ -55,7 +59,8 @@ const menuOptions = computed(() => { { key: "home", link: "home", - label: "为我推荐", + label: t("menu.recommend"), + icon: renderIcon("Home", { style: { transform: "translateY(-1px)", @@ -65,7 +70,8 @@ const menuOptions = computed(() => { { key: "discover", link: "discover", - label: "发现音乐", + label: t("menu.discover"), + show: !settingStore.hideDiscover, icon: renderIcon("Discover", { style: { @@ -75,7 +81,8 @@ const menuOptions = computed(() => { }, { key: "personal-fm", - label: "私人漫游", + label: t("menu.roaming"), + show: isLogin() !== 0 && !settingStore.hidePersonalFM, icon: renderIcon("Radio", { style: { @@ -86,7 +93,8 @@ const menuOptions = computed(() => { { key: "radio-hot", link: "radio-hot", - label: "播客电台", + label: t("menu.podcast"), + show: !settingStore.hideRadioHot, icon: renderIcon("Record", { style: { @@ -102,8 +110,9 @@ const menuOptions = computed(() => { key: "like-songs", label: () => h("div", { class: "user-liked" }, [ - h(NText, null, () => "我喜欢的音乐"), + h(NText, null, () => t("menu.myLikeSongs")), !settingStore.hideHeartbeatMode + ? h(NButton, { type: statusStore.playHeartbeatMode ? "primary" : "default", round: true, @@ -122,14 +131,16 @@ const menuOptions = computed(() => { { key: "like", link: "like", - label: "我的收藏", + label: t("menu.myCollection"), + show: !settingStore.hideLike, icon: renderIcon("Star"), }, { key: "cloud", link: "cloud", - label: "我的云盘", + label: t("menu.myCloud"), + show: isLogin() === 1 && !settingStore.hideCloud, icon: renderIcon("Cloud"), }, @@ -143,22 +154,25 @@ const menuOptions = computed(() => { value: dataStore.downloadingSongs.length, offset: [22, 13], }, - () => "下载管理", + () => t("menu.download"), ), + show: statusStore.isDeveloperMode && isElectron && !settingStore.hideDownload, icon: renderIcon("Download"), }, { key: "local", link: "local", - label: "本地歌曲", + label: t("menu.local"), + show: isElectron && !settingStore.hideLocal, icon: renderIcon("FolderMusic"), }, { key: "history", link: "history", - label: "最近播放", + label: t("menu.recent"), + show: !settingStore.hideHistory, icon: renderIcon("History"), }, @@ -173,8 +187,9 @@ const menuOptions = computed(() => { icon: statusStore.menuCollapsed ? renderIcon("PlaylistAdd") : undefined, label: () => h("div", { class: "user-list" }, [ - h(NText, { depth: 3 }, () => ["创建的歌单"]), + h(NText, { depth: 3 }, () => [t("menu.createdList")]), h(NButton, { + type: "tertiary", round: true, strong: true, @@ -197,8 +212,9 @@ const menuOptions = computed(() => { h( "div", { class: "user-list" }, - h(NText, { depth: 3 }, () => ["收藏的歌单"]), + h(NText, { depth: 3 }, () => [t("menu.collectedList")]), ), + children: [...likedPlaylist.value], }, ] @@ -206,7 +222,8 @@ const menuOptions = computed(() => { { key: "local", link: "local", - label: "本地歌曲", + label: t("menu.local"), + show: isElectron, icon: renderIcon("FolderMusic"), }, diff --git a/src/components/Layout/Nav.vue b/src/components/Layout/Nav.vue index 5b2e1880a..ec3940d3a 100644 --- a/src/components/Layout/Nav.vue +++ b/src/components/Layout/Nav.vue @@ -23,7 +23,7 @@ - + @@ -33,18 +33,18 @@ -
- +
+
-
+
-
- +
+ @@ -68,32 +68,33 @@ - 确认关闭软件吗? - 记住且不再询问 + {{ t("nav.client.content") }} + {{ t("nav.client.remember") }} + @@ -103,7 +104,9 @@ import { useSettingStore } from "@/stores"; import { renderIcon } from "@/utils/helper"; import { openSetting } from "@/utils/modal"; import { isDev, isElectron } from "@/utils/env"; +import { useI18n } from "vue-i18n"; +const { t } = useI18n(); const router = useRouter(); const settingStore = useSettingStore(); @@ -150,10 +153,10 @@ const setOptions = computed(() => [ { label: settingStore.themeMode === "auto" - ? "浅色模式" + ? t("nav.menu.auto") : settingStore.themeMode === "light" - ? "深色模式" - : "跟随系统", + ? t("nav.menu.light") + : t("nav.menu.dark"), key: "themeMode", icon: renderIcon( settingStore.themeMode === "auto" @@ -170,20 +173,20 @@ const setOptions = computed(() => [ { // 重启 key: "restart", - label: "软件热重载", + label: t("nav.menu.reload"), show: isElectron, props: { onClick: () => window.electron.ipcRenderer.send("win-reload") }, icon: renderIcon("Restart"), }, { key: "dev-tools", - label: "开启控制台", + label: t("nav.menu.console"), show: isDev, icon: renderIcon("Code"), }, { key: "setting", - label: "全局设置", + label: t("nav.menu.global"), icon: renderIcon("Settings"), }, ]); @@ -214,6 +217,7 @@ onMounted(() => { }); } }); +