Compare commits

...

486 Commits

Author SHA1 Message Date
a33a03f512 Bump version to 3.7.1 2024-12-27 01:44:11 +09:00
f8a53f0d61 fix(api-server): fix swagger 2024-12-27 01:43:03 +09:00
748d77d1c0 fix(downloader): fix #2234 2024-12-27 01:30:09 +09:00
725ad0d630 fix(deps): update dependency node-html-parser to v7 (#2776)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-27 01:15:58 +09:00
bdbab17772 chore(deps): update dependency vite to v6.0.6 (#2774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-27 01:15:18 +09:00
57d2fa372d fix(synced-lyrics): use blur instead of static background color 2024-12-27 01:13:53 +09:00
80471b0ca4 fix: use networkManager.fetch instead of fetch 2024-12-27 01:05:55 +09:00
22fdfe3342 fix(downloader): fix #2769 2024-12-27 00:50:18 +09:00
5ecfa2a1f7 fix: fix #2645, fix #2741 2024-12-26 23:49:19 +09:00
b9beea810e fix(music-together): fix crash 2024-12-26 23:14:42 +09:00
f0e77812e7 fix: fix login CORS issue 2024-12-26 23:13:28 +09:00
6d1237c2a2 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 29.8% (121 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2024-12-26 06:04:43 +00:00
b43c92386e chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-12-26 06:04:42 +00:00
017476a81b chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-12-26 06:04:41 +00:00
9b047d9c54 chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-12-26 06:04:40 +00:00
31f009d3c4 chore(i18n): Translated using Weblate (Polish)
Currently translated at 98.7% (401 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-12-26 06:04:40 +00:00
8504f2c086 chore(i18n): Translated using Weblate (Italian)
Currently translated at 99.2% (403 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2024-12-26 06:04:39 +00:00
1d6251baea feat(api-server): Add queue api (#2767) 2024-12-25 18:55:24 +09:00
3ea13a2a22 fix(api-server): repeat event listener 2024-12-25 13:08:02 +09:00
1cc153084d Update changelog for v3.7.0 2024-12-25 01:45:32 +00:00
1c468b4054 Bump version to 3.7.0 2024-12-25 10:28:55 +09:00
1bad46890a fix: fix possible NPE 2024-12-25 10:28:24 +09:00
5829c8d0f7 chore(i18n): Translated using Weblate (Urdu)
Currently translated at 15.7% (64 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ur/
2024-12-25 02:17:53 +01:00
85aceaaae4 chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2024-12-25 02:15:11 +01:00
24e593b22f fix: use HEAD instead of GET in songInfo.imageSrc validation step
Thanks to @daika7ana!
Close #2766
2024-12-25 09:49:30 +09:00
3f8ca6002e chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (403 of 403 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-12-25 01:45:27 +01:00
b62ccfe7b1 feat(amuse): song query api (add amuse plugin) (#2723)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-12-25 09:45:19 +09:00
237dde9765 feat(api-server): add absolute seek endpoint (#2748)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-12-25 08:46:51 +09:00
65f4339fd1 fix: flatpak baseVersion 2024-12-25 08:42:59 +09:00
109e9f8166 feat(api-server): Add repeat mode and seek time API (#2630)
Co-authored-by: sent44 <sent44@root533.premium-rootserver.net>
Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-12-25 08:41:44 +09:00
9163b6f04b fix(ci): Bump flatpak runtime version 2024-12-25 08:17:40 +09:00
51da259c97 feat(synced-lyrics): Better-Lyrics Styling for Synced-Lyrics (#2554)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-12-25 08:15:36 +09:00
2bf67b941e chore(i18n): Translated using Weblate (Urdu)
Currently translated at 15.7% (63 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ur/
2024-12-24 23:44:35 +01:00
533b96d1f6 feat(synced-lyrics): multiple lyric sources (#2383)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-12-25 07:44:29 +09:00
5c9ded8779 chore(deps): update dependency typescript-eslint to v8.18.2 (#2763)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-25 01:42:18 +09:00
6f389bb297 chore(i18n): Added translation using Weblate (Urdu) 2024-12-24 08:59:48 +01:00
8a209404d4 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 26.1% (105 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2024-12-24 08:59:35 +01:00
6193fb487a chore(i18n): Translated using Weblate (Hindi)
Currently translated at 25.9% (104 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2024-12-23 17:00:41 +01:00
9aa7f7a023 chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2024-12-23 17:00:40 +01:00
5bfaa9a791 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-12-23 17:00:39 +01:00
py
d210ec8227 chore(i18n): Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hans/
2024-12-23 17:00:38 +01:00
dec7c5e95c chore(i18n): Translated using Weblate (Ukrainian)
Currently translated at 99.0% (397 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/uk/
2024-12-23 17:00:37 +01:00
940d0beb84 chore(i18n): Translated using Weblate (French)
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fr/
2024-12-23 17:00:36 +01:00
cf98754276 chore(deps): update dependency discord-api-types to v0.37.114 (#2761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-24 00:37:14 +09:00
d91d493dd1 chore(deps): update dependency discord-api-types to v0.37.113 (#2759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-23 09:11:34 +09:00
7e1aea21db fix: Set correct window class for X11 and Wayland (#2758) 2024-12-23 09:10:57 +09:00
0179dfd311 feat: Specify flatpak runtime (#2755) 2024-12-22 23:39:05 +09:00
98ea26bbff chore(deps): update dependency rollup to v4.29.1 (#2749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-22 23:38:48 +09:00
0d9daaad66 chore(deps): update dependency esbuild to v0.24.2 (#2742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-22 23:38:33 +09:00
fe319daec1 fix: Add Flatpak permissions needed for MPRIS and tray icon (#2754) 2024-12-22 23:37:30 +09:00
929c58671a chore(deps): update dependency vite-plugin-inspect to v0.10.6 (#2756)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-22 23:36:28 +09:00
4fb2350c2b chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-12-21 16:00:29 +01:00
a401bfa809 chore(i18n): Translated using Weblate (Japanese)
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ja/
2024-12-21 16:00:28 +01:00
fdeed76f6f chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (401 of 401 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2024-12-21 16:00:27 +01:00
0ab113816a chore(deps): update dependency vite to v6.0.5 (#2745)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 23:33:52 +09:00
8a58b02c7b fix(deps): update dependency i18next to v24.2.0 (#2744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 23:32:16 +09:00
037b059b55 chore(deps): update dependency vite-plugin-inspect to v0.10.4 (#2743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 23:32:07 +09:00
bb0f9fb3d0 chore(deps): update dependency discord-api-types to v0.37.112 (#2740)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-20 23:31:24 +09:00
d3c7848896 fix(discord): use net.fetch instead of fetch 2024-12-20 23:23:15 +09:00
ea50cb1e65 fix(discord): check imageSrc 2024-12-20 23:22:48 +09:00
5070fd88b5 fix(discord): Fix Album Art failing on Discord RPC (#2666) 2024-12-20 23:19:51 +09:00
21177478cb fix(equalizer): add addedVersion 2024-12-20 23:19:33 +09:00
26b8b38b89 feat: Add equalizer plugin with presets (e.g. bass booster) (#2575) 2024-12-20 23:17:11 +09:00
be04d66aa8 fix: use ghostry adblocker 2024-12-19 19:53:43 +09:00
a837987e70 chore(deps): update dependency vite to v6.0.4 (#2738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-19 19:28:44 +09:00
da99558163 fix: Fixed #1796 (#2736) 2024-12-19 19:24:32 +09:00
3b50cbcb6e Revert "feat: use swc and lightningcss"
This reverts commit ae3a289005.
2024-12-19 12:42:31 +09:00
595c011bce Revert "fix: fix minify size issue"
This reverts commit 458fe54063.
2024-12-19 12:42:15 +09:00
458fe54063 fix: fix minify size issue 2024-12-19 12:38:49 +09:00
ae3a289005 feat: use swc and lightningcss 2024-12-19 12:22:15 +09:00
a49eea9246 chore(deps): update dependency electron-devtools-installer to v4 (#2734)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 22:02:22 +09:00
d675a175e9 Revert "chore(deps): update dependency electron-builder to v25" (#2732)
This reverts commit 6c510a71c2.
2024-12-18 16:14:39 +09:00
6c510a71c2 chore(deps): update dependency electron-builder to v25 (#2490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 13:23:56 +09:00
5503d2cbb8 fix(deps): update dependency i18next to v24.1.2 (#2727)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 12:05:24 +09:00
ba4c7e1a0c chore(deps): update dependency electron-devtools-installer to v3.2.1 (#2731)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 12:02:00 +09:00
e19c458441 chore(deps): update dependency typescript-eslint to v8.18.1 (#2724)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-17 09:11:12 +09:00
ec5cf0cae8 chore(i18n): Translated using Weblate (Filipino)
Currently translated at 87.1% (346 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fil/
2024-12-16 10:00:36 +01:00
b3c4570f8c fix: tab misalignment (#2713) 2024-12-16 11:49:57 +09:00
112b6d893b fix(deps): update dependency @hono/zod-validator to v0.4.2 (#2709)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 22:02:16 +09:00
52236907e4 chore(deps): update eslint monorepo to v9.17.0 (#2712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 22:00:38 +09:00
d449529ea7 fix(deps): update dependency hono to v4.6.14 (#2716)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-15 22:00:28 +09:00
61c799f7d4 fix: discord rich presence connection status (#2714)
* fix: discord rich presence connection status

* fix: optional chaining already handles null case
2024-12-15 22:00:00 +09:00
1a4ee13e47 fix(CI): temporary disable title check 2024-12-13 12:33:17 +09:00
f91afb984a fix: Laggy scrolling behaviour in large playlists (#2708) 2024-12-13 12:28:48 +09:00
f9892b0eae fix(deps): update dependency youtubei.js to v12.2.0 (#2705)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-13 12:19:20 +09:00
60c7885a3c fix(deps): update dependency i18next to v24.1.0 (#2698)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-11 20:58:08 +09:00
63ca6aa533 chore(deps): update dependency @stylistic/eslint-plugin-js to v2.12.1 (#2697)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-11 20:57:53 +09:00
e77a8c04e8 fix(deps): update dependency zod to v3.24.1 (#2694)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-11 13:30:22 +09:00
0bfabf604c fix(deps): update dependency youtubei.js to v12.1.0 (#2695)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-11 07:22:18 +09:00
4343c599cf chore(deps): update dependency discord-api-types to v0.37.111 (#2690)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-10 12:06:17 +09:00
c251554c31 chore(deps): update dependency typescript-eslint to v8.18.0 (#2692)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-10 12:06:09 +09:00
95e519bdc9 chore(deps): update playwright monorepo to v1.49.1 (#2693)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-10 12:06:00 +09:00
79d38bfc8e fix(deps): update dependency hono to v4.6.13 (#2682)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 18:26:40 +09:00
f5655b0ae6 chore(deps): update dependency rollup to v4.28.1 (#2683)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 18:26:24 +09:00
12b4afc3ce fix(deps): update dependency conf to v13.1.0 (#2686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 18:26:10 +09:00
c104d47737 chore(deps): update dependency @stylistic/eslint-plugin-js to v2.12.0 (#2689)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 18:25:59 +09:00
870cf6143c chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 97.9% (389 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2024-12-06 18:00:23 +01:00
1baed0e913 fix(deps): update dependency youtubei.js to v12 (#2681)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-06 12:11:21 +09:00
02619c79bb chore(deps): update dependency vite to v6.0.3 (#2680)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-06 12:11:10 +09:00
0faad538f3 fix(album-actions): Fixed #2312 (#2676)
* Fixed #2312

* Update src/plugins/album-actions/index.ts

Co-authored-by: JellyBrick <shlee1503@naver.com>

---------

Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-12-06 12:10:10 +09:00
Bai
e7de30c629 chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2024-12-05 15:00:29 +01:00
c5d8333039 chore(deps): update dependency eslint-import-resolver-typescript to v3.7.0 (#2672)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-05 22:41:35 +09:00
4da08e7c9b chore(deps): update dependency node-gyp to v11 (#2678)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-05 22:41:25 +09:00
Bai
171387995a chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2024-12-04 02:00:59 +00:00
aeac020c9a fix(deps): update dependency i18next to v24.0.5 (#2669)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 21:51:58 +09:00
5c05ddeb29 fix(deps): update dependency i18next to v24.0.4 (#2668)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 16:30:34 +09:00
cbdd649365 chore(deps): update dependency vite to v6.0.2 (#2662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 16:30:23 +09:00
d2cf2ad71f chore(deps): update dependency node-gyp to v10.3.1 (#2665)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 16:28:21 +09:00
7d33494097 chore(deps): update dependency typescript-eslint to v8.17.0 (#2664)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 16:28:12 +09:00
ca83edabf3 chore(deps): update dependency vite-plugin-inspect to v0.10.3 (#2667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 16:27:33 +09:00
f84e77e814 chore(deps): update dependency rollup to v4.28.0 (#2661)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 22:07:47 +09:00
14f2120a32 chore(deps): update dependency discord-api-types to v0.37.110 (#2653)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 22:04:03 +09:00
1cbf14ee2a fix(deps): update dependency @hono/zod-openapi to v0.18.3 (#2654)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 22:03:54 +09:00
b7cb167fc6 chore(deps): update eslint monorepo to v9.16.0 (#2656)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 22:03:45 +09:00
41b9f8b967 chore(deps): update dependency vite-plugin-inspect to v0.10.2 (#2657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-01 22:03:34 +09:00
0b769ce287 fix(youtube-music.css): Fixed #2514 (#2659) 2024-12-01 22:03:11 +09:00
ad71ef8a68 chore(i18n): Translated using Weblate (Arabic)
Currently translated at 36.2% (144 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2024-11-30 15:00:35 +01:00
048a994f32 fix: Fixed Skip Disliked Song not working (#2651) 2024-11-28 20:21:41 +09:00
c2bd8ce188 fix(deps): update dependency @hono/zod-openapi to v0.18.2 (#2650)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-28 20:20:39 +09:00
62ce4e818c chore(deps): update dependency vite-plugin-inspect to v0.10.1 (#2652)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-28 20:20:24 +09:00
4ab8829a02 chore(deps): update dependency electron to v33.2.1 (#2649)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-28 12:02:27 +09:00
36b3e2cb0c chore(deps): update dependency vite-plugin-inspect to v0.10.0 (#2646)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 23:20:27 +09:00
9ba0614a7d chore(deps): update dependency vite to v6 (#2644)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 23:17:55 +09:00
81431ad196 fix(deps): update dependency @hono/swagger-ui to v0.5.0 (#2643)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 23:16:11 +09:00
a8e8d5afd7 chore(deps): update dependency discord-api-types to v0.37.109 (#2642)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 23:16:00 +09:00
f3d86743ee chore(deps): update dependency vite-plugin-solid to v2.11.0 (#2641)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 23:15:50 +09:00
6306968193 fix(deps): update dependency hono to v4.6.12 (#2636)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 07:24:16 +09:00
7142a253d6 fix(deps): update dependency i18next to v24.0.2 (#2637)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 07:24:07 +09:00
2a24588338 chore(deps): update dependency discord-api-types to v0.37.108 (#2638)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 07:23:58 +09:00
2abaf54ac8 chore(deps): update dependency typescript-eslint to v8.16.0 (#2639)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-27 07:23:26 +09:00
cc730ad55c chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-11-25 16:01:11 +00:00
d8581c5d69 chore(i18n): Translated using Weblate (Hebrew)
Currently translated at 10.3% (41 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/he/
2024-11-24 16:00:26 +01:00
3208bf4a6d fix: fix pnpm-lock.yaml 2024-11-24 14:46:02 +09:00
4109db1ad7 chore(deps): update dependency rollup to v4.27.4 (#2632)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 14:36:40 +09:00
87a0ef5d54 fix(deps): update dependency i18next to v24 (#2633)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 14:34:40 +09:00
cdc40f0c53 chore(deps): update dependency typescript to v5.7.2 (#2629)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 14:32:08 +09:00
7a3b8082a2 chore(deps): update dependency discord-api-types to v0.37.107 (#2627)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 14:31:57 +09:00
3e9039c97d fix(deps): update dependency @hono/zod-openapi to v0.18.0 (#2626)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 14:31:48 +09:00
b9d1130468 fix(deps): update dependency i18next to v23.16.8 (#2625)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-24 14:31:38 +09:00
605f0984e4 chore(deps): update dependency vite-plugin-inspect to v0.8.8 (#2623)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 12:27:36 +09:00
44de7d9e98 fix(deps): update dependency hono to v4.6.11 (#2624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 12:27:25 +09:00
9926575744 chore(deps): update playwright monorepo to v1.49.0 (#2617)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 12:26:28 +09:00
f16a99f6e4 chore(deps): update dependency rollup to v4.27.3 (#2610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 12:10:10 +09:00
a23c64b5b8 chore(deps): update dependency typescript-eslint to v8.15.0 (#2611)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 12:10:00 +09:00
0899f76548 chore(deps): update dependency @stylistic/eslint-plugin-js to v2.11.0 (#2618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-21 12:09:44 +09:00
515dcdc7e3 chore(i18n): Translated using Weblate (Arabic)
Currently translated at 35.7% (142 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2024-11-19 20:20:51 +01:00
b2c4bc425b chore(deps): update dependency discord-api-types to v0.37.105 (#2603)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 23:36:03 +09:00
363c3b3a67 chore(deps): update dependency rollup to v4.27.2 (#2604)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 23:35:54 +09:00
c2dde3d78f chore(deps): update eslint monorepo to v9.15.0 (#2607)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 23:35:45 +09:00
eb515cfc61 fix(deps): update dependency @hono/zod-openapi to v0.17.1 (#2608)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 23:35:34 +09:00
c208ca184f chore(i18n): Translated using Weblate (Estonian)
Currently translated at 19.3% (77 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/et/
2024-11-17 01:00:26 +01:00
c231fa7c44 fix(ambient-mode): fix ambient-mode overlapping other elements (#2609)
Co-authored-by: h-banii <h-banii@users.noreply.github.com>
2024-11-16 18:41:29 +09:00
9e1b8d43d0 fix: Allow media playback control (MPRIS) for flatpak (#2606) 2024-11-16 15:45:09 +09:00
f50ece88df chore(i18n): Translated using Weblate (Slovenian)
Currently translated at 69.2% (275 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sl/
2024-11-16 00:00:34 +01:00
eeb780d190 fix(deps): update dependency @hono/node-server to v1.13.7 (#2598)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 01:59:11 +09:00
cafdf654d3 chore(deps): update dependency rollup to v4.26.0 (#2600)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 01:47:36 +09:00
2d665013e7 fix(deps): update dependency hono to v4.6.10 (#2601)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-14 01:47:25 +09:00
451a46e208 chore(i18n): Translated using Weblate (Polish)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-11-12 19:00:31 +01:00
490b901c34 fix(deps): update dependency @hono/node-server to v1.13.6 (#2594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-12 18:12:53 +09:00
b57b4a3454 chore(deps): update dependency vite to v5.4.11 (#2595)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-12 18:12:43 +09:00
60c61e32b1 chore(deps): update dependency typescript-eslint to v8.14.0 (#2596)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-12 18:12:30 +09:00
aa9052d449 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 99.7% (396 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2024-11-11 10:00:21 +00:00
67f3a38583 chore(deps): update dependency electron to v33.2.0 (#2591)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 22:45:49 +09:00
a00ecc4729 fix(deps): update dependency @hono/zod-openapi to v0.17.0 (#2592)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 22:44:18 +09:00
56d63fca52 fix(deps): update dependency i18next to v23.16.5 (#2589)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 18:49:48 +09:00
759f3ba317 fix(deps): update dependency @hono/node-server to v1.13.5 (#2578)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 18:49:41 +09:00
d8daf03f2c fix(deps): update dependency hono to v4.6.9 (#2579)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 18:47:33 +09:00
a519c7c714 chore(deps): update dependency discord-api-types to v0.37.104 (#2588)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 18:47:27 +09:00
933d12fdd1 chore(deps): update dependency typescript-eslint to v8.13.0 (#2581)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 18:44:46 +09:00
61fb733550 chore(deps): update dependency rollup to v4.25.0 (#2580)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-10 18:44:40 +09:00
7f05e3168d chore(docs): Update screenshot (#2587) 2024-11-10 18:44:31 +09:00
3b7697a90d chore(docs): Specify full path to xattr for macOS, fixes #2583 (#2586) 2024-11-10 18:43:34 +09:00
350b1467fe chore(i18n): Translated using Weblate (Sinhala)
Currently translated at 12.3% (49 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/si/
2024-11-07 17:00:17 +00:00
2f5d102f4d chore(i18n): Translated using Weblate (Turkish)
Currently translated at 98.9% (393 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2024-11-05 21:00:23 +01:00
66e296df1a fix(taskbar-mediacontrol): remove console.log 2024-11-03 19:21:47 +09:00
1e4cd699db fix: callback for time-changed event (#2577)
Co-authored-by: Derek Alsop <15299183+Azorant@users.noreply.github.com>
2024-11-03 19:18:06 +09:00
516fbff3d7 fix: innerHTML trusted-types 2024-11-03 18:22:33 +09:00
aab9358d67 chore(deps): update eslint monorepo to v9.14.0 (#2573)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 15:48:00 +09:00
ae3939f857 chore(deps): update dependency utf-8-validate to v6.0.5 (#2572)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 15:45:54 +09:00
79bafd1780 chore(deps): update dependency @stylistic/eslint-plugin-js to v2.10.1 (#2571)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-03 15:44:46 +09:00
3f4f52a31f chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-11-01 15:00:19 +00:00
c2b7b29716 fix(deps): update dependency @hono/node-server to v1.13.4 (#2570)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-01 07:19:44 +09:00
dab84b9cf9 chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-10-31 15:00:16 +01:00
e5980158eb chore(deps): update dependency @stylistic/eslint-plugin-js to v2.10.0 (#2569)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-31 12:24:46 +09:00
647d4c9d99 fix(deps): update dependency @floating-ui/dom to v1.6.12 (#2568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-31 12:24:38 +09:00
30feb6128b chore(deps): update dependency rollup to v4.24.3 (#2565)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-30 07:57:12 +09:00
0cf6923540 fix(deps): update dependency hono to v4.6.8 (#2564)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-30 07:57:04 +09:00
cce9f0b462 chore(deps): update dependency typescript-eslint to v8.12.2 (#2563)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-30 07:56:55 +09:00
c0805fb758 chore(deps): update dependency typescript-eslint to v8.12.0 (#2561)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-29 07:13:13 +09:00
04e5844301 fix(deps): update dependency youtubei.js to v11 (#2562)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-29 07:13:03 +09:00
f28e663133 chore(i18n): Translated using Weblate (Slovenian)
Currently translated at 69.2% (275 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sl/
2024-10-28 17:00:25 +01:00
2c84527c43 chore(i18n): Translated using Weblate (Czech)
Currently translated at 95.2% (378 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/cs/
2024-10-28 17:00:23 +01:00
68511de727 chore(deps): update dependency rollup to v4.24.2 (#2559)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 19:33:15 +09:00
e7ca9f129f fix(deps): update dependency @hono/node-server to v1.13.3 (#2560)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 19:33:06 +09:00
259da70e4f fix(deps): update dependency i18next to v23.16.4 (#2550)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 19:01:37 +09:00
9409d75ac7 chore(deps): update playwright monorepo to v1.48.2 (#2551)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 19:01:24 +09:00
3ea923f56f fix(deps): update dependency hono to v4.6.7 (#2552)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 19:01:13 +09:00
6d6c8c94cf chore(deps): update dependency @babel/runtime to v7.26.0 (#2548)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-28 19:01:03 +09:00
29098758a9 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-10-27 16:00:14 +01:00
fdbb35e221 chore(deps): update dependency @types/color to v4 (#2547)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-25 12:15:35 +09:00
6ddac62313 fix(deps): update dependency i18next to v23.16.3 (#2545)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-25 07:18:08 +09:00
ae4b494300 chore(i18n): Translated using Weblate (Arabic)
Currently translated at 31.2% (124 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2024-10-24 21:13:04 +02:00
Adi
7d9eed88f4 chore(i18n): Translated using Weblate (French)
Currently translated at 98.7% (392 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fr/
2024-10-24 21:13:04 +02:00
4abf848f99 fix(deps): update dependency solid-js to v1.9.3 (#2541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 14:36:36 +09:00
cc0a6cfdce chore(deps): update dependency vite to v5.4.10 (#2542)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 14:25:16 +09:00
a74d0dd0ca chore(deps): update dependency electron to v33.0.2 (#2537)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 07:08:31 +09:00
18f15d4cce chore(deps): update dependency @babel/runtime to v7.25.9 (#2538)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-23 07:08:22 +09:00
80e20c6579 chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-10-22 19:15:42 +00:00
761026fd74 chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-10-22 19:15:41 +00:00
95b75f020c chore(deps): update dependency discord-api-types to v0.37.103 (#2532)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 22:28:47 +09:00
574e4baef8 chore(deps): update dependency typescript-eslint to v8.11.0 (#2534)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 22:28:39 +09:00
ec4871d5a8 fix(deps): update dependency hono to v4.6.6 (#2536)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-22 18:36:51 +09:00
ccd6bf9c3f chore(i18n): Translated using Weblate (Arabic)
Currently translated at 27.9% (111 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2024-10-21 12:16:16 +02:00
2975d4292c chore(i18n): Translated using Weblate (Romanian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ro/
2024-10-21 12:16:15 +02:00
ad9571550f fix(tuna-obs): Added song url to tuna-obs plugin (#2524) 2024-10-21 10:16:41 +09:00
980068217c fix(deps): update dependency i18next to v23.16.2 (#2530)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-21 00:05:49 +09:00
18f69aea3f fix(deps): update dependency i18next to v23.16.1 (#2529)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-20 23:34:58 +09:00
add7cb9e48 chore(deps): update eslint monorepo to v9.13.0 (#2528)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-20 23:34:48 +09:00
aa67a57971 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 1.5% (6 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2024-10-20 10:16:29 +02:00
74f22b4474 chore(i18n): Translated using Weblate (Japanese)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ja/
2024-10-20 10:16:29 +02:00
DW
7ef4a23576 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 0.2% (1 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2024-10-19 07:16:28 +02:00
3c90a1f459 chore(i18n): Translated using Weblate (Turkish)
Currently translated at 97.4% (387 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2024-10-19 07:16:27 +02:00
DW
3793d36f36 chore(i18n): Added translation using Weblate (Hindi) 2024-10-18 07:01:23 +02:00
179f4b29db chore(i18n): Translated using Weblate (Persian)
Currently translated at 74.3% (295 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fa/
2024-10-18 07:01:22 +02:00
34f106896c chore(i18n): Translated using Weblate (Icelandic)
Currently translated at 97.2% (386 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/is/
2024-10-18 07:01:22 +02:00
06b581f499 chore(deps): update dependency typescript-eslint to v8.10.0 (#2527)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-18 07:47:15 +09:00
3ec126628c chore(deps): update playwright monorepo to v1.48.1 (#2516)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-18 07:47:06 +09:00
1d3bb60e0b fix(tuna-obs): lite mode logic 2024-10-18 07:46:50 +09:00
2e3ced6006 fix(tuna-obs): fix lite mode logic 2024-10-18 07:45:49 +09:00
e8efca5a3e chore(i18n): Translated using Weblate (Persian)
Currently translated at 74.3% (295 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fa/
2024-10-17 19:16:24 +02:00
5161c356f9 chore(i18n): Translated using Weblate (Thai)
Currently translated at 70.2% (279 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/th/
2024-10-17 19:16:23 +02:00
py
e917b30e64 chore(i18n): Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hans/
2024-10-17 19:16:23 +02:00
2d847f9808 chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2024-10-17 19:16:22 +02:00
21755fffc7 chore(deps): update dependency electron to v33.0.1 (#2523)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-17 11:37:56 +09:00
5c9d3e3e67 fix: disable gpu memory buffer video frames (#2519) 2024-10-17 07:11:33 +09:00
ea801f65ef Update changelog for v3.6.2 2024-10-16 11:59:00 +00:00
27f4c0393e Bump version to 3.6.2 2024-10-16 20:43:19 +09:00
9bc42f836f fix: trustedTypes issue
- Close #2339
2024-10-16 20:40:35 +09:00
11b11ed966 fix(deps): update dependency serve to v14.2.4 (#2515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-16 20:15:01 +09:00
5f79b7e788 chore(i18n): Translated using Weblate (Icelandic)
Currently translated at 94.7% (376 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/is/
2024-10-15 22:15:39 +02:00
7d1d806797 chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2024-10-15 22:15:39 +02:00
836cedb0f3 chore(i18n): Translated using Weblate (Ukrainian)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/uk/
2024-10-15 22:15:39 +02:00
70349e13cc chore(i18n): Translated using Weblate (Russian)
Currently translated at 99.7% (396 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-10-15 22:15:39 +02:00
6d16b74471 fix(deps): update dependency hono to v4.6.5 (#2509)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 22:33:46 +09:00
c211780c33 chore(deps): update dependency vite to v5.4.9 (#2500)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 13:46:51 +09:00
2173ba0234 fix(api-server): properly implement next api call (#2505) 2024-10-15 13:34:19 +09:00
3a4cbc543b chore(deps): update dependency electron to v33 (#2507)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 13:30:11 +09:00
2fef7f0246 chore(deps): update dependency typescript-eslint to v8.9.0 (#2503)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 05:03:21 +09:00
12d693921e chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-10-14 19:24:56 +02:00
d1b4879f51 chore(deps): update dependency discord-api-types to v0.37.102 (#2501)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-14 23:32:47 +09:00
f14939fcd2 Update changelog for v3.6.1 2024-10-14 13:42:17 +00:00
4e66b0cedd fix: remove snap arm 2024-10-14 22:23:37 +09:00
11fe54d640 fix(style): fix youtube music player layout not aligned issue 2024-10-14 22:01:26 +09:00
446529f738 fix: remove pacman 2024-10-14 21:59:56 +09:00
ac6e9deeb9 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2024-10-14 14:42:58 +02:00
100873163f fix: remove "compression": "maximum" 2024-10-14 21:34:33 +09:00
e141e18bac fix: fix build 2024-10-14 21:27:42 +09:00
f4da0c2c95 fix: enum value must be one of xz,lzo, got 'maximum' 2024-10-14 21:17:15 +09:00
7507bce3cc fix: fix org.electronjs.Electron2.BaseApp/x86_64/20.08 2024-10-14 21:03:10 +09:00
2b970fade8 fix: fix org.freedesktop.Sdk/x86_64/20.08 2024-10-14 20:51:36 +09:00
35f0e43082 fix: remove duplicate flatpak 2024-10-14 20:38:25 +09:00
ae4410a613 fix(flatpak): remove armhf/arm64 2024-10-14 20:32:05 +09:00
5534174016 fix: fix flatpak build 2024-10-14 20:27:33 +09:00
15cf6c77c3 fix: fix flatpak release 2024-10-14 20:12:54 +09:00
18a8fc462d fix: fix pnpm-lock 2024-10-14 20:01:02 +09:00
d3acb4945a chore(flatpak-builder): Add more details when failing 2024-10-14 19:57:41 +09:00
32d3c58b44 fix: fix release workflow 2024-10-14 19:33:37 +09:00
bd8c2eb390 fix: configuration has an unknown property 'AppImage' 2024-10-14 19:26:24 +09:00
a81fa9c0d1 fix: apt update 2024-10-14 19:22:02 +09:00
1d0f7d7a48 fix: fix release 2024-10-14 19:20:04 +09:00
b6687307df Bump version to 3.6.1 2024-10-14 19:16:25 +09:00
7e07a44f68 fix(downloader): fix #2371 2024-10-14 18:27:04 +09:00
5ca66530ee fix(ytm-bugs): incorrect video ratio
- Close #2459
2024-10-14 18:16:22 +09:00
95acbe2b65 fix: fix conflict with adguard 2024-10-14 18:06:08 +09:00
534aeb163a fix(api-server): fix init/authentication error
- Close #2497
2024-10-14 17:51:59 +09:00
6abcbee290 chore(i18n): Translated using Weblate (English)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/en/
2024-10-14 09:54:33 +02:00
4457a043a4 chore(i18n): Translated using Weblate (English)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/en/
2024-10-14 09:54:05 +02:00
410a052fea chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-10-14 09:51:36 +02:00
e4287085a1 chore(i18n): Translated using Weblate (Filipino)
Currently translated at 87.1% (346 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fil/
2024-10-14 09:51:36 +02:00
b6cefef8fb fix(api-server): Various fixes and improvements (#2496) 2024-10-14 16:48:11 +09:00
9d7e2a06bc fix(deps): update dependency electron-debug to v4.1.0 (#2499)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-14 16:45:19 +09:00
d516fc2153 fix(renderer): fix force like buttons display logic (#2493) 2024-10-14 04:27:23 +09:00
77bfe8e218 fix: RSS feed CORS issue
- Close #1620
2024-10-14 04:04:17 +09:00
0fcbe38837 fix(deps): update dependency i18next to v23.16.0 (#2492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-14 03:46:38 +09:00
b85a40f683 Update changelog for v3.6.0 2024-10-13 13:57:28 +00:00
8020d61715 Bump version to 3.6.0 2024-10-13 22:48:28 +09:00
cb1381bbb3 fix: apply fix from eslint 2024-10-13 22:45:11 +09:00
f42f20f770 chore(i18n): Translated using Weblate (Persian)
Currently translated at 49.1% (195 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fa/
2024-10-13 15:40:48 +02:00
9fb1dbfde0 chore(i18n): Translated using Weblate (Arabic)
Currently translated at 26.9% (107 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2024-10-13 15:40:47 +02:00
4f1ebab45d chore(i18n): Translated using Weblate (Catalan)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ca/
2024-10-13 15:34:42 +02:00
95644ea513 chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (397 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2024-10-13 15:34:41 +02:00
2fcddc8d2d chore(i18n): Translated using Weblate (Spanish)
Currently translated at 99.7% (396 of 397 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2024-10-13 15:34:41 +02:00
6505a93645 fix(api-server): fix i18n 2024-10-13 21:56:17 +09:00
11c25efd47 fix(taskbar-mediacontrol): fix icon color
- Close #2485
2024-10-13 21:45:20 +09:00
a97bc8da5a fix(README): fix eslint path 2024-10-13 21:42:00 +09:00
782116b31b fix: pin deps version 2024-10-13 19:14:40 +09:00
708d4b5480 chore(deps): Bump pnpm/action-setup to v4 2024-10-13 19:11:03 +09:00
9ba8913da7 feat(api-server): remote control api (#1909)
Co-authored-by: JellyBrick <shlee1503@naver.com>
Co-authored-by: Angelos Bouklis <angelbouklis.official@gmail.com>
Co-authored-by: Angelos Bouklis <me@arjix.dev>
Co-authored-by: Angelos Bouklis <53124886+ArjixWasTaken@users.noreply.github.com>
2024-10-13 19:10:12 +09:00
d07dae2542 fix: fix pnpm-lock.yaml 2024-10-13 18:24:36 +09:00
e7f213c4dc chore(eslint): apply eslint-plugin-prettier
- Close #2438
2024-10-13 18:24:01 +09:00
4cbf6c015b chore(deps): update playwright monorepo to v1.48.0 (#2489)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 18:05:01 +09:00
8acb93225b fix(synced-lyrics): fix text extract logic 2024-10-13 18:03:37 +09:00
8153955ccf fix(synced-lyrics): Fix 2 issues (#2441) 2024-10-13 18:00:03 +09:00
1de1cbac65 chore(deps): update dependency typescript to v5.6.3 (#2486)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:14:17 +09:00
825aac1dab chore(deps): update dependency electron to v32.2.0 (#2487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:14:08 +09:00
d48aa7ad39 chore(deps): update dependency del-cli to v6 (#2475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:12:05 +09:00
65ad09a02e chore(deps): update dependency typescript-eslint to v8.8.1 (#2477)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:11:56 +09:00
08aae09446 fix(deps): update dependency solid-js to v1.9.2 (#2480)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:11:25 +09:00
88f54a389f Revert "chore(deps): update dependency electron-builder to v25" (#2488) 2024-10-13 17:11:11 +09:00
4c23b1f970 chore(deps): update dependency electron-builder to v25 (#2406)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:09:34 +09:00
a979f1c8ea fix(deps): update dependency deepmerge-ts to v7.1.3 (#2481)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-13 17:09:28 +09:00
ead448ed98 chore(i18n): Translated using Weblate (Persian)
Currently translated at 51.0% (195 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fa/
2024-10-11 06:56:26 +02:00
fade340e80 chore(i18n): Translated using Weblate (Arabic)
Currently translated at 28.0% (107 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2024-10-11 06:56:25 +02:00
8cc8160f70 chore(i18n): Translated using Weblate (Persian)
Currently translated at 22.5% (86 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fa/
2024-10-10 14:39:44 +02:00
ee354ff678 chore(i18n): Added translation using Weblate (Persian) 2024-10-10 01:45:13 +02:00
ca7ccc7b3e chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-10-09 17:15:40 +02:00
f6b2766ec2 fix(deps): update dependency ts-morph to v24 (#2474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-07 12:42:06 +09:00
4a5f811485 fix(deps): update dependency i18next to v23.15.2 (#2471)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 19:57:18 +09:00
a092da7ba5 chore(deps): update eslint monorepo to v9.12.0 (#2470)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:32:49 +09:00
b587a16419 chore(deps): update dependency @stylistic/eslint-plugin-js to v2.9.0 (#2469)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:30:15 +09:00
4cf4f19ccc chore(deps): bump micromatch from 4.0.5 to 4.0.8 (#2465)
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-05 15:06:59 +09:00
5b84c9efce chore(deps): bump braces from 3.0.2 to 3.0.3 (#2466)
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-05 15:06:52 +09:00
98bbbfd851 fix(deps): update dependency electron-updater to v6.3.9 (#2468)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:04:15 +09:00
da2dbcacc4 fix(deps): update dependency deepmerge-ts to v7.1.1 (#2467)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:02:19 +09:00
7b6235694b chore(deps): update dependency typescript-eslint to v8.8.0 (#2457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:02:09 +09:00
4ad8e7b9dc chore(deps): update dependency @babel/runtime to v7.25.7 (#2462)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:02:01 +09:00
51ecfff86b chore(deps): update dependency rollup to v4.24.0 (#2458)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 15:00:04 +09:00
2c21a03201 chore(deps): update dependency eslint-plugin-import to v2.31.0 (#2464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-05 14:59:44 +09:00
4c2cb8dac9 chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 73.2% (280 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-10-04 15:15:48 +02:00
9edcd2c32e chore(i18n): Translated using Weblate (Filipino)
Currently translated at 86.9% (332 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fil/
2024-10-03 02:15:41 +00:00
0829fd2167 chore(deps): update dependency rollup to v4.22.5 (#2448)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-30 07:24:04 +09:00
494e58296b chore(deps): update dependency typescript-eslint to v8.7.0 (#2450)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-30 07:20:57 +09:00
151da2d786 fix(deps): update dependency solid-js to v1.9.1 (#2451)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-30 07:20:46 +09:00
d7f5f28091 chore(deps): update dependency vite to v5.4.8 (#2449)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-28 15:52:06 +09:00
358fb3b084 chore(deps): update dependency discord-api-types to v0.37.101 (#2440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-28 15:51:54 +09:00
af79ba266d chore(deps): update dependency esbuild to v0.24.0 (#2439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-28 15:51:44 +09:00
45f419f41a chore(deps): update eslint monorepo to v9.11.1 (#2442)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-28 15:35:42 +09:00
5189d6cfee chore(deps): update dependency @types/howler to v2.2.12 (#2443)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-28 15:35:30 +09:00
102034b58c chore(i18n): Translated using Weblate (Polish)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-09-24 18:15:47 +02:00
50d92bc004 chore(i18n): Translated using Weblate (English)
Currently translated at 99.7% (381 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/en/
2024-09-24 18:15:46 +02:00
f2716e1dc8 chore(i18n): Translated using Weblate (Polish)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-09-23 17:26:28 +02:00
9d436ed0a8 chore(i18n): Translated using Weblate (Polish)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-09-23 17:26:28 +02:00
31d472e289 chore(deps): update dependency vite to v5.4.7 (#2434)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-22 08:17:56 +09:00
7f9a2b3011 chore(deps): update playwright monorepo to v1.47.2 (#2436)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-22 08:17:35 +09:00
f54b346dce chore(deps): update eslint monorepo to v9.11.0 (#2437)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-22 08:17:12 +09:00
dbff62bc5b fix(deps): update dependency youtubei.js to v10.5.0 (#2431)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-22 08:13:18 +09:00
87f43e3237 chore(deps): update dependency rollup to v4.22.4 (#2430)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-22 08:13:00 +09:00
49cdcbdcc2 chore(deps): update dependency electron to v32.1.2 (#2433)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-22 08:12:50 +09:00
bcff26c85b chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 72.2% (276 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-09-21 03:40:55 +00:00
bcfb33b4b1 chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 72.2% (276 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-09-21 03:40:54 +00:00
b172d8e509 chore(i18n): Added translation using Weblate (Portuguese (Brazil)) 2024-09-20 04:55:25 +02:00
f10d146272 chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2024-09-19 23:40:54 +02:00
6105821a94 feat: ESLint Flat Config (v9 support #2229) (#2426)
* Flat config

* undo accidental formatting changes

* remove extra newline
2024-09-19 21:19:41 +09:00
7c983df6f4 chore(deps): update dependency electron to v32.1.1 2024-09-19 07:39:25 +09:00
cbbddefcf8 chore(i18n): Translated using Weblate (Ukrainian)
Currently translated at 97.3% (372 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/uk/
2024-09-18 15:41:01 +00:00
8d49c67fcb Update changelog for v3.5.3 2024-09-17 12:41:36 +00:00
c94b22b82c Bump version to 3.5.3 2024-09-17 21:32:22 +09:00
cab3cb49f0 chore(deps): update dependency electron to v32.1.0 2024-09-17 21:31:29 +09:00
e42084f008 fix(deps): update dependency @floating-ui/dom to v1.6.11 2024-09-17 21:30:11 +09:00
adca273ec3 chore(deps): update dependency typescript to v5.6.2 2024-09-17 21:28:03 +09:00
91dceb3c22 chore(deps): update playwright monorepo to v1.47.1 2024-09-17 21:27:47 +09:00
216e76f4a1 fix(music-together): fix ? operator 2024-09-17 21:09:30 +09:00
178bfa483f fix: openToast to toastService 2024-09-17 21:05:35 +09:00
10ecf5d2fe fix(src/index): fix typo 2024-09-17 20:40:23 +09:00
7099b81296 fix(src/index): ignore eslint error 2024-09-17 20:40:23 +09:00
1f15376b00 chore(deps): update dependency vite to v5.4.6 2024-09-17 20:39:32 +09:00
02b7a39753 chore(deps): update dependency eslint to v8.57.1 2024-09-17 20:38:38 +09:00
6edc84a8bd chore(deps): update dependency rollup to v4.21.3 2024-09-17 20:38:19 +09:00
11a0d39064 fix(song-info-front): fix nullable issue 2024-09-17 20:27:11 +09:00
d5a5ed35b6 fix: fix trustedHTML issue
- (Maybe) fix #2339, caused by YouTube's A/B testing
2024-09-17 20:05:22 +09:00
dbb9e95b32 fix(deps): update dependency i18next to v23.15.1 2024-09-17 18:27:27 +09:00
d4c8a4320d chore(deps): update typescript-eslint monorepo to v8.6.0 2024-09-17 18:27:05 +09:00
68d4f38e41 chore(i18n): Translated using Weblate (Hungarian)
Currently translated at 94.7% (362 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hu/
2024-09-15 22:09:12 +00:00
2204784e89 chore(i18n): Translated using Weblate (Icelandic)
Currently translated at 92.9% (355 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/is/
2024-09-15 22:09:12 +00:00
c3b995b0a8 chore(i18n): Translated using Weblate (Hebrew)
Currently translated at 6.0% (23 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/he/
2024-09-11 22:09:24 +02:00
ed0a344077 chore(i18n): Translated using Weblate (Polish)
Currently translated at 95.2% (364 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-09-09 22:09:15 +00:00
199d912823 Update changelog for v3.5.2 2024-09-07 12:27:30 +00:00
089eff3152 Revert "chore(deps): update dependency electron-builder to v25"
This reverts commit fe4c89c349.
2024-09-07 20:22:27 +09:00
306ee8dba5 Bump version to 3.5.2 2024-09-07 19:09:15 +09:00
a4992bafb2 fix(synced-lyric): fix timestamp
- Close #2323
- Close #2379
2024-09-07 19:06:52 +09:00
5b004eedff fix(song-info): fix regex 2024-09-07 18:40:24 +09:00
2a66076d31 fix(synced-lyric): optimize logic 2024-09-07 18:37:37 +09:00
f48e46d29c chore(deps): update dependency eslint-plugin-import to v2.30.0 2024-09-07 18:29:22 +09:00
20296f5463 chore(deps): update dependency rollup to v4.21.2 2024-09-07 18:29:16 +09:00
fe4c89c349 chore(deps): update dependency electron-builder to v25 2024-09-07 18:29:09 +09:00
3640527c8c fix(synced-lyrics): LRCLIB returns 0 results if album is undefined
- inspired by #2381
2024-09-07 18:28:13 +09:00
3326582a16 chore(deps): update dependency electron to v32 2024-09-07 18:21:41 +09:00
5dcb9fe9ba fix(deps): update dependency i18next to v23.14.0 2024-09-07 18:19:15 +09:00
336fa1e6fd fix(deps): update dependency youtubei.js to v10.4.0 2024-09-07 18:19:09 +09:00
3679a109d6 chore(deps): update dependency esbuild to v0.23.1 2024-09-07 18:15:01 +09:00
5290ed3de2 chore(deps): update playwright monorepo to v1.47.0 2024-09-07 18:14:40 +09:00
fe5195714f chore(deps): update typescript-eslint monorepo to v8.4.0 (#2401)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 18:14:27 +09:00
8eb846262d chore(deps): update dependency @total-typescript/ts-reset to v0.6.1 (#2396)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 18:09:00 +09:00
e9a1c2a91f chore(deps): update dependency electron to v31.5.0 (#2397)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 18:08:41 +09:00
2d1f78b383 chore(deps): update dependency eslint-import-resolver-typescript to v3.6.3 (#2376)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 18:06:07 +09:00
1899064fd3 chore(deps): update dependency discord-api-types to v0.37.100 (#2394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 18:06:00 +09:00
e0280e5fe2 fix(deps): update dependency electron-updater to v6.3.4 (#2395)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 18:05:54 +09:00
d577e0fba6 chore(deps): update dependency @babel/runtime to v7.25.6 (#2388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 17:26:24 +09:00
37577c2f7f chore(deps): update dependency vite-plugin-inspect to v0.8.7 (#2389)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-07 17:26:16 +09:00
c880f0a4eb chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2024-09-05 21:09:15 +02:00
4875955914 chore(deps): update dependency discord-api-types to v0.37.99 (#2374)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-04 23:47:50 +09:00
5b28c780bd chore(deps): update dependency vite to v5.4.3 (#2377)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-04 23:47:42 +09:00
4db2674b15 chore(i18n): Translated using Weblate (Greek)
Currently translated at 52.6% (201 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/el/
2024-09-02 23:09:12 +00:00
Sen
a454a0163f chore(i18n): Translated using Weblate (Dutch)
Currently translated at 74.0% (283 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/nl/
2024-08-31 21:09:31 +02:00
61eb28e780 fix: incorrect regex when splitting artistName (#2378)
Fixes the incorrect regex used to split a string in the form of `Name1 & Name2` or `Name1, Name2`.

Previously the regex was actually splitting on `Name1 &, Name2`...
2024-08-29 07:48:18 +09:00
e165e64952 chore(i18n): Translated using Weblate (Hungarian)
Currently translated at 93.7% (358 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hu/
2024-08-28 13:09:22 +00:00
f380822e11 chore(deps): update dependency @babel/runtime to v7.25.4 (#2373)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 12:22:29 +09:00
6b1995145a synced-lyrics: make the lyrics search more reliable (#2343)
* fix: comparing multiple artists on a single track

* fix: get song info on startup

* chore: also split on commas

* chore: re-apply .toLowerCase() on the artist names

* chore: remove redundant code

* chore: attempt at improving the initial videodata

* oops

* eureka!

* stuff
2024-08-28 12:21:58 +09:00
9317e99f43 fix(deps): update dependency solid-js to v1.8.22 (#2354)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 12:20:37 +09:00
66d05d8683 chore(deps): update typescript-eslint monorepo to v8.3.0 (#2350)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 12:20:26 +09:00
545a3a4bb6 fix(deps): update dependency electron-debug to v4.0.1 (#2349)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 12:20:07 +09:00
04a6d16dbe chore(deps): update dependency electron to v31.4.0 (#2356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 12:19:53 +09:00
3c36477b1e fix: hide native-controls on linux when in-app-menu is used (#2366) 2024-08-28 12:19:30 +09:00
c5c191492e fix: detect the upgrade btn using the icon (#2364) 2024-08-23 07:13:55 +09:00
b12e2f607c chore(i18n): Translated using Weblate (Filipino)
Currently translated at 86.6% (331 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fil/
2024-08-20 03:09:10 +00:00
1d77ad6de4 fix: exclude build-id files from rpm (#2361) 2024-08-19 07:46:05 +09:00
25bd26d7f3 chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-17 12:09:10 +02:00
d11d0abe73 chore(i18n): Translated using Weblate (Japanese)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ja/
2024-08-17 12:09:10 +02:00
8a643c465d chore(i18n): Translated using Weblate (Estonian)
Currently translated at 18.8% (72 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/et/
2024-08-15 22:09:31 +00:00
233673b8d8 chore(i18n): Translated using Weblate (Estonian)
Currently translated at 14.1% (54 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/et/
2024-08-13 21:09:13 +02:00
5a448fab31 chore(i18n): Translated using Weblate (Catalan)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ca/
2024-08-13 21:09:12 +02:00
42e8262cda fix(deps): update dependency i18next to v23.12.3 (#2352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-13 11:57:27 +09:00
f64769b1d3 fix(deps): update dependency @floating-ui/dom to v1.6.10 (#2340)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 12:12:08 +09:00
e12998761b fix(deps): update dependency electron-updater to v6.3.3 (#2347)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 12:11:55 +09:00
2e20fa83b8 chore(i18n): Translated using Weblate (German)
Currently translated at 99.2% (379 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-08-11 10:09:24 +00:00
5149757af3 chore(i18n): Translated using Weblate (German)
Currently translated at 99.2% (379 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-08-11 10:09:24 +00:00
655741f108 chore(i18n): Translated using Weblate (German)
Currently translated at 96.3% (368 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-08-10 11:41:12 +02:00
4e58571ad0 chore(i18n): Translated using Weblate (German)
Currently translated at 96.3% (368 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-08-10 11:41:12 +02:00
1e4a615b47 chore(i18n): Translated using Weblate (German)
Currently translated at 94.7% (362 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-08-10 11:39:20 +02:00
dedcf0c9ff fix(deps): update dependency solid-js to v1.8.20 (#2345)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-10 10:58:28 +09:00
a84a7d236a chore(deps): update dependency vite to v5.4.0 (#2342)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-10 10:54:05 +09:00
e56b4b21f0 chore(i18n): Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/
2024-08-09 16:09:15 +02:00
361f9e42bd chore(i18n): Translated using Weblate (Malay)
Currently translated at 19.6% (75 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ms/
2024-08-09 16:09:13 +02:00
918736d2ca chore(i18n): Translated using Weblate (German)
Currently translated at 94.2% (360 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2024-08-09 16:09:12 +02:00
8f3d5b08ac chore(i18n): Translated using Weblate (Russian)
Currently translated at 97.3% (372 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-08-08 00:09:19 +02:00
4ca327d801 chore(deps): update typescript-eslint monorepo to v8.0.1 (#2335)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 23:03:13 +09:00
8d0aa057ad fix(deps): update dependency @floating-ui/dom to v1.6.9 (#2337)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 23:02:23 +09:00
b7ffee089b chore(deps): update playwright monorepo to v1.46.0 (#2336)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-07 23:02:12 +09:00
d72b994f66 chore(README): Translation README to Russian and adding Synced Lyrics to main README (#2338)
* Translation of README.md to Russian and adding Synced Lyrics to default README.md

* Syntax fixes

* Sorting of Synced Lyrics Alphabetically
2024-08-07 23:01:49 +09:00
e6dafdb068 chore(i18n): Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/
2024-08-06 11:09:21 +02:00
14886dd4bd chore(i18n): Translated using Weblate (Catalan)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ca/
2024-08-06 11:09:17 +02:00
c9f2f88bac chore(i18n): Translated using Weblate (Russian)
Currently translated at 97.3% (372 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-08-06 11:09:17 +02:00
1eabbc0bbe chore(i18n): Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hans/
2024-08-05 09:09:19 +02:00
32a572b35a fix(downloader): fix playabilityStatus 2024-08-04 16:33:28 +09:00
59a5679cbb fix(cache): use cacheNoArgs for better performance 2024-08-04 16:31:07 +09:00
ac51f798c3 fix(synced-lyric): fix album_name 2024-08-04 15:49:30 +09:00
7599cc694a Revert "fix(MPRIS): Prevents player to start with invalid MPRIS interface (#1996)"
This reverts commit eaf9d310aa.

Fix #2225
2024-08-04 15:26:14 +09:00
53595654b1 chore(adblocker): add comment 2024-08-04 14:50:14 +09:00
7656c41dbc fix(adblocker/inplayer): fix Response.prototype.json
fix #2310
2024-08-04 14:36:10 +09:00
ff0c5b87c9 chore(i18n): Translated using Weblate (Estonian)
Currently translated at 2.8% (11 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/et/
2024-08-03 22:09:19 +00:00
506c95740a chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 99.4% (380 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2024-08-03 22:09:18 +00:00
575a42e28a chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2024-08-03 22:09:17 +00:00
dcdc6a825f chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-03 22:09:16 +00:00
0a41bb1cd6 chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-03 22:09:16 +00:00
72a4736dc9 chore(i18n): Translated using Weblate (Greek)
Currently translated at 47.3% (181 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/el/
2024-08-03 22:09:15 +00:00
f2b1e6b6bf chore(deps): update dependency rollup to v4.20.0 (#2326)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-03 18:47:56 +09:00
bc0e28ad6d chore(i18n): Added translation using Weblate (Estonian) 2024-08-02 23:59:14 +02:00
8ebae91c02 chore(i18n): Translated using Weblate (Hungarian)
Currently translated at 93.7% (358 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hu/
2024-08-02 23:59:13 +02:00
954ad90733 chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-02 23:59:13 +02:00
5af0643788 chore(i18n): Translated using Weblate (French)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fr/
2024-08-02 23:59:13 +02:00
be633ac1f2 chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 99.7% (381 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-02 21:58:41 +02:00
0d047c1fd5 chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 99.7% (381 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-02 21:58:41 +02:00
e8b1aca629 chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2024-08-02 21:58:41 +02:00
5b9bacf390 chore(i18n): Translated using Weblate (Filipino)
Currently translated at 85.3% (326 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fil/
2024-08-02 14:09:23 +02:00
ccd16f4a5f chore(i18n): Translated using Weblate (Chinese (Traditional))
Currently translated at 93.4% (357 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-08-02 14:09:22 +02:00
02e519dab3 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2024-08-02 14:09:21 +02:00
473ea78f12 synced-lyrics: fix album name? 2024-08-01 15:46:53 +03:00
e7f366b770 Update changelog for v3.5.1 2024-08-01 11:49:06 +00:00
66816ac42d Bump version to 3.5.1 2024-08-01 20:39:44 +09:00
08b985f2ab chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (382 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2024-08-01 13:38:36 +02:00
747bde2136 fix(synced-lyrics): fix lyric load
fix #2295
2024-08-01 20:19:08 +09:00
eabc28b39f fix(wait-for-element): add 100ms timeout for improve performance 2024-08-01 20:19:08 +09:00
3537dc19ee chore(i18n): Translated using Weblate (Hungarian)
Currently translated at 97.8% (358 of 366 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hu/
2024-08-01 10:57:05 +00:00
6afeb60557 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (366 of 366 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2024-08-01 10:57:04 +00:00
71115dedee chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (366 of 366 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2024-08-01 10:57:04 +00:00
8750b54f76 fix(synced-lyrics): fix i18n 2024-08-01 19:56:32 +09:00
482a1c5073 fix(deps): update dependency youtubei.js to v10.3.0 (#2306)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-01 19:27:58 +09:00
c8d516c40b fix: Window gets stuck offscreen in some instances (#2303)
Improved offscreen detection logic, fixes th-ch#1894
2024-08-01 19:27:01 +09:00
c1ad168c32 fix: Incorrect window size on multi-monitor scaled displays (#2302)
see discussion on th-ch#2258
2024-08-01 19:26:37 +09:00
5f5be5d02f chore(deps): update dependency rollup to v4.19.2 (#2304)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-01 19:25:59 +09:00
61ef56dccc chore: enable sourcemaps in dev 2024-08-01 11:02:21 +03:00
a73b5acc75 chore(deps): update typescript-eslint monorepo to v8 (major) (#2297)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-01 16:37:08 +09:00
877573532c ts-fix: disambiguate ElectronStore typings 2024-08-01 10:10:52 +03:00
7b033b5caf fix(ambient-mode): fix ambient-mode not working for videos after restart (#2294)
* Fix Ambient Mode not working for videos after restart (#2255)

This should fix https://github.com/th-ch/youtube-music/issues/1641

* fix: fix waitForElement

---------

Co-authored-by: craftgeil <80261988+craftgeil@users.noreply.github.com>
2024-07-31 22:08:45 +09:00
8924ec29d3 fix(deps): update dependency @xhayper/discord-rpc to v1.2.0 (#2291)
* fix(deps): update dependency @xhayper/discord-rpc to v1.2.0

* fix: discord-rpc

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: JellyBrick <shlee1503@naver.com>
2024-07-31 21:57:37 +09:00
23e688aaf8 Update changelog for v3.5.0 2024-07-31 12:04:22 +00:00
204 changed files with 14930 additions and 4393 deletions

View File

@ -1 +0,0 @@
.eslintrc.js

View File

@ -1,80 +0,0 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
plugins: ['prettier', '@typescript-eslint', 'import'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
ecmaVersion: 'latest'
},
rules: {
'arrow-parens': ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': ['off', { checksVoidReturn: false }],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
"@typescript-eslint/no-non-null-assertion": "off",
'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-default-export': 'off',
'import/no-duplicates': 'error',
'import/no-unresolved': ['error', { ignore: ['^virtual:', '\\?inline$', '\\?raw$', '\\?asset&asarUnpack'] }],
'import/order': [
'error',
{
'groups': ['builtin', 'external', ['internal', 'index', 'sibling'], 'parent', 'type'],
'newlines-between': 'always-and-inside-groups',
'alphabetize': {order: 'ignore', caseInsensitive: false}
}
],
'import/prefer-default-export': 'off',
'camelcase': ['error', {properties: 'never'}],
'class-methods-use-this': 'off',
'lines-around-comment': [
'error',
{
beforeBlockComment: false,
afterBlockComment: false,
beforeLineComment: false,
afterLineComment: false,
},
],
'max-len': 'off',
'no-mixed-operators': 'error',
'no-multi-spaces': ['error', {ignoreEOLComments: true}],
'no-tabs': 'error',
'no-void': 'error',
'no-empty': 'off',
'prefer-promise-reject-errors': 'off',
'quotes': ['error', 'single', {
avoidEscape: true,
allowTemplateLiterals: false,
}],
'quote-props': ['error', 'consistent'],
'semi': ['error', 'always'],
},
env: {
browser: true,
node: true,
es6: true,
},
ignorePatterns: ['dist', 'node_modules'],
root: true,
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts']
},
'import/resolver': {
typescript: {},
exports: {},
},
},
};

View File

@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false
@ -62,6 +62,12 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sudo snap install snapcraft --classic
sudo apt update
sudo apt install -y flatpak flatpak-builder
sudo flatpak remote-add --if-not-exists --system flathub https://flathub.org/repo/flathub.flatpakrepo
sudo flatpak install -y flathub org.freedesktop.Platform/x86_64/24.08
sudo flatpak install -y flathub org.freedesktop.Sdk/x86_64/24.08
sudo flatpak install -y flathub org.electronjs.Electron2.BaseApp/x86_64/24.08
pnpm release:linux
- name: Build and release on Windows
@ -90,7 +96,7 @@ jobs:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false

View File

@ -4,7 +4,7 @@
[![GitHub release](https://img.shields.io/github/release/th-ch/youtube-music.svg?style=for-the-badge&logo=youtube-music)](https://github.com/th-ch/youtube-music/releases/)
[![GitHub license](https://img.shields.io/github/license/th-ch/youtube-music.svg?style=for-the-badge)](https://github.com/th-ch/youtube-music/blob/master/LICENSE)
[![eslint code style](https://img.shields.io/badge/code_style-eslint-5ed9c7.svg?style=for-the-badge)](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
[![eslint code style](https://img.shields.io/badge/code_style-eslint-5ed9c7.svg?style=for-the-badge)](https://github.com/th-ch/youtube-music/blob/master/eslint.config.mjs)
[![Build status](https://img.shields.io/github/actions/workflow/status/th-ch/youtube-music/build.yml?branch=master&style=for-the-badge&logo=youtube-music)](https://GitHub.com/th-ch/youtube-music/releases/)
[![GitHub All Releases](https://img.shields.io/github/downloads/th-ch/youtube-music/total?style=for-the-badge&logo=youtube-music)](https://GitHub.com/th-ch/youtube-music/releases/)
[![AUR](https://img.shields.io/aur/version/youtube-music-bin?color=blueviolet&style=for-the-badge&logo=youtube-music)](https://aur.archlinux.org/packages/youtube-music-bin)
@ -12,7 +12,7 @@
</div>
![Screenshot](web/screenshot.jpg "Screenshot")
![Screenshot](web/screenshot.png "Screenshot")
<div align="center">
@ -21,7 +21,7 @@
</a>
</div>
Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸](./docs/readme/README-is.md), [🇨🇱 🇪🇸](./docs/readme/README-es.md)
Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸](./docs/readme/README-is.md), [🇨🇱 🇪🇸](./docs/readme/README-es.md), [🇷🇺](./docs/readme/README-ru.md)
**Electron wrapper around YouTube Music featuring:**
@ -95,6 +95,8 @@ Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸]
- **Downloader**: downloads
MP3 [directly from the interface](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
- **Equalizer**: add filters to boost or cut specific range of frequencies (e.g. bass booster)
- **Exponential Volume**: Makes the volume
slider [exponential](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) so it's easier to
select lower volumes
@ -141,6 +143,8 @@ Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸]
- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Automatically Skips non-music parts like intro/outro or
parts of music videos where the song isn't playing
- **Synced Lyrics**: Provides synced lyrics to songs, using providers like [LRClib](https://lrclib.net).
- **Taskbar Media Control**: Control playback from
your [Windows taskbar](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
@ -159,6 +163,7 @@ Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸]
- **Visualizer**: Different music visualizers
## Translation
You can help with translation on [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
@ -189,7 +194,7 @@ brew install th-ch/youtube-music/youtube-music
If you install the app manually and get an error "is damaged and cant be opened." when launching the app, run the following in the Terminal:
```bash
xattr -cr /Applications/YouTube\ Music.app
/usr/bin/xattr -cr /Applications/YouTube\ Music.app
```
### Windows

View File

@ -2,8 +2,350 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v3.7.0](https://github.com/th-ch/youtube-music/compare/v3.6.2...v3.7.0)
- feat(amuse): song query api (add amuse plugin) [`#2723`](https://github.com/th-ch/youtube-music/pull/2723)
- feat(api-server): add absolute seek endpoint [`#2748`](https://github.com/th-ch/youtube-music/pull/2748)
- feat(api-server): Add repeat mode and seek time API [`#2630`](https://github.com/th-ch/youtube-music/pull/2630)
- feat(synced-lyrics): Better-Lyrics Styling for Synced-Lyrics [`#2554`](https://github.com/th-ch/youtube-music/pull/2554)
- feat(synced-lyrics): multiple lyric sources [`#2383`](https://github.com/th-ch/youtube-music/pull/2383)
- chore(deps): update dependency typescript-eslint to v8.18.2 [`#2763`](https://github.com/th-ch/youtube-music/pull/2763)
- chore(deps): update dependency discord-api-types to v0.37.114 [`#2761`](https://github.com/th-ch/youtube-music/pull/2761)
- chore(deps): update dependency discord-api-types to v0.37.113 [`#2759`](https://github.com/th-ch/youtube-music/pull/2759)
- fix: Set correct window class for X11 and Wayland [`#2758`](https://github.com/th-ch/youtube-music/pull/2758)
- feat: Specify flatpak runtime [`#2755`](https://github.com/th-ch/youtube-music/pull/2755)
- chore(deps): update dependency rollup to v4.29.1 [`#2749`](https://github.com/th-ch/youtube-music/pull/2749)
- chore(deps): update dependency esbuild to v0.24.2 [`#2742`](https://github.com/th-ch/youtube-music/pull/2742)
- fix: Add Flatpak permissions needed for MPRIS and tray icon [`#2754`](https://github.com/th-ch/youtube-music/pull/2754)
- chore(deps): update dependency vite-plugin-inspect to v0.10.6 [`#2756`](https://github.com/th-ch/youtube-music/pull/2756)
- chore(deps): update dependency vite to v6.0.5 [`#2745`](https://github.com/th-ch/youtube-music/pull/2745)
- fix(deps): update dependency i18next to v24.2.0 [`#2744`](https://github.com/th-ch/youtube-music/pull/2744)
- chore(deps): update dependency vite-plugin-inspect to v0.10.4 [`#2743`](https://github.com/th-ch/youtube-music/pull/2743)
- chore(deps): update dependency discord-api-types to v0.37.112 [`#2740`](https://github.com/th-ch/youtube-music/pull/2740)
- fix(discord): Fix Album Art failing on Discord RPC [`#2666`](https://github.com/th-ch/youtube-music/pull/2666)
- feat: Add equalizer plugin with presets (e.g. bass booster) [`#2575`](https://github.com/th-ch/youtube-music/pull/2575)
- chore(deps): update dependency vite to v6.0.4 [`#2738`](https://github.com/th-ch/youtube-music/pull/2738)
- fix: Fixed #1796 [`#2736`](https://github.com/th-ch/youtube-music/pull/2736)
- chore(deps): update dependency electron-devtools-installer to v4 [`#2734`](https://github.com/th-ch/youtube-music/pull/2734)
- Revert "chore(deps): update dependency electron-builder to v25" [`#2732`](https://github.com/th-ch/youtube-music/pull/2732)
- chore(deps): update dependency electron-builder to v25 [`#2490`](https://github.com/th-ch/youtube-music/pull/2490)
- fix(deps): update dependency i18next to v24.1.2 [`#2727`](https://github.com/th-ch/youtube-music/pull/2727)
- chore(deps): update dependency electron-devtools-installer to v3.2.1 [`#2731`](https://github.com/th-ch/youtube-music/pull/2731)
- chore(deps): update dependency typescript-eslint to v8.18.1 [`#2724`](https://github.com/th-ch/youtube-music/pull/2724)
- fix: tab misalignment [`#2713`](https://github.com/th-ch/youtube-music/pull/2713)
- fix(deps): update dependency @hono/zod-validator to v0.4.2 [`#2709`](https://github.com/th-ch/youtube-music/pull/2709)
- chore(deps): update eslint monorepo to v9.17.0 [`#2712`](https://github.com/th-ch/youtube-music/pull/2712)
- fix(deps): update dependency hono to v4.6.14 [`#2716`](https://github.com/th-ch/youtube-music/pull/2716)
- fix: discord rich presence connection status [`#2714`](https://github.com/th-ch/youtube-music/pull/2714)
- fix: Laggy scrolling behaviour in large playlists [`#2708`](https://github.com/th-ch/youtube-music/pull/2708)
- fix(deps): update dependency youtubei.js to v12.2.0 [`#2705`](https://github.com/th-ch/youtube-music/pull/2705)
- fix(deps): update dependency i18next to v24.1.0 [`#2698`](https://github.com/th-ch/youtube-music/pull/2698)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.12.1 [`#2697`](https://github.com/th-ch/youtube-music/pull/2697)
- fix(deps): update dependency zod to v3.24.1 [`#2694`](https://github.com/th-ch/youtube-music/pull/2694)
- fix(deps): update dependency youtubei.js to v12.1.0 [`#2695`](https://github.com/th-ch/youtube-music/pull/2695)
- chore(deps): update dependency discord-api-types to v0.37.111 [`#2690`](https://github.com/th-ch/youtube-music/pull/2690)
- chore(deps): update dependency typescript-eslint to v8.18.0 [`#2692`](https://github.com/th-ch/youtube-music/pull/2692)
- chore(deps): update playwright monorepo to v1.49.1 [`#2693`](https://github.com/th-ch/youtube-music/pull/2693)
- fix(deps): update dependency hono to v4.6.13 [`#2682`](https://github.com/th-ch/youtube-music/pull/2682)
- chore(deps): update dependency rollup to v4.28.1 [`#2683`](https://github.com/th-ch/youtube-music/pull/2683)
- fix(deps): update dependency conf to v13.1.0 [`#2686`](https://github.com/th-ch/youtube-music/pull/2686)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.12.0 [`#2689`](https://github.com/th-ch/youtube-music/pull/2689)
- fix(deps): update dependency youtubei.js to v12 [`#2681`](https://github.com/th-ch/youtube-music/pull/2681)
- chore(deps): update dependency vite to v6.0.3 [`#2680`](https://github.com/th-ch/youtube-music/pull/2680)
- fix(album-actions): Fixed #2312 [`#2676`](https://github.com/th-ch/youtube-music/pull/2676)
- chore(deps): update dependency eslint-import-resolver-typescript to v3.7.0 [`#2672`](https://github.com/th-ch/youtube-music/pull/2672)
- chore(deps): update dependency node-gyp to v11 [`#2678`](https://github.com/th-ch/youtube-music/pull/2678)
- fix(deps): update dependency i18next to v24.0.5 [`#2669`](https://github.com/th-ch/youtube-music/pull/2669)
- fix(deps): update dependency i18next to v24.0.4 [`#2668`](https://github.com/th-ch/youtube-music/pull/2668)
- chore(deps): update dependency vite to v6.0.2 [`#2662`](https://github.com/th-ch/youtube-music/pull/2662)
- chore(deps): update dependency node-gyp to v10.3.1 [`#2665`](https://github.com/th-ch/youtube-music/pull/2665)
- chore(deps): update dependency typescript-eslint to v8.17.0 [`#2664`](https://github.com/th-ch/youtube-music/pull/2664)
- chore(deps): update dependency vite-plugin-inspect to v0.10.3 [`#2667`](https://github.com/th-ch/youtube-music/pull/2667)
- chore(deps): update dependency rollup to v4.28.0 [`#2661`](https://github.com/th-ch/youtube-music/pull/2661)
- chore(deps): update dependency discord-api-types to v0.37.110 [`#2653`](https://github.com/th-ch/youtube-music/pull/2653)
- fix(deps): update dependency @hono/zod-openapi to v0.18.3 [`#2654`](https://github.com/th-ch/youtube-music/pull/2654)
- chore(deps): update eslint monorepo to v9.16.0 [`#2656`](https://github.com/th-ch/youtube-music/pull/2656)
- chore(deps): update dependency vite-plugin-inspect to v0.10.2 [`#2657`](https://github.com/th-ch/youtube-music/pull/2657)
- fix(youtube-music.css): Fixed #2514 [`#2659`](https://github.com/th-ch/youtube-music/pull/2659)
- fix: Fixed Skip Disliked Song not working [`#2651`](https://github.com/th-ch/youtube-music/pull/2651)
- fix(deps): update dependency @hono/zod-openapi to v0.18.2 [`#2650`](https://github.com/th-ch/youtube-music/pull/2650)
- chore(deps): update dependency vite-plugin-inspect to v0.10.1 [`#2652`](https://github.com/th-ch/youtube-music/pull/2652)
- chore(deps): update dependency electron to v33.2.1 [`#2649`](https://github.com/th-ch/youtube-music/pull/2649)
- chore(deps): update dependency vite-plugin-inspect to v0.10.0 [`#2646`](https://github.com/th-ch/youtube-music/pull/2646)
- chore(deps): update dependency vite to v6 [`#2644`](https://github.com/th-ch/youtube-music/pull/2644)
- fix(deps): update dependency @hono/swagger-ui to v0.5.0 [`#2643`](https://github.com/th-ch/youtube-music/pull/2643)
- chore(deps): update dependency discord-api-types to v0.37.109 [`#2642`](https://github.com/th-ch/youtube-music/pull/2642)
- chore(deps): update dependency vite-plugin-solid to v2.11.0 [`#2641`](https://github.com/th-ch/youtube-music/pull/2641)
- fix(deps): update dependency hono to v4.6.12 [`#2636`](https://github.com/th-ch/youtube-music/pull/2636)
- fix(deps): update dependency i18next to v24.0.2 [`#2637`](https://github.com/th-ch/youtube-music/pull/2637)
- chore(deps): update dependency discord-api-types to v0.37.108 [`#2638`](https://github.com/th-ch/youtube-music/pull/2638)
- chore(deps): update dependency typescript-eslint to v8.16.0 [`#2639`](https://github.com/th-ch/youtube-music/pull/2639)
- chore(deps): update dependency rollup to v4.27.4 [`#2632`](https://github.com/th-ch/youtube-music/pull/2632)
- fix(deps): update dependency i18next to v24 [`#2633`](https://github.com/th-ch/youtube-music/pull/2633)
- chore(deps): update dependency typescript to v5.7.2 [`#2629`](https://github.com/th-ch/youtube-music/pull/2629)
- chore(deps): update dependency discord-api-types to v0.37.107 [`#2627`](https://github.com/th-ch/youtube-music/pull/2627)
- fix(deps): update dependency @hono/zod-openapi to v0.18.0 [`#2626`](https://github.com/th-ch/youtube-music/pull/2626)
- fix(deps): update dependency i18next to v23.16.8 [`#2625`](https://github.com/th-ch/youtube-music/pull/2625)
- chore(deps): update dependency vite-plugin-inspect to v0.8.8 [`#2623`](https://github.com/th-ch/youtube-music/pull/2623)
- fix(deps): update dependency hono to v4.6.11 [`#2624`](https://github.com/th-ch/youtube-music/pull/2624)
- chore(deps): update playwright monorepo to v1.49.0 [`#2617`](https://github.com/th-ch/youtube-music/pull/2617)
- chore(deps): update dependency rollup to v4.27.3 [`#2610`](https://github.com/th-ch/youtube-music/pull/2610)
- chore(deps): update dependency typescript-eslint to v8.15.0 [`#2611`](https://github.com/th-ch/youtube-music/pull/2611)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.11.0 [`#2618`](https://github.com/th-ch/youtube-music/pull/2618)
- chore(deps): update dependency discord-api-types to v0.37.105 [`#2603`](https://github.com/th-ch/youtube-music/pull/2603)
- chore(deps): update dependency rollup to v4.27.2 [`#2604`](https://github.com/th-ch/youtube-music/pull/2604)
- chore(deps): update eslint monorepo to v9.15.0 [`#2607`](https://github.com/th-ch/youtube-music/pull/2607)
- fix(deps): update dependency @hono/zod-openapi to v0.17.1 [`#2608`](https://github.com/th-ch/youtube-music/pull/2608)
- fix(ambient-mode): fix ambient-mode overlapping other elements [`#2609`](https://github.com/th-ch/youtube-music/pull/2609)
- fix: Allow media playback control (MPRIS) for flatpak [`#2606`](https://github.com/th-ch/youtube-music/pull/2606)
- fix(deps): update dependency @hono/node-server to v1.13.7 [`#2598`](https://github.com/th-ch/youtube-music/pull/2598)
- chore(deps): update dependency rollup to v4.26.0 [`#2600`](https://github.com/th-ch/youtube-music/pull/2600)
- fix(deps): update dependency hono to v4.6.10 [`#2601`](https://github.com/th-ch/youtube-music/pull/2601)
- fix(deps): update dependency @hono/node-server to v1.13.6 [`#2594`](https://github.com/th-ch/youtube-music/pull/2594)
- chore(deps): update dependency vite to v5.4.11 [`#2595`](https://github.com/th-ch/youtube-music/pull/2595)
- chore(deps): update dependency typescript-eslint to v8.14.0 [`#2596`](https://github.com/th-ch/youtube-music/pull/2596)
- chore(deps): update dependency electron to v33.2.0 [`#2591`](https://github.com/th-ch/youtube-music/pull/2591)
- fix(deps): update dependency @hono/zod-openapi to v0.17.0 [`#2592`](https://github.com/th-ch/youtube-music/pull/2592)
- fix(deps): update dependency i18next to v23.16.5 [`#2589`](https://github.com/th-ch/youtube-music/pull/2589)
- fix(deps): update dependency @hono/node-server to v1.13.5 [`#2578`](https://github.com/th-ch/youtube-music/pull/2578)
- fix(deps): update dependency hono to v4.6.9 [`#2579`](https://github.com/th-ch/youtube-music/pull/2579)
- chore(deps): update dependency discord-api-types to v0.37.104 [`#2588`](https://github.com/th-ch/youtube-music/pull/2588)
- chore(deps): update dependency typescript-eslint to v8.13.0 [`#2581`](https://github.com/th-ch/youtube-music/pull/2581)
- chore(deps): update dependency rollup to v4.25.0 [`#2580`](https://github.com/th-ch/youtube-music/pull/2580)
- chore(docs): Update screenshot [`#2587`](https://github.com/th-ch/youtube-music/pull/2587)
- chore(docs): Specify full path to xattr for macOS, fixes #2583 [`#2586`](https://github.com/th-ch/youtube-music/pull/2586)
- fix: callback for time-changed event [`#2577`](https://github.com/th-ch/youtube-music/pull/2577)
- chore(deps): update eslint monorepo to v9.14.0 [`#2573`](https://github.com/th-ch/youtube-music/pull/2573)
- chore(deps): update dependency utf-8-validate to v6.0.5 [`#2572`](https://github.com/th-ch/youtube-music/pull/2572)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.10.1 [`#2571`](https://github.com/th-ch/youtube-music/pull/2571)
- fix(deps): update dependency @hono/node-server to v1.13.4 [`#2570`](https://github.com/th-ch/youtube-music/pull/2570)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.10.0 [`#2569`](https://github.com/th-ch/youtube-music/pull/2569)
- fix(deps): update dependency @floating-ui/dom to v1.6.12 [`#2568`](https://github.com/th-ch/youtube-music/pull/2568)
- chore(deps): update dependency rollup to v4.24.3 [`#2565`](https://github.com/th-ch/youtube-music/pull/2565)
- fix(deps): update dependency hono to v4.6.8 [`#2564`](https://github.com/th-ch/youtube-music/pull/2564)
- chore(deps): update dependency typescript-eslint to v8.12.2 [`#2563`](https://github.com/th-ch/youtube-music/pull/2563)
- chore(deps): update dependency typescript-eslint to v8.12.0 [`#2561`](https://github.com/th-ch/youtube-music/pull/2561)
- fix(deps): update dependency youtubei.js to v11 [`#2562`](https://github.com/th-ch/youtube-music/pull/2562)
- chore(deps): update dependency rollup to v4.24.2 [`#2559`](https://github.com/th-ch/youtube-music/pull/2559)
- fix(deps): update dependency @hono/node-server to v1.13.3 [`#2560`](https://github.com/th-ch/youtube-music/pull/2560)
- fix(deps): update dependency i18next to v23.16.4 [`#2550`](https://github.com/th-ch/youtube-music/pull/2550)
- chore(deps): update playwright monorepo to v1.48.2 [`#2551`](https://github.com/th-ch/youtube-music/pull/2551)
- fix(deps): update dependency hono to v4.6.7 [`#2552`](https://github.com/th-ch/youtube-music/pull/2552)
- chore(deps): update dependency @babel/runtime to v7.26.0 [`#2548`](https://github.com/th-ch/youtube-music/pull/2548)
- chore(deps): update dependency @types/color to v4 [`#2547`](https://github.com/th-ch/youtube-music/pull/2547)
- fix(deps): update dependency i18next to v23.16.3 [`#2545`](https://github.com/th-ch/youtube-music/pull/2545)
- fix(deps): update dependency solid-js to v1.9.3 [`#2541`](https://github.com/th-ch/youtube-music/pull/2541)
- chore(deps): update dependency vite to v5.4.10 [`#2542`](https://github.com/th-ch/youtube-music/pull/2542)
- chore(deps): update dependency electron to v33.0.2 [`#2537`](https://github.com/th-ch/youtube-music/pull/2537)
- chore(deps): update dependency @babel/runtime to v7.25.9 [`#2538`](https://github.com/th-ch/youtube-music/pull/2538)
- chore(deps): update dependency discord-api-types to v0.37.103 [`#2532`](https://github.com/th-ch/youtube-music/pull/2532)
- chore(deps): update dependency typescript-eslint to v8.11.0 [`#2534`](https://github.com/th-ch/youtube-music/pull/2534)
- fix(deps): update dependency hono to v4.6.6 [`#2536`](https://github.com/th-ch/youtube-music/pull/2536)
- fix(tuna-obs): Added song url to tuna-obs plugin [`#2524`](https://github.com/th-ch/youtube-music/pull/2524)
- fix(deps): update dependency i18next to v23.16.2 [`#2530`](https://github.com/th-ch/youtube-music/pull/2530)
- fix(deps): update dependency i18next to v23.16.1 [`#2529`](https://github.com/th-ch/youtube-music/pull/2529)
- chore(deps): update eslint monorepo to v9.13.0 [`#2528`](https://github.com/th-ch/youtube-music/pull/2528)
- chore(deps): update dependency typescript-eslint to v8.10.0 [`#2527`](https://github.com/th-ch/youtube-music/pull/2527)
- chore(deps): update playwright monorepo to v1.48.1 [`#2516`](https://github.com/th-ch/youtube-music/pull/2516)
- chore(deps): update dependency electron to v33.0.1 [`#2523`](https://github.com/th-ch/youtube-music/pull/2523)
- fix: disable gpu memory buffer video frames [`#2519`](https://github.com/th-ch/youtube-music/pull/2519)
- fix: use HEAD instead of GET in songInfo.imageSrc validation step [`#2766`](https://github.com/th-ch/youtube-music/issues/2766)
- fix: Fixed #1796 (#2736) [`#1796`](https://github.com/th-ch/youtube-music/issues/1796)
- fix(album-actions): Fixed #2312 (#2676) [`#2312`](https://github.com/th-ch/youtube-music/issues/2312) [`#2312`](https://github.com/th-ch/youtube-music/issues/2312)
- fix(youtube-music.css): Fixed #2514 (#2659) [`#2514`](https://github.com/th-ch/youtube-music/issues/2514)
- chore(docs): Specify full path to xattr for macOS, fixes #2583 (#2586) [`#2583`](https://github.com/th-ch/youtube-music/issues/2583)
- fix: fix pnpm-lock.yaml [`3208bf4`](https://github.com/th-ch/youtube-music/commit/3208bf4a6d47d824875b06bd031299694482f02d)
- Revert "feat: use swc and lightningcss" [`3b50cbc`](https://github.com/th-ch/youtube-music/commit/3b50cbcb6e3163115d52f05075af5d6f25b80660)
- feat: use swc and lightningcss [`ae3a289`](https://github.com/th-ch/youtube-music/commit/ae3a28900576ea388666747bc4794577e1d57e23)
#### [v3.6.2](https://github.com/th-ch/youtube-music/compare/v3.6.1...v3.6.2)
> 16 October 2024
- fix(deps): update dependency serve to v14.2.4 [`#2515`](https://github.com/th-ch/youtube-music/pull/2515)
- fix(deps): update dependency hono to v4.6.5 [`#2509`](https://github.com/th-ch/youtube-music/pull/2509)
- chore(deps): update dependency vite to v5.4.9 [`#2500`](https://github.com/th-ch/youtube-music/pull/2500)
- fix(api-server): properly implement next api call [`#2505`](https://github.com/th-ch/youtube-music/pull/2505)
- chore(deps): update dependency electron to v33 [`#2507`](https://github.com/th-ch/youtube-music/pull/2507)
- chore(deps): update dependency typescript-eslint to v8.9.0 [`#2503`](https://github.com/th-ch/youtube-music/pull/2503)
- chore(deps): update dependency discord-api-types to v0.37.102 [`#2501`](https://github.com/th-ch/youtube-music/pull/2501)
- fix: trustedTypes issue [`#2339`](https://github.com/th-ch/youtube-music/issues/2339)
- chore(i18n): Translated using Weblate (Icelandic) [`5f79b7e`](https://github.com/th-ch/youtube-music/commit/5f79b7e788c47b0a27a4967c9f3a9e20b483cd75)
- chore(i18n): Translated using Weblate (Chinese (Traditional Han script)) [`12d6939`](https://github.com/th-ch/youtube-music/commit/12d693921e26a5c54015673a404e005d1a7175a4)
- chore(i18n): Translated using Weblate (Ukrainian) [`836cedb`](https://github.com/th-ch/youtube-music/commit/836cedb0f317b74bf2fc3ec2d1aa865719f46ec0)
#### [v3.6.1](https://github.com/th-ch/youtube-music/compare/v3.6.0...v3.6.1)
> 14 October 2024
- fix(api-server): Various fixes and improvements [`#2496`](https://github.com/th-ch/youtube-music/pull/2496)
- fix(deps): update dependency electron-debug to v4.1.0 [`#2499`](https://github.com/th-ch/youtube-music/pull/2499)
- fix(renderer): fix force like buttons display logic [`#2493`](https://github.com/th-ch/youtube-music/pull/2493)
- fix(deps): update dependency i18next to v23.16.0 [`#2492`](https://github.com/th-ch/youtube-music/pull/2492)
- fix(downloader): fix #2371 [`#2371`](https://github.com/th-ch/youtube-music/issues/2371)
- fix(ytm-bugs): incorrect video ratio [`#2459`](https://github.com/th-ch/youtube-music/issues/2459)
- fix(api-server): fix init/authentication error [`#2497`](https://github.com/th-ch/youtube-music/issues/2497)
- fix: RSS feed CORS issue [`#1620`](https://github.com/th-ch/youtube-music/issues/1620)
- chore(flatpak-builder): Add more details when failing [`d3acb49`](https://github.com/th-ch/youtube-music/commit/d3acb4945a8dcde6598c53d8207bbf16eda8c739)
- chore(i18n): Translated using Weblate (Filipino) [`e428708`](https://github.com/th-ch/youtube-music/commit/e4287085a11f30d141148ab0432cc684819fd0d0)
- Bump version to 3.6.1 [`b668730`](https://github.com/th-ch/youtube-music/commit/b6687307dfe7ef765517019093c8db3c2ad14417)
#### [v3.6.0](https://github.com/th-ch/youtube-music/compare/v3.5.3...v3.6.0)
> 13 October 2024
- feat(api-server): remote control api [`#1909`](https://github.com/th-ch/youtube-music/pull/1909)
- chore(deps): update playwright monorepo to v1.48.0 [`#2489`](https://github.com/th-ch/youtube-music/pull/2489)
- fix(`synced-lyrics`): Fix 2 issues [`#2441`](https://github.com/th-ch/youtube-music/pull/2441)
- chore(deps): update dependency typescript to v5.6.3 [`#2486`](https://github.com/th-ch/youtube-music/pull/2486)
- chore(deps): update dependency electron to v32.2.0 [`#2487`](https://github.com/th-ch/youtube-music/pull/2487)
- chore(deps): update dependency del-cli to v6 [`#2475`](https://github.com/th-ch/youtube-music/pull/2475)
- chore(deps): update dependency typescript-eslint to v8.8.1 [`#2477`](https://github.com/th-ch/youtube-music/pull/2477)
- fix(deps): update dependency solid-js to v1.9.2 [`#2480`](https://github.com/th-ch/youtube-music/pull/2480)
- Revert "chore(deps): update dependency electron-builder to v25" [`#2488`](https://github.com/th-ch/youtube-music/pull/2488)
- chore(deps): update dependency electron-builder to v25 [`#2406`](https://github.com/th-ch/youtube-music/pull/2406)
- fix(deps): update dependency deepmerge-ts to v7.1.3 [`#2481`](https://github.com/th-ch/youtube-music/pull/2481)
- fix(deps): update dependency ts-morph to v24 [`#2474`](https://github.com/th-ch/youtube-music/pull/2474)
- fix(deps): update dependency i18next to v23.15.2 [`#2471`](https://github.com/th-ch/youtube-music/pull/2471)
- chore(deps): update eslint monorepo to v9.12.0 [`#2470`](https://github.com/th-ch/youtube-music/pull/2470)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.9.0 [`#2469`](https://github.com/th-ch/youtube-music/pull/2469)
- chore(deps): bump micromatch from 4.0.5 to 4.0.8 [`#2465`](https://github.com/th-ch/youtube-music/pull/2465)
- chore(deps): bump braces from 3.0.2 to 3.0.3 [`#2466`](https://github.com/th-ch/youtube-music/pull/2466)
- fix(deps): update dependency electron-updater to v6.3.9 [`#2468`](https://github.com/th-ch/youtube-music/pull/2468)
- fix(deps): update dependency deepmerge-ts to v7.1.1 [`#2467`](https://github.com/th-ch/youtube-music/pull/2467)
- chore(deps): update dependency typescript-eslint to v8.8.0 [`#2457`](https://github.com/th-ch/youtube-music/pull/2457)
- chore(deps): update dependency @babel/runtime to v7.25.7 [`#2462`](https://github.com/th-ch/youtube-music/pull/2462)
- chore(deps): update dependency rollup to v4.24.0 [`#2458`](https://github.com/th-ch/youtube-music/pull/2458)
- chore(deps): update dependency eslint-plugin-import to v2.31.0 [`#2464`](https://github.com/th-ch/youtube-music/pull/2464)
- chore(deps): update dependency rollup to v4.22.5 [`#2448`](https://github.com/th-ch/youtube-music/pull/2448)
- chore(deps): update dependency typescript-eslint to v8.7.0 [`#2450`](https://github.com/th-ch/youtube-music/pull/2450)
- fix(deps): update dependency solid-js to v1.9.1 [`#2451`](https://github.com/th-ch/youtube-music/pull/2451)
- chore(deps): update dependency vite to v5.4.8 [`#2449`](https://github.com/th-ch/youtube-music/pull/2449)
- chore(deps): update dependency discord-api-types to v0.37.101 [`#2440`](https://github.com/th-ch/youtube-music/pull/2440)
- chore(deps): update dependency esbuild to v0.24.0 [`#2439`](https://github.com/th-ch/youtube-music/pull/2439)
- chore(deps): update eslint monorepo to v9.11.1 [`#2442`](https://github.com/th-ch/youtube-music/pull/2442)
- chore(deps): update dependency @types/howler to v2.2.12 [`#2443`](https://github.com/th-ch/youtube-music/pull/2443)
- chore(deps): update dependency vite to v5.4.7 [`#2434`](https://github.com/th-ch/youtube-music/pull/2434)
- chore(deps): update playwright monorepo to v1.47.2 [`#2436`](https://github.com/th-ch/youtube-music/pull/2436)
- chore(deps): update eslint monorepo to v9.11.0 [`#2437`](https://github.com/th-ch/youtube-music/pull/2437)
- fix(deps): update dependency youtubei.js to v10.5.0 [`#2431`](https://github.com/th-ch/youtube-music/pull/2431)
- chore(deps): update dependency rollup to v4.22.4 [`#2430`](https://github.com/th-ch/youtube-music/pull/2430)
- chore(deps): update dependency electron to v32.1.2 [`#2433`](https://github.com/th-ch/youtube-music/pull/2433)
- feat: ESLint Flat Config (v9 support #2229) [`#2426`](https://github.com/th-ch/youtube-music/pull/2426)
- fix(taskbar-mediacontrol): fix icon color [`#2485`](https://github.com/th-ch/youtube-music/issues/2485)
- chore(eslint): apply eslint-plugin-prettier [`#2438`](https://github.com/th-ch/youtube-music/issues/2438)
- fix: apply fix from eslint [`cb1381b`](https://github.com/th-ch/youtube-music/commit/cb1381bbb394e2bbb404f44817ef96411dabc8a9)
- chore(i18n): Translated using Weblate (Portuguese (Brazil)) [`bcff26c`](https://github.com/th-ch/youtube-music/commit/bcff26c85b18258806f3960309776bc860c3a54e)
- chore(i18n): Translated using Weblate (Persian) [`ead448e`](https://github.com/th-ch/youtube-music/commit/ead448ed98095339557903eb0f84c4a6d0f32058)
#### [v3.5.3](https://github.com/th-ch/youtube-music/compare/v3.5.2...v3.5.3)
> 17 September 2024
- fix: fix `trustedHTML` issue [`#2339`](https://github.com/th-ch/youtube-music/issues/2339)
- chore(deps): update dependency rollup to v4.21.3 [`6edc84a`](https://github.com/th-ch/youtube-music/commit/6edc84a8bd6c7e009041117ba0d2004783eb3a47)
- chore(deps): update typescript-eslint monorepo to v8.6.0 [`d4c8a43`](https://github.com/th-ch/youtube-music/commit/d4c8a4320d733f7bddc4dcd1de93644790e71d66)
- chore(deps): update dependency eslint to v8.57.1 [`02b7a39`](https://github.com/th-ch/youtube-music/commit/02b7a39753528cfd8c0d107d6d2ec6ef78c5afe7)
#### [v3.5.2](https://github.com/th-ch/youtube-music/compare/v3.5.1...v3.5.2)
> 7 September 2024
- chore(deps): update typescript-eslint monorepo to v8.4.0 [`#2401`](https://github.com/th-ch/youtube-music/pull/2401)
- chore(deps): update dependency @total-typescript/ts-reset to v0.6.1 [`#2396`](https://github.com/th-ch/youtube-music/pull/2396)
- chore(deps): update dependency electron to v31.5.0 [`#2397`](https://github.com/th-ch/youtube-music/pull/2397)
- chore(deps): update dependency eslint-import-resolver-typescript to v3.6.3 [`#2376`](https://github.com/th-ch/youtube-music/pull/2376)
- chore(deps): update dependency discord-api-types to v0.37.100 [`#2394`](https://github.com/th-ch/youtube-music/pull/2394)
- fix(deps): update dependency electron-updater to v6.3.4 [`#2395`](https://github.com/th-ch/youtube-music/pull/2395)
- chore(deps): update dependency @babel/runtime to v7.25.6 [`#2388`](https://github.com/th-ch/youtube-music/pull/2388)
- chore(deps): update dependency vite-plugin-inspect to v0.8.7 [`#2389`](https://github.com/th-ch/youtube-music/pull/2389)
- chore(deps): update dependency discord-api-types to v0.37.99 [`#2374`](https://github.com/th-ch/youtube-music/pull/2374)
- chore(deps): update dependency vite to v5.4.3 [`#2377`](https://github.com/th-ch/youtube-music/pull/2377)
- fix: incorrect regex when splitting artistName [`#2378`](https://github.com/th-ch/youtube-music/pull/2378)
- chore(deps): update dependency @babel/runtime to v7.25.4 [`#2373`](https://github.com/th-ch/youtube-music/pull/2373)
- synced-lyrics: make the lyrics search more reliable [`#2343`](https://github.com/th-ch/youtube-music/pull/2343)
- fix(deps): update dependency solid-js to v1.8.22 [`#2354`](https://github.com/th-ch/youtube-music/pull/2354)
- chore(deps): update typescript-eslint monorepo to v8.3.0 [`#2350`](https://github.com/th-ch/youtube-music/pull/2350)
- fix(deps): update dependency electron-debug to v4.0.1 [`#2349`](https://github.com/th-ch/youtube-music/pull/2349)
- chore(deps): update dependency electron to v31.4.0 [`#2356`](https://github.com/th-ch/youtube-music/pull/2356)
- fix: hide native-controls on linux when in-app-menu is used [`#2366`](https://github.com/th-ch/youtube-music/pull/2366)
- fix: detect the upgrade btn using the icon [`#2364`](https://github.com/th-ch/youtube-music/pull/2364)
- fix: exclude build-id files from rpm [`#2361`](https://github.com/th-ch/youtube-music/pull/2361)
- fix(deps): update dependency i18next to v23.12.3 [`#2352`](https://github.com/th-ch/youtube-music/pull/2352)
- fix(deps): update dependency @floating-ui/dom to v1.6.10 [`#2340`](https://github.com/th-ch/youtube-music/pull/2340)
- fix(deps): update dependency electron-updater to v6.3.3 [`#2347`](https://github.com/th-ch/youtube-music/pull/2347)
- fix(deps): update dependency solid-js to v1.8.20 [`#2345`](https://github.com/th-ch/youtube-music/pull/2345)
- chore(deps): update dependency vite to v5.4.0 [`#2342`](https://github.com/th-ch/youtube-music/pull/2342)
- chore(deps): update typescript-eslint monorepo to v8.0.1 [`#2335`](https://github.com/th-ch/youtube-music/pull/2335)
- fix(deps): update dependency @floating-ui/dom to v1.6.9 [`#2337`](https://github.com/th-ch/youtube-music/pull/2337)
- chore(deps): update playwright monorepo to v1.46.0 [`#2336`](https://github.com/th-ch/youtube-music/pull/2336)
- chore(README): Translation README to Russian and adding Synced Lyrics to main README [`#2338`](https://github.com/th-ch/youtube-music/pull/2338)
- chore(deps): update dependency rollup to v4.20.0 [`#2326`](https://github.com/th-ch/youtube-music/pull/2326)
- fix(synced-lyric): fix timestamp [`#2323`](https://github.com/th-ch/youtube-music/issues/2323) [`#2379`](https://github.com/th-ch/youtube-music/issues/2379)
- Revert "fix(MPRIS): Prevents player to start with invalid MPRIS interface (#1996)" [`#2225`](https://github.com/th-ch/youtube-music/issues/2225)
- fix(adblocker/inplayer): fix Response.prototype.json [`#2310`](https://github.com/th-ch/youtube-music/issues/2310)
- chore(deps): update dependency eslint-plugin-import to v2.30.0 [`f48e46d`](https://github.com/th-ch/youtube-music/commit/f48e46d29cf09c76c5172fd56d2d0f705616e4e3)
- Revert "chore(deps): update dependency electron-builder to v25" [`089eff3`](https://github.com/th-ch/youtube-music/commit/089eff3152903c8b55ad3e5571b944062a647e27)
- chore(deps): update dependency electron-builder to v25 [`fe4c89c`](https://github.com/th-ch/youtube-music/commit/fe4c89c349bb9f4f54d95c2018943095ccfdab0c)
#### [v3.5.1](https://github.com/th-ch/youtube-music/compare/v3.5.0...v3.5.1)
> 1 August 2024
- fix(deps): update dependency youtubei.js to v10.3.0 [`#2306`](https://github.com/th-ch/youtube-music/pull/2306)
- fix: Window gets stuck offscreen in some instances [`#2303`](https://github.com/th-ch/youtube-music/pull/2303)
- fix: Incorrect window size on multi-monitor scaled displays [`#2302`](https://github.com/th-ch/youtube-music/pull/2302)
- chore(deps): update dependency rollup to v4.19.2 [`#2304`](https://github.com/th-ch/youtube-music/pull/2304)
- chore(deps): update typescript-eslint monorepo to v8 (major) [`#2297`](https://github.com/th-ch/youtube-music/pull/2297)
- fix(ambient-mode): fix ambient-mode not working for videos after restart [`#2294`](https://github.com/th-ch/youtube-music/pull/2294)
- fix(deps): update dependency @xhayper/discord-rpc to v1.2.0 [`#2291`](https://github.com/th-ch/youtube-music/pull/2291)
- fix(synced-lyrics): fix lyric load [`#2295`](https://github.com/th-ch/youtube-music/issues/2295)
- fix(ambient-mode): fix ambient-mode not working for videos after restart (#2294) [`#1641`](https://github.com/th-ch/youtube-music/issues/1641)
- fix(synced-lyrics): fix i18n [`8750b54`](https://github.com/th-ch/youtube-music/commit/8750b54f766c735ff039c6be454427f17d4737e2)
- ts-fix: disambiguate ElectronStore typings [`8775735`](https://github.com/th-ch/youtube-music/commit/877573532c1b68af861a3fdc44d093f3097d36ab)
- chore(i18n): Translated using Weblate (Hungarian) [`3537dc1`](https://github.com/th-ch/youtube-music/commit/3537dc19eecce7f7deb2478942f70d3c7b72148d)
#### [v3.5.0](https://github.com/th-ch/youtube-music/compare/v3.4.1...v3.5.0)
> 31 July 2024
- plugin: Synced Lyrics [`#2207`](https://github.com/th-ch/youtube-music/pull/2207)
- chore(deps): update dependency electron to v31.3.1 [`#2290`](https://github.com/th-ch/youtube-music/pull/2290)
- chore(deps): update typescript-eslint monorepo to v7.18.0 [`#2292`](https://github.com/th-ch/youtube-music/pull/2292)
- fix(deps): update dependency youtubei.js to v10.2.0 [`#2285`](https://github.com/th-ch/youtube-music/pull/2285)
- chore(deps): update dependency electron to v31.3.0 [`#2282`](https://github.com/th-ch/youtube-music/pull/2282)
- chore(deps): update typescript-eslint monorepo to v7.17.0 [`#2283`](https://github.com/th-ch/youtube-music/pull/2283)
- fix(deps): update dependency solid-js to v1.8.19 [`#2280`](https://github.com/th-ch/youtube-music/pull/2280)
- fix(deps): update dependency @xhayper/discord-rpc to v1.1.4 [`#2279`](https://github.com/th-ch/youtube-music/pull/2279)
- chore(deps): update dependency @babel/runtime to v7.25.0 [`#2281`](https://github.com/th-ch/youtube-music/pull/2281)
- fix(deps): update dependency @floating-ui/dom to v1.6.8 [`#2278`](https://github.com/th-ch/youtube-music/pull/2278)
- Fix: Incorrect window size on scaled displays [`#2258`](https://github.com/th-ch/youtube-music/pull/2258)
- chore(deps): update dependency vite-plugin-resolve to v2.5.2 [`#2276`](https://github.com/th-ch/youtube-music/pull/2276)
- chore(deps): update playwright monorepo to v1.45.3 [`#2277`](https://github.com/th-ch/youtube-music/pull/2277)
- fix(deps): update dependency deepmerge-ts to v7.1.0 [`#2263`](https://github.com/th-ch/youtube-music/pull/2263)
- chore(deps): update dependency typescript to v5.5.4 [`#2274`](https://github.com/th-ch/youtube-music/pull/2274)
- chore(deps): update dependency vite to v5.3.5 [`#2275`](https://github.com/th-ch/youtube-music/pull/2275)
- fix(deps): update dependency i18next to v23.12.2 [`#2260`](https://github.com/th-ch/youtube-music/pull/2260)
- chore(deps): update dependency discord-api-types to v0.37.93 [`#2273`](https://github.com/th-ch/youtube-music/pull/2273)
- chore(deps): update dependency rollup to v4.19.1 [`#2261`](https://github.com/th-ch/youtube-music/pull/2261)
- fix(deps): update dependency custom-electron-prompt to v1.5.8 [`#2262`](https://github.com/th-ch/youtube-music/pull/2262)
- feat(adblocker): add new option AdSpeedup [`#2235`](https://github.com/th-ch/youtube-music/pull/2235)
- fix: disable multi-plane format for software video [`#2254`](https://github.com/th-ch/youtube-music/pull/2254)
- chore(deps): update dependency eslint-plugin-prettier to v5.2.1 [`#2253`](https://github.com/th-ch/youtube-music/pull/2253)
- chore(deps): update dependency vite to v5.3.4 [`#2243`](https://github.com/th-ch/youtube-music/pull/2243)
- chore(deps): update typescript-eslint monorepo to v7.16.1 [`#2239`](https://github.com/th-ch/youtube-music/pull/2239)
- chore(deps): update playwright monorepo to v1.45.2 [`#2244`](https://github.com/th-ch/youtube-music/pull/2244)
- chore(deps): update dependency vite-plugin-inspect to v0.8.5 [`#2252`](https://github.com/th-ch/youtube-music/pull/2252)
- fix(deps): update dependency semver to v7.6.3 [`#2250`](https://github.com/th-ch/youtube-music/pull/2250)
- chore(deps): update dependency electron to v31.2.1 [`#2241`](https://github.com/th-ch/youtube-music/pull/2241)
- chore(i18n): Translated using Weblate (Catalan) [`4a8440c`](https://github.com/th-ch/youtube-music/commit/4a8440c281c341977ab3687982cec8cbc5af6cf7)
- Update changelog for v3.4.1 [`18e0b1b`](https://github.com/th-ch/youtube-music/commit/18e0b1b86341b13f1cbc713bfbd7b5d7a45ee392)
- fix(synced-lyrics): fix type error [`9357a15`](https://github.com/th-ch/youtube-music/commit/9357a15116a8526d22ba6142c0a02f31688743f2)
#### [v3.4.1](https://github.com/th-ch/youtube-music/compare/v3.4.0...v3.4.1)
> 15 July 2024
- fix(mpris): fix mpris position [`#2225`](https://github.com/th-ch/youtube-music/issues/2225)
- fix(deb): fix depends [`#1983`](https://github.com/th-ch/youtube-music/issues/1983)
- fix: fix touchbar icon [`#2183`](https://github.com/th-ch/youtube-music/issues/2183)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 721 KiB

View File

@ -12,7 +12,7 @@
</div>
![Screenshot](/web/screenshot.jpg "Screenshot")
![Screenshot](/web/screenshot.png "Screenshot")
<div align="center">
@ -182,7 +182,7 @@ brew install th-ch/youtube-music/youtube-music
Si instalas la aplicación manualmente y obtienes un error "está dañado y no se puede abrir" al iniciar la aplicación, ejecuta lo siguiente en la Terminal:
```bash
xattr -cr /Applications/YouTube\ Music.app
/usr/bin/xattr -cr /Applications/YouTube\ Music.app
```
### Windows

View File

@ -12,7 +12,7 @@
</div>
![Capture d'écran](https://github.com/th-ch/youtube-music/raw/master/web/screenshot.jpg "Capture d'écran")
![Capture d'écran](/web/screenshot.png "Capture d'écran")
<div align="center">
@ -185,7 +185,7 @@ brew install th-ch/youtube-music/youtube-music
Si vous installez l'application manuellement et obtenez une erreur "est endommagé et ne peut pas être ouvert." lors du lancement de l'application, exécutez ce qui suit dans le Terminal :
```bash
xattr -cr /Applications/YouTube\ Music.app
/usr/bin/xattr -cr /Applications/YouTube\ Music.app
```
### Windows

View File

@ -12,7 +12,7 @@
</div>
![Screenshot](../../web/screenshot.jpg "Screenshot")
![Screenshot](/web/screenshot.png "Screenshot")
<div align="center">
@ -180,7 +180,7 @@ brew install th-ch/youtube-music/youtube-music
Ef þú setur upp forritið handvirkt og færð villu "er skemmd og ekki er hægt að opna það," þegar þú ræsir forritið skaltu keyra eftirfarandi í flugstöðinni:
```bash
xattr -cr /Applications/YouTube\ Music.app
/usr/bin/xattr -cr /Applications/YouTube\ Music.app
```
### Windows

View File

@ -12,7 +12,7 @@
</div>
![Screenshot](../../web/screenshot.jpg "Screenshot")
![Screenshot](/web/screenshot.png "Screenshot")
<div align="center">
<a href="https://github.com/th-ch/youtube-music/releases/latest">
@ -147,7 +147,7 @@ brew install --cask https://raw.githubusercontent.com/th-ch/youtube-music/master
(앱을 수동으로 설치하고) 앱을 실행할 때 `손상되었기 때문에 열 수 없습니다.`라는 오류가 발생하면 터미널에서 다음을 실행하세요:
```bash
xattr -cr /Applications/YouTube\ Music.app
/usr/bin/xattr -cr /Applications/YouTube\ Music.app
```
### Windows

374
docs/readme/README-ru.md Normal file
View File

@ -0,0 +1,374 @@
<div align="center">
# YouTube Music
[![GitHub release](https://img.shields.io/github/release/th-ch/youtube-music.svg?style=for-the-badge&logo=youtube-music)](https://github.com/th-ch/youtube-music/releases/)
[![GitHub license](https://img.shields.io/github/license/th-ch/youtube-music.svg?style=for-the-badge)](https://github.com/th-ch/youtube-music/blob/master/LICENSE)
[![eslint code style](https://img.shields.io/badge/code_style-eslint-5ed9c7.svg?style=for-the-badge)](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
[![Build status](https://img.shields.io/github/actions/workflow/status/th-ch/youtube-music/build.yml?branch=master&style=for-the-badge&logo=youtube-music)](https://GitHub.com/th-ch/youtube-music/releases/)
[![GitHub All Releases](https://img.shields.io/github/downloads/th-ch/youtube-music/total?style=for-the-badge&logo=youtube-music)](https://GitHub.com/th-ch/youtube-music/releases/)
[![AUR](https://img.shields.io/aur/version/youtube-music-bin?color=blueviolet&style=for-the-badge&logo=youtube-music)](https://aur.archlinux.org/packages/youtube-music-bin)
[![Known Vulnerabilities](https://snyk.io/test/github/th-ch/youtube-music/badge.svg)](https://snyk.io/test/github/th-ch/youtube-music)
</div>
![Screenshot](/web/screenshot.png "Screenshot")
<div align="center">
<a href="https://github.com/th-ch/youtube-music/releases/latest">
<img src="web/youtube-music.svg" width="400" height="100" alt="YouTube Music SVG">
</a>
</div>
**Клиент для YouTube Music основанный на Electron с поддержкой:**
- Нативный вид приложения, нацелен на сохранение оригинального интерфейса
- Фреймворк для пользовательских плагинов: изменяйте YouTube Music под ваши нужды (внешний вид, контент, возможности), включайте/выключайте плагины в один клик
## Демо-изображение
| Экран плеера (цветовая тема альбома & режим Ambient) |
|:---------------------------------------------------------------------------------------------------------:|
|![Screenshot1](https://github.com/th-ch/youtube-music/assets/16558115/53efdf73-b8fa-4d7b-a235-b96b91ea77fc)|
## Содержание
- [Возможности](#features)
- [Доступные плагины](#available-plugins)
- [Перевод](#translation)
- [Скачать](#download)
- [Arch Linux](#arch-linux)
- [MacOS](#macos)
- [Windows](#windows)
- [Как установить без подключения к интернету? (в Windows)](#how-to-install-without-a-network-connection-in-windows)
- [Темы](#themes)
- [Для разработчиков](#dev)
- [Создайте свои собственные плагины](#build-your-own-plugins)
- [Создание плагина](#creating-a-plugin)
- [Примеры использования](#common-use-cases)
- [Сборка](#build)
- [Предварительный просмотр](#production-preview)
- [Тестирование](#tests)
- [Лицензия](#license)
- [Часто задаваемые вопросы](#faq)
## Возможности:
- **Авто-подтверждение при паузе** (Всегда включено): отключает всплывающие уведомление ["Продолжить просмотр?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png),
которое приостанавливает воспроизведение через определённое время
- И больше ...
## Доступные плагины:
- **Блокировщик рекламы**: Блокирует всю рекламу и трекеры
- **Действия с альбомом**: Добавляет кнопки "Убрать дизлайк", "Дизлайк", "Лайк", "Убрать лайк" и применяет их действия ко всем трекам в плейлисте или альбоме
- **Цветовая тема альбома**: Применяет динамическую тему и эффекты, основываясь на цветовой палитре альбома
- **Режим Ambient**: Применяет световой эффект, проецируя нежные цвета из видео на задний фон вашего экрана
- **Нормализация аудио**: Применяет нормализацию к аудио (уменьшает громкость громких частей трека и повышает громкость тихих частей трека)
- **Размытие панели навигации**: Делает панель навигации прозрачной и размытой
- **Обход возрастных ограничений**: Обходит проверку возраста YouTube
- **Выбор субтитров**: Включить субтитры
- **Компактная боковая панель**: Всегда показывать боковую панель компактно
- **Плавный переход**: Плавный переход между треками
- **Отключить автопроигрыш**: Каждый трек начинается в режиме паузы
- **[Discord](https://discord.com/) Rich Presence**: Показывает вашим друзьям, что вы слушаете с помощью [Rich Presence](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
- **Загрузчик**: Загрузка MP3 [напрямую из интерфейса](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
- **Расширенная громкость**: Делает слайдер громкости [расширенным](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) облегчая выбор громкости
- **Меню в приложении**: [Придаёт панели меню красивый тёмный вид](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
> (посмотрите [этот пост,](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) если у вас есть проблемы с доступом к меню после включения этого плагина и опции "Скрыть меню")
- **Скробблер**: Добавляет поддержку скробблинга [Last.fm](https://www.last.fm/) и [ListenBrainz](https://listenbrainz.org/)
- **Lumia Stream**: Добавляет поддержку [Lumia Stream](https://lumiastream.com/)
- **Тесты песен Genius**: Добавляет поддержку текстов для большинства песен
- **Music Together**: Делитесь плейлистом с другими. Когда ведущий воспроизводит трек, все остальные будут слушать этот же трек.
- **Навигация**: Кнопки Назад/Вперед интегрированы в интерфейс, как в вашем любимом браузере
- **Без входа в систему Google**: Убирает из интерфейса кнопки и ссылки для входа через Google
- **Уведомления**: Показывает уведомление, когда трек начинает играть ([интерактивные уведомления](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) доступны только для Windows)
- **Картинка в картинке**: Позволяет переключить приложение в режим "картинка в картинке"
- **Скорость воспроизведения**: Слушайте быстрее, слушайте медленнее! [Добавляет слайдер для контроля скорости трека](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
- **Точная громкость**: Точечно управляйте громкостью с помощью колеса мыши/горячих клавиш, с кастомным интерфейсом и настраиваемыми шагами громкости
- **Ярлыки (и MPRIS)**: Позволяет настроить глобальные горячие клавиши управления воспроизведением (плей/пауза/следующий/предыдущий) + отключает [отображение медиа на экране,](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png) переопределяя клавиши управления + включает Ctrl/CMD + F для поиска + включает поддержку linux mpris для клавиш управления медиа + [настраиваемые сочетания клавиш](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50) для [продвинутых пользователей](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
- **Пропускать непонравившиеся треки**: Пропускает непонравившиеся треки
- **Пропуск тишины**: Автоматически пропускает тихие моменты в песнях
- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Автоматически пропускает немузыкальные части, такие как интро/аутро музыкальных видео, где трек не играет
- **Управление воспроизведением из панели задач**: Управляйте воспроизведением из [панели задач Windows](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
- **TouchBar**: Кастомная раскладка TouchBar для MacOS
- **Tuna OBS**: Интеграция с [OBS](https://obsproject.com/) плагином [Tuna](https://obsproject.com/forum/resources/tuna.843/)
- **Изменение качества видео**: Позволяет менять качество видео [кнопкой](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) на медиаплеере видео
- **Переключатель видео**: Добавляет
[кнопку](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) переключения режимов Трек/Видео. Также может удалять вкладку "Видео" полностью
- **Визуализатор**: Различные визуализаторы музыки
- **Synced Lyrics**:
Предоставляет синхронизированные слова для песен из таких источников, как [LRClib](https://lrclib.net).
## Перевод
Вы можете помочь с переводом на ваш язык на [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
<a href="https://hosted.weblate.org/engage/youtube-music/">
<img src="https://hosted.weblate.org/widget/youtube-music/i18n/multi-auto.svg" alt="translation status" />
<img src="https://hosted.weblate.org/widget/youtube-music/i18n/287x66-black.png" alt="translation status 2" />
</a>
## Скачать
Вы можете посмотреть [latest release,](https://github.com/th-ch/youtube-music/releases/latest) чтобы быстро найти новую версию.
### Arch Linux
Установите пакет [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) из AUR. Инструкции по установке из AUR можете найти на этой [вики-странице](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
### macOS
Вы можете установить приложение с помощью Homebrew (сморите [cask definition](https://github.com/th-ch/homebrew-youtube-music)):
```bash
brew install th-ch/youtube-music/youtube-music
```
Если вы устанавливаете приложение вручную и получаете ошибку "is damaged and cant be opened.", запустите в терминале следующую команду:
```bash
/usr/bin/xattr -cr /Applications/YouTube\ Music.app
```
### Windows
Вы можете использовать [пакетный менеджер Scoop](https://scoop.sh) для установки пакета `youtube-music` из [`extras` bucket](https://github.com/ScoopInstaller/Extras).
```bash
scoop bucket add extras
scoop install extras/youtube-music
```
Также для установки вы можете использовать [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), официальный пакетный менеджер командной строки Windows 11, для установки пакета `th-ch.YouTubeMusic`.
*К сведению: SmartScreen защитника Windows может блокировать установку, так как она от "неизвестного издателя". Это также применимо к методу ручной установки, когда вы пытаетесь запустить исполняемый файл(.exe) после загрузки здесь, на GitHub (тот же файл).*
```bash
winget install th-ch.YouTubeMusic
```
#### Установка без подключения к Интернету? (в Windows)
- Скачайте файл `*.nsis.7z` из _архетиктура вашего устройства_ на [release page](https://github.com/th-ch/youtube-music/releases/latest).
- `x64` для 64-bit Windows
- `ia32` для 32-bit Windows
- `arm64` для ARM64 Windows
- Скачайте установщик в release page. (`*-Setup.exe`)
- Поместите их в **одной директории**.
- Запустите установщик.
## Темы
Вы можете загрузить файл CSS для смены внешнего вида приложения (Настройки > Визуальные настройки > Тема).
Некоторые предустановленные темы доступны здесь: https://github.com/kerichdev/themes-for-ytmdesktop-player.
## Для разработчиков
```bash
git clone https://github.com/th-ch/youtube-music
cd youtube-music
pnpm install --frozen-lockfile
pnpm dev
```
## Создайте свои собственные плагины
Используя плагины вы можете:
- Манипулировать приложением - `BrowserWindow` из electron проброшен обработчику плагинов
- Изменять внешний вид, манипулируя HTML/CSS
### Создание плагина
Создайте директорию в `src/plugins/YOUR-PLUGIN-NAME`:
- `index.ts`: основной файл плагина
```typescript
import style from './style.css?inline'; // import style as inline
import { createPlugin } from '@/utils';
export default createPlugin({
name: 'Plugin Label',
restartNeeded: true, // if value is true, ytmusic show restart dialog
config: {
enabled: false,
}, // your custom config
stylesheets: [style], // your custom style,
menu: async ({ getConfig, setConfig }) => {
// All *Config methods are wrapped Promise<T>
const config = await getConfig();
return [
{
label: 'menu',
submenu: [1, 2, 3].map((value) => ({
label: `value ${value}`,
type: 'radio',
checked: config.value === value,
click() {
setConfig({ value });
},
})),
},
];
},
backend: {
start({ window, ipc }) {
window.maximize();
// you can communicate with renderer plugin
ipc.handle('some-event', () => {
return 'hello';
});
},
// it fired when config changed
onConfigChange(newConfig) { /* ... */ },
// it fired when plugin disabled
stop(context) { /* ... */ },
},
renderer: {
async start(context) {
console.log(await context.ipc.invoke('some-event'));
},
// Only renderer available hook
onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
// set plugin config easily
context.setConfig({ myConfig: api.getVolume() });
},
onConfigChange(newConfig) { /* ... */ },
stop(_context) { /* ... */ },
},
preload: {
async start({ getConfig }) {
const config = await getConfig();
},
onConfigChange(newConfig) {},
stop(_context) {},
},
});
```
### Примеры использования
- Кастомный CSS: создайте файл `style.css` в той же директории, затем:
```typescript
// index.ts
import style from './style.css?inline'; // import style as inline
import { createPlugin } from '@/utils';
export default createPlugin({
name: 'Plugin Label',
restartNeeded: true, // if value is true, ytmusic will show a restart dialog
config: {
enabled: false,
}, // your custom config
stylesheets: [style], // your custom style
renderer() {} // define renderer hook
});
```
- Если вы хотите изменить HTML:
```typescript
import { createPlugin } from '@/utils';
export default createPlugin({
name: 'Plugin Label',
restartNeeded: true, // if value is true, ytmusic will show the restart dialog
config: {
enabled: false,
}, // your custom config
renderer() {
// Remove the login button
document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
} // define renderer hook
});
```
- обмен между фронтом и бэком может быть выполнен с помощью модуля ipcMain из electron. Смотрите файл `index.ts` и
пример в плагине `sponsorblock`.
## Сборка
1. Склонируйте репозиторий
2. Следуйте [этой инструкции,](https://pnpm.io/installation) чтобы установить `pnpm`
3. Запустите `pnpm install --frozen-lockfile` для установки зависимостей
4. Запустите `pnpm build:OS`
- `pnpm dist:win` - Windows
- `pnpm dist:linux` - Linux (amd64)
- `pnpm dist:linux:deb-arm64` - Linux (arm64 for Debian)
- `pnpm dist:linux:rpm-arm64` - Linux (arm64 for Fedora)
- `pnpm dist:mac` - macOS (amd64)
- `pnpm dist:mac:arm64` - macOS (arm64)
Сборка приложения для macOS, Linux, и Windows,
используя [electron-builder](https://github.com/electron-userland/electron-builder).
## Предварительный просмотр
```bash
pnpm start
```
## Тестирование
```bash
pnpm test
```
Использует [Playwright](https://playwright.dev/) для тестирования приложения.
## Лицензия
MIT © [th-ch](https://github.com/th-ch/youtube-music)
## Часто задаваемые вопросы
### Почему меня приложения не отображается?
Если опция `Скрыть меню` включена - вы можете отобразить меню с помощью клавиши <kbd>alt</kbd> (или <kbd>\`</kbd> [обратный апостроф], если используете плагин "Меню в приложении")

View File

@ -51,6 +51,7 @@ export default defineConfig({
};
if (mode === 'development') {
commonConfig.build!.sourcemap = 'inline';
commonConfig.plugins?.push(
Inspect({
build: true,
@ -98,6 +99,7 @@ export default defineConfig({
};
if (mode === 'development') {
commonConfig.build!.sourcemap = 'inline';
commonConfig.plugins?.push(
Inspect({
build: true,
@ -148,6 +150,7 @@ export default defineConfig({
};
if (mode === 'development') {
commonConfig.build!.sourcemap = 'inline';
commonConfig.plugins?.push(
Inspect({
build: true,

80
eslint.config.mjs Normal file
View File

@ -0,0 +1,80 @@
//@ts-check
import eslint from '@eslint/js';
import prettier from 'eslint-plugin-prettier/recommended';
import stylistic from '@stylistic/eslint-plugin-js';
import tsEslint from 'typescript-eslint';
import * as importPlugin from 'eslint-plugin-import';
export default tsEslint.config(
eslint.configs.recommended,
tsEslint.configs.eslintRecommended,
...tsEslint.configs.recommendedTypeChecked,
prettier,
{ ignores: ['dist', 'node_modules', '*.config.*js', '*.test.*js'] },
{
plugins: {
stylistic,
importPlugin
},
languageOptions: {
parser: tsEslint.parser,
parserOptions: {
project: true,
sourceType: 'module',
ecmaVersion: 'latest'
}
},
rules: {
'stylistic/arrow-parens': ['error', 'always'],
'stylistic/object-curly-spacing': ['error', 'always'],
'prettier/prettier': ['error', { singleQuote: true, semi: true, tabWidth: 2, trailingComma: 'all', quoteProps: 'preserve' }],
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': ['off', { checksVoidReturn: false }],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-non-null-assertion': 'off',
'importPlugin/first': 'error',
'importPlugin/newline-after-import': 'off',
'importPlugin/no-default-export': 'off',
'importPlugin/no-duplicates': 'error',
'importPlugin/no-unresolved': ['error', { ignore: ['^virtual:', '\\?inline$', '\\?raw$', '\\?asset&asarUnpack'] }],
'importPlugin/order': ['error', {
'groups': ['builtin', 'external', ['internal', 'index', 'sibling'], 'parent', 'type'],
'newlines-between': 'always-and-inside-groups',
'alphabetize': { order: 'ignore', caseInsensitive: false }
}],
'importPlugin/prefer-default-export': 'off',
'camelcase': ['error', { properties: 'never' }],
'class-methods-use-this': 'off',
'stylistic/lines-around-comment': ['error', {
beforeBlockComment: false,
afterBlockComment: false,
beforeLineComment: false,
afterLineComment: false,
}],
'stylistic/max-len': 'off',
'stylistic/no-mixed-operators': 'warn', // prettier does not support no-mixed-operators
'stylistic/no-multi-spaces': ['error', { ignoreEOLComments: true }],
'stylistic/no-tabs': 'error',
'no-void': 'error',
'no-empty': 'off',
'prefer-promise-reject-errors': 'off',
'stylistic/quotes': ['error', 'single', {
avoidEscape: true,
allowTemplateLiterals: false,
}],
'stylistic/quote-props': ['error', 'consistent'],
'stylistic/semi': ['error', 'always'],
},
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts']
},
'import/resolver': {
typescript: {},
exports: {},
},
},
},
);

View File

@ -1,7 +1,8 @@
{
"name": "youtube-music",
"desktopName": "com.github.th_ch.youtube_music",
"productName": "YouTube Music",
"version": "3.5.0",
"version": "3.7.1",
"description": "YouTube Music Desktop App - including custom plugins",
"main": "./dist/main/index.js",
"license": "MIT",
@ -21,7 +22,7 @@
"license",
"!node_modules",
"node_modules/custom-electron-prompt/**",
"node_modules/@cliqz/adblocker-electron-preload/**",
"node_modules/@ghostery/adblocker-electron-preload/**",
"node_modules/@ffmpeg.wasm/core-mt/**",
"!node_modules/**/*.map",
"!node_modules/**/*.ts"
@ -40,7 +41,8 @@
]
}
],
"icon": "assets/generated/icons/mac/icon.icns"
"icon": "assets/generated/icons/mac/icon.icns",
"compression": "maximum"
},
"win": {
"icon": "assets/generated/icons/win/icon.ico",
@ -61,7 +63,8 @@
"arm64"
]
}
]
],
"compression": "maximum"
},
"nsisWeb": {
"runAfterFinish": false
@ -69,12 +72,84 @@
"linux": {
"icon": "assets/generated/icons/png",
"category": "AudioVideo",
"desktop": {
"StartupWMClass": "com.github.th_ch.youtube_music"
},
"target": [
"AppImage",
"snap",
"freebsd",
"deb",
"rpm"
{
"target": "AppImage",
"arch": [
"x64",
"arm64",
"armv7l"
]
},
{
"target": "flatpak",
"arch": [
"x64"
]
},
{
"target": "deb",
"arch": [
"x64",
"arm64",
"armv7l"
]
},
{
"target": "rpm",
"arch": [
"x64",
"arm64"
]
},
{
"target": "snap",
"arch": [
"x64"
]
},
{
"target": "freebsd",
"arch": [
"x64",
"arm64",
"armv7l"
]
},
{
"target": "tar.gz",
"arch": [
"x64",
"arm64",
"armv7l"
]
}
]
},
"appImage": {
"description": "YouTube Music Desktop App bundled with custom plugins (and built-in ad blocker / downloader)",
"category": "AudioVideo"
},
"flatpak": {
"description": "YouTube Music Desktop App bundled with custom plugins (and built-in ad blocker / downloader)",
"category": "AudioVideo",
"runtimeVersion": "24.08",
"baseVersion": "24.08",
"finishArgs": [
"--socket=wayland",
"--socket=x11",
"--share=ipc",
"--device=dri",
"--socket=pulseaudio",
"--share=network",
"--filesystem=xdg-music:rw",
"--talk-name=org.freedesktop.Notifications",
"--talk-name=org.gnome.SessionManager",
"--talk-name=org.kde.StatusNotifierWatcher",
"--own-name=org.mpris.MediaPlayer2.YoutubeMusic.*"
]
},
"deb": {
@ -94,6 +169,10 @@
"rpm": {
"depends": [
"/usr/lib64/libuuid.so.1"
],
"fpm": [
"--rpm-rpmbuild-define",
"_build_id_links none"
]
},
"snap": {
@ -116,7 +195,8 @@
"vite:inspect": "pnpm clean && electron-vite build --mode development && pnpm exec serve .vite-inspect",
"start": "electron-vite preview",
"start:debug": "cross-env ELECTRON_ENABLE_LOGGING=1 pnpm start",
"dev": "electron-vite dev --watch",
"dev": "cross-env NODE_OPTIONS=--enable-source-maps electron-vite dev --watch",
"dev:renderer": "cross-env NODE_OPTIONS=--enable-source-maps electron-vite dev",
"dev:debug": "cross-env ELECTRON_ENABLE_LOGGING=1 pnpm dev",
"clean": "del-cli dist && del-cli pack && del-cli .vite-inspect",
"dist": "pnpm clean && pnpm build && pnpm electron-builder --win --mac --linux -p never",
@ -135,109 +215,121 @@
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"engines": {
"node": ">=18.0.0",
"node": ">=18",
"pnpm": ">=8"
},
"pnpm": {
"overrides": {
"usocket": "1.0.1",
"node-gyp": "10.2.0",
"node-gyp": "11.0.0",
"xml2js": "0.6.2",
"node-fetch": "3.3.2",
"@electron/universal": "2.0.1",
"@babel/runtime": "7.25.0"
"@babel/runtime": "7.26.0"
},
"patchedDependencies": {
"vudio@2.1.1": "patches/vudio@2.1.1.patch",
"@xhayper/discord-rpc@1.1.4": "patches/@xhayper__discord-rpc@1.1.4.patch",
"app-builder-lib@24.13.3": "patches/app-builder-lib@24.13.3.patch"
"app-builder-lib@24.13.3": "patches/app-builder-lib@24.13.3.patch",
"@malept/flatpak-bundler": "patches/@malept__flatpak-bundler.patch"
}
},
"dependencies": {
"@cliqz/adblocker-electron": "1.27.1",
"@cliqz/adblocker-electron-preload": "1.27.1",
"@electron-toolkit/tsconfig": "1.0.1",
"@electron/remote": "2.1.2",
"@ffmpeg.wasm/core-mt": "0.12.0",
"@ffmpeg.wasm/main": "0.12.0",
"@floating-ui/dom": "1.6.8",
"@floating-ui/dom": "1.6.12",
"@foobar404/wave": "2.0.5",
"@ghostery/adblocker-electron": "2.3.1",
"@ghostery/adblocker-electron-preload": "2.3.1",
"@hono/node-server": "1.13.7",
"@hono/swagger-ui": "0.5.0",
"@hono/zod-openapi": "0.18.3",
"@hono/zod-validator": "0.4.2",
"@jellybrick/electron-better-web-request": "1.0.4",
"@jellybrick/mpris-service": "2.1.4",
"@skyra/jaro-winkler": "^1.1.1",
"@xhayper/discord-rpc": "1.1.4",
"@jimp/plugin-invert": "0.22.12",
"@skyra/jaro-winkler": "1.1.1",
"@xhayper/discord-rpc": "1.2.0",
"async-mutex": "0.5.0",
"butterchurn": "3.0.0-beta.4",
"butterchurn-presets": "3.0.0-beta.4",
"color": "4.2.3",
"conf": "13.0.1",
"conf": "13.1.0",
"custom-electron-prompt": "1.5.8",
"dbus-next": "0.10.2",
"deepmerge-ts": "7.1.0",
"electron-debug": "4.0.0",
"deepmerge-ts": "7.1.3",
"electron-debug": "4.1.0",
"electron-is": "3.0.0",
"electron-localshortcut": "3.2.1",
"electron-store": "10.0.0",
"electron-unhandled": "4.0.1",
"electron-updater": "6.3.2",
"electron-updater": "6.3.9",
"fast-average-color": "9.4.0",
"fast-equals": "5.0.1",
"filenamify": "6.0.0",
"hono": "4.6.14",
"howler": "2.2.4",
"html-to-text": "9.0.5",
"i18next": "23.12.2",
"i18next": "24.2.0",
"jimp": "1.6.0",
"keyboardevent-from-electron-accelerator": "2.0.0",
"keyboardevents-areequal": "0.2.2",
"node-html-parser": "6.1.13",
"node-html-parser": "7.0.1",
"node-id3": "0.2.6",
"peerjs": "1.5.4",
"semver": "7.6.3",
"serve": "14.2.3",
"serve": "14.2.4",
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
"solid-floating-ui": "0.3.1",
"solid-js": "1.8.19",
"solid-js": "1.9.3",
"solid-styled-components": "0.28.5",
"solid-transition-group": "0.2.3",
"ts-morph": "23.0.0",
"ts-morph": "24.0.0",
"vudio": "2.1.1",
"x11": "2.3.0",
"youtubei.js": "10.2.0"
"youtubei.js": "12.2.0",
"zod": "3.24.1"
},
"devDependencies": {
"@playwright/test": "1.45.3",
"@total-typescript/ts-reset": "0.5.1",
"@types/color": "3.0.6",
"@eslint/js": "9.17.0",
"@playwright/test": "1.49.1",
"@stylistic/eslint-plugin-js": "2.12.1",
"@total-typescript/ts-reset": "0.6.1",
"@types/color": "4.2.0",
"@types/electron-localshortcut": "3.1.3",
"@types/howler": "2.2.11",
"@types/eslint__js": "8.42.3",
"@types/howler": "2.2.12",
"@types/html-to-text": "9.0.4",
"@types/semver": "7.5.8",
"@typescript-eslint/eslint-plugin": "7.18.0",
"@typescript-eslint/parser": "7.18.0",
"@types/trusted-types": "2.0.7",
"bufferutil": "4.0.8",
"builtin-modules": "4.0.0",
"cross-env": "7.0.3",
"del-cli": "5.1.0",
"discord-api-types": "0.37.93",
"electron": "31.3.1",
"del-cli": "6.0.0",
"discord-api-types": "0.37.114",
"electron": "33.2.1",
"electron-builder": "24.13.3",
"electron-devtools-installer": "3.2.0",
"electron-devtools-installer": "4.0.0",
"electron-vite": "2.3.0",
"esbuild": "0.23.0",
"eslint": "8.57.0",
"esbuild": "0.24.2",
"eslint": "9.17.0",
"eslint-config-prettier": "9.1.0",
"eslint-import-resolver-exports": "1.0.0-beta.5",
"eslint-import-resolver-typescript": "3.6.1",
"eslint-plugin-import": "2.29.1",
"eslint-import-resolver-typescript": "3.7.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-prettier": "5.2.1",
"glob": "11.0.0",
"node-gyp": "10.2.0",
"playwright": "1.45.3",
"rollup": "4.19.1",
"typescript": "5.5.4",
"utf-8-validate": "6.0.4",
"vite": "5.3.5",
"vite-plugin-inspect": "0.8.5",
"node-gyp": "11.0.0",
"playwright": "1.49.1",
"rollup": "4.29.1",
"typescript": "5.7.2",
"typescript-eslint": "8.18.2",
"utf-8-validate": "6.0.5",
"vite": "6.0.6",
"vite-plugin-inspect": "0.10.6",
"vite-plugin-resolve": "2.5.2",
"vite-plugin-solid": "2.10.2",
"vite-plugin-solid": "2.11.0",
"ws": "8.18.0"
},
"auto-changelog": {

View File

@ -0,0 +1,29 @@
diff --git a/index.js b/index.js
index 5968fcf47b69094993b0f861c03f5560e4a6a9b7..0fe16d4f40612c0abfa57898909ce0083f56944c 100644
--- a/index.js
+++ b/index.js
@@ -56,19 +56,23 @@ function getOptionsWithDefaults (options, manifest) {
async function spawnWithLogging (options, command, args, allowFail) {
return new Promise((resolve, reject) => {
logger(`$ ${command} ${args.join(' ')}`)
+ const output = []
const child = childProcess.spawn(command, args, { cwd: options['working-dir'] })
child.stdout.on('data', (data) => {
+ output.push(data)
logger(`1> ${data}`)
})
child.stderr.on('data', (data) => {
+ output.push(data)
logger(`2> ${data}`)
})
child.on('error', (error) => {
+ logger(`error - ${error.message} ${error.stack}`)
reject(error)
})
child.on('close', (code) => {
if (!allowFail && code !== 0) {
- reject(new Error(`${command} failed with status code ${code}`))
+ reject(new Error(`${command} ${args.join(' ')} failed with status code ${code} ${output.join(' ')}`))
}
resolve(code === 0)
})

View File

@ -1,17 +0,0 @@
diff --git a/package.json b/package.json
index 40db5dfbd8a4455ce2987d8115eca9882e1f9f14..414fc6986b9c0cc288908eb0107b90c4bfd916b2 100644
--- a/package.json
+++ b/package.json
@@ -25,11 +25,7 @@
},
"dependencies": {
"axios": "^1.7.2",
- "ws": "^8.18.0"
- },
- "optionalDependencies": {
- "bufferutil": "^4.0.8",
- "utf-8-validate": "^6.0.4"
+ "ws": "^8.18.0"
},
"devDependencies": {
"@types/node": "^14.*",

5016
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
import Store from 'electron-store';
import { deepmergeCustom } from 'deepmerge-ts';
import defaultConfig from './defaults';
import store from './store';
import store, { IStore } from './store';
import plugins from './plugins';
import { restart } from '@/providers/app-controls';
@ -70,12 +69,11 @@ type Paths<T, D extends number = 10> = [D] extends [never]
: '';
type SplitKey<K> = K extends `${infer A}.${infer B}` ? [A, B] : [K, string];
type PathValue<T, K extends string> = SplitKey<K> extends [
infer A extends keyof T,
infer B extends string,
]
type PathValue<T, K extends string> =
SplitKey<K> extends [infer A extends keyof T, infer B extends string]
? PathValue<T[A], B>
: T;
const get = <Key extends Paths<typeof defaultConfig>>(key: Key) =>
store.get(key) as PathValue<typeof defaultConfig, typeof key>;
@ -86,7 +84,7 @@ export default {
setPartial,
setMenuOption,
edit: () => store.openInEditor(),
watch(cb: Parameters<Store['onDidAnyChange']>[0]) {
watch(cb: Parameters<IStore['onDidAnyChange']>[0]) {
store.onDidAnyChange(cb);
},
plugins,

View File

@ -1,12 +1,14 @@
import Store from 'electron-store';
import Conf from 'conf';
import defaults from './defaults';
import { DefaultPresetList, type Preset } from '@/plugins/downloader/types';
// prettier-ignore
export type IStore = InstanceType<typeof import('conf/dist/source/index').default<Record<string, unknown>>>;
const migrations = {
'>=3.3.0'(store: Conf<Record<string, unknown>>) {
'>=3.3.0'(store: IStore) {
const lastfmConfig = store.get('plugins.lastfm') as {
enabled?: boolean;
token?: string;
@ -16,9 +18,8 @@ const migrations = {
secret?: string;
};
if (lastfmConfig) {
let scrobblerConfig = store.get(
'plugins.scrobbler',
) as {
let scrobblerConfig = store.get('plugins.scrobbler') as
| {
enabled?: boolean;
scrobblers?: {
lastfm?: {
@ -30,7 +31,8 @@ const migrations = {
secret?: string;
};
};
} | undefined;
}
| undefined;
if (!scrobblerConfig) {
scrobblerConfig = {
@ -56,7 +58,7 @@ const migrations = {
store.delete('plugins.lastfm');
}
},
'>=3.0.0'(store: Conf<Record<string, unknown>>) {
'>=3.0.0'(store: IStore) {
const discordConfig = store.get('plugins.discord') as Record<
string,
unknown
@ -78,14 +80,14 @@ const migrations = {
}
}
},
'>=2.1.3'(store: Conf<Record<string, unknown>>) {
'>=2.1.3'(store: IStore) {
const listenAlong = store.get('plugins.discord.listenAlong');
if (listenAlong !== undefined) {
store.set('plugins.discord.playOnYouTubeMusic', listenAlong);
store.delete('plugins.discord.listenAlong');
}
},
'>=2.1.0'(store: Conf<Record<string, unknown>>) {
'>=2.1.0'(store: IStore) {
const originalPreset = store.get('plugins.downloader.preset') as
| string
| undefined;
@ -110,7 +112,7 @@ const migrations = {
store.delete('plugins.downloader.ffmpegArgs');
}
},
'>=1.20.0'(store: Conf<Record<string, unknown>>) {
'>=1.20.0'(store: IStore) {
store.delete('plugins.visualizer'); // default value is now in the plugin
if (store.get('plugins.notifications.toastStyle') === undefined) {
@ -125,14 +127,14 @@ const migrations = {
store.set('options.likeButtons', 'force');
}
},
'>=1.17.0'(store: Conf<Record<string, unknown>>) {
'>=1.17.0'(store: IStore) {
store.delete('plugins.picture-in-picture'); // default value is now in the plugin
if (store.get('plugins.video-toggle.mode') === undefined) {
store.set('plugins.video-toggle.mode', 'custom');
}
},
'>=1.14.0'(store: Conf<Record<string, unknown>>) {
'>=1.14.0'(store: IStore) {
if (
typeof store.get('plugins.precise-volume.globalShortcuts') !== 'object'
) {
@ -144,12 +146,12 @@ const migrations = {
store.set('plugins.video-toggle.enabled', true);
}
},
'>=1.13.0'(store: Conf<Record<string, unknown>>) {
'>=1.13.0'(store: IStore) {
if (store.get('plugins.discord.listenAlong') === undefined) {
store.set('plugins.discord.listenAlong', true);
}
},
'>=1.12.0'(store: Conf<Record<string, unknown>>) {
'>=1.12.0'(store: IStore) {
const options = store.get('plugins.shortcuts') as
| Record<
string,
@ -187,12 +189,12 @@ const migrations = {
}
}
},
'>=1.11.0'(store: Conf<Record<string, unknown>>) {
'>=1.11.0'(store: IStore) {
if (store.get('options.resumeOnStart') === undefined) {
store.set('options.resumeOnStart', true);
}
},
'>=1.7.0'(store: Conf<Record<string, unknown>>) {
'>=1.7.0'(store: IStore) {
const enabledPlugins = store.get('plugins') as string[];
if (!Array.isArray(enabledPlugins)) {
console.warn('Plugins are not in array format, cannot migrate');
@ -233,4 +235,4 @@ export default new Store({
},
clearInvalidConfig: false,
migrations,
});
}) as Store & IStore;

View File

@ -14,9 +14,9 @@
}
},
"language": {
"code": "إنجليزي",
"local-name": "الإنجليزي",
"name": "الإنجليزية"
"code": "ar",
"local-name": "العربية",
"name": "Arabic"
},
"main": {
"console": {
@ -194,7 +194,133 @@
}
},
"tray": {
"next": "التالي"
"next": "التالي",
"play-pause": "تشغيل/إيقاف",
"previous": "السابق",
"quit": "خروج",
"restart": "إعادة تشغيل التطبيق",
"show": "عرض النافدة",
"tooltip": {
"default": "يوتيوب اغاني",
"with-song-info": "يوتيوب أغاني: {{الفنان}}-{{العنوان}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "إذا تم عرض إعلان, فإن الصوت سيتم كتمانه وسيتم وضع سرعة التشغيل الى 16x",
"name": "تسريع الإعلان"
},
"adblocker": {
"description": "حجب جميع الإعلانات والمتتبعات جاهز للأستخدام",
"menu": {
"blocker": "حاجب الإعلانات"
},
"name": "حاجب الإعلانات"
},
"album-actions": {
"description": "يضيف أزرار \"إلغاء عدم الإعجاب\"، \"عدم الإعجاب\"، \"الإعجاب\"، و\"إلغاء الإعجاب\" لتطبيقها على جميع الأغاني في قائمة التشغيل أو الألبوم",
"name": "إجراءات الألبوم"
},
"album-color-theme": {
"description": "يطبق ثيمًا ديناميكيًا وتأثيرات بصرية بناء على ألوان الألبوم",
"menu": {
"color-mix-ratio": {
"label": "‬نسبة قوة اللون",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "ثيم ألوان الألبوم"
},
"ambient-mode": {
"description": "يطبق تأثير إضاءة عن طريق إسقاط ألوان ناعمة من الفيديو على خلفية شاشتك",
"menu": {
"blur-amount": {
"label": "مقدار التمويه",
"submenu": {
"pixels": "{{blurAmount}} بكسل"
}
},
"buffer": {
"label": "تخزين الصوت الؤقت",
"submenu": {
"buffer": "{{buffer}}"
}
},
"opacity": {
"label": "الشفافية",
"submenu": {
"percent": "{{opacity}}%"
}
},
"quality": {
"label": "الجودة",
"submenu": {
"pixels": "{{quality}} بكسل"
}
},
"size": {
"label": "الحجم",
"submenu": {
"percent": "{{size}}%"
}
},
"smoothness-transition": {
"label": "انتقال السلاسة",
"submenu": {
"during": "خلال {{interpolationTime}} ثانيه"
}
},
"use-fullscreen": {
"label": "استخدام شاشه كامله"
}
},
"name": "الوضع المحيطي"
},
"api-server": {
"description": "يضيف خادم للتحكم في المشغل",
"dialog": {
"request": {
"buttons": {
"allow": "سماح",
"deny": "رفض"
}
}
},
"menu": {
"hostname": {
"label": "اسم المضيف"
}
},
"prompt": {
"hostname": {
"title": "اسم الخادم"
}
}
},
"blur-nav-bar": {
"description": "يجعل شريط التنقل شفاف و ضبابي"
},
"bypass-age-restrictions": {
"description": "تجاوز تَحَقّق اليوتيوب من السن",
"name": "تجاوز التحقق من السن"
},
"downloader": {
"backend": {
"feedback": {
"downloading-counter": "تنزيل {{current}}/{{total}}…",
"error-while-downloading": "خطأ في تحميل \"{{author}} - {{title}}\": {{error}}",
"loading": "جار التحميل…",
"preparing-file": "يتم تجهيز الملف…",
"saving": "يتم الحفظ…",
"video-id-not-found": "لم يتم ايجاد الفيديو"
}
},
"menu": {
"choose-download-folder": "اختر مكان التحميل"
}
}
}
}

View File

@ -15,7 +15,7 @@
},
"language": {
"code": "ca",
"local-name": "català",
"local-name": "Català",
"name": "Catalan"
},
"main": {
@ -84,9 +84,9 @@
"label": "Navegació",
"submenu": {
"copy-current-url": "Copia l'URL actual",
"go-back": "Anar enrere",
"go-forward": "Anar endavant",
"quit": "Sortir",
"go-back": "Ves enrere",
"go-forward": "Ves endavant",
"quit": "Surt",
"restart": "Reinicia l'aplicació"
}
},
@ -102,11 +102,11 @@
"override-user-agent": "Sobreescriu l'agent d'usuari (User-Agent)",
"restart-on-config-changes": "Reinicia quan es canviï la configuració",
"set-proxy": {
"label": "Definir proxy",
"label": "Definir servidor intermediari (proxy)",
"prompt": {
"label": "Introduir l'adreça del proxy: (deixar en blanc per deshabilitar)",
"label": "Introduir l'adreça del servidor intermediari: (deixar en blanc per deshabilitar)",
"placeholder": "Exemple: SOCKS5://127.0.0.1:9999",
"title": "Definir proxy"
"title": "Definir servidor intermediari (proxy)"
}
},
"toggle-dev-tools": "Commuta les DevTools"
@ -144,11 +144,11 @@
"disabled": "Deshabilitat",
"enabled-and-hide-app": "Mostra la icona i amaga l'aplicació",
"enabled-and-show-app": "Mostra la icona i mostra l'aplicació",
"play-pause-on-click": "Reproduir/Pausar en clicar"
"play-pause-on-click": "Reprodueix / pausa en clicar"
}
},
"visual-tweaks": {
"label": "Configuració visual",
"label": "Opcions visuals",
"submenu": {
"like-buttons": {
"default": "Per defecte",
@ -182,9 +182,9 @@
"new": "NOU"
},
"view": {
"label": "Mostra",
"label": "Veure",
"submenu": {
"force-reload": "Força recàrrega",
"force-reload": "Força la recàrrega",
"reload": "Recarrega",
"reset-zoom": "Mida real",
"toggle-fullscreen": "Commuta la pantalla completa",
@ -220,7 +220,7 @@
},
"album-actions": {
"description": "Afegeix botons de «no m'agrada / retirar el no m'agrada» i «m'agrada / retirar el m'agrada» per aplicar-ho a totes les cançons en una llista de reproducció o àlbum",
"name": "Accions de l'àlbum"
"name": "Accions a l'àlbum"
},
"album-color-theme": {
"description": "Aplica un tema dinàmic i efectes visuals basats en la paleta de colors de l'àlbum",
@ -279,9 +279,52 @@
},
"name": "Mode ambient"
},
"api-server": {
"description": "Afegeix un servidor API per controlar el reproductor",
"dialog": {
"request": {
"buttons": {
"allow": "Permet",
"deny": "Denegar"
},
"message": "Permetre que {{ID}} ({{origin}}) accedeixi a l'API?",
"title": "Petició d'autorització API"
}
},
"menu": {
"auth-strategy": {
"label": "Estratègia d'autorització",
"submenu": {
"auth-at-first": {
"label": "Autoritza a la primera petició"
},
"none": {
"label": "Sense autorització"
}
}
},
"hostname": {
"label": "Nom del host"
},
"port": {
"label": "Port"
}
},
"name": "Servidor API [Beta]",
"prompt": {
"hostname": {
"label": "Introdueix el nom del host (per exemple 0.0.0.0) pel servidor API:",
"title": "Nom del host"
},
"port": {
"label": "Introdueix el port pel servidor API:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Aplica compressió a l'àudio (baixa el volum de les parts més sorolloses de la senyal d'àudio i puja el volum de les parts més fluixes)",
"name": "Compressor d'àudio"
"name": "Compress d'àudio"
},
"blur-nav-bar": {
"description": "Desenfoca i aplica transparència a la barra de navegació",
@ -518,7 +561,7 @@
},
"no-google-login": {
"description": "Elimina els botons d'inici de sessió de Google de la interfície",
"name": "Sense inici de sessió de Google"
"name": "Amaga l'inici de sessió de Google"
},
"notifications": {
"description": "Mostra una notificació quan una cançó es comença a reproduir (les notificacions interactives estan disponibles a Windows)",
@ -602,7 +645,7 @@
}
},
"description": "Permet canviar la qualitat del vídeo amb un botó que s'hi mostra a sobre",
"name": "Canvia la qualitat del vídeo"
"name": "Botó de qualitat del vídeo"
},
"scrobbler": {
"description": "Afegeix suport per scrobbling (Last.fm, ListenBrainz, etc.)",
@ -657,8 +700,8 @@
}
},
"skip-disliked-songs": {
"description": "Omet cançons amb «No m'agrada»",
"name": "Omet cançons amb «No m'agrad"
"description": "Salta les cançons amb «no m'agrada»",
"name": "Salta les cançons que no t'agraden"
},
"skip-silences": {
"description": "Omet automàticament les seccions amb silenci a les cançons",
@ -668,6 +711,59 @@
"description": "Omet automàticament els segments dels vídeos que no son música, com la intro o el final",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Proporciona lletres sincronitzades amb les cançons, a través de proveïdors com LRClib.",
"errors": {
"fetch": "⚠️ - Se ha produït un error en descarregar la lletra. Si us plau, intenta-ho més tard.",
"not-found": "⚠️ - No s'ha trobat la lletra per aquesta cançó."
},
"menu": {
"default-text-string": {
"label": "Caràcter per defecte entre lletres",
"tooltip": "Tria el caràcter per defecte que es mostrarà a l'espai entre les lletres"
},
"line-effect": {
"label": "Efecte de la línia",
"submenu": {
"focus": {
"label": "Focus",
"tooltip": "Mostra tan sols la línia actual en blanc"
},
"offset": {
"label": "Desplaçament",
"tooltip": "Desplaçament a la dreta de la línia actual"
},
"scale": {
"label": "Escala",
"tooltip": "Redimensiona la línia actual"
}
},
"tooltip": "Tria l'efecte a aplicar a la línia actual"
},
"precise-timing": {
"label": "Fes que les lletres es sincronitzin a la perfecció",
"tooltip": "Calcula al mil·lisegon l'aparició de la següent línia (pot tenir un petit impacte en el rendiment)"
},
"show-lyrics-even-if-inexact": {
"label": "Mostra la lletra tot i que sigui inexacta",
"tooltip": "Si no es troba la cançó, el plugin torna a intentar obtenir la lletra amb una cerca diferent.\nEl resultat d'aquesta segona cerca podria no ser exacte."
},
"show-time-codes": {
"label": "Mostra els codis de temps",
"tooltip": "Mostra els codis de temps al costat de la lletra"
}
},
"name": "Lletres sincronitzades",
"refetch-btn": {
"fetching": "Obtenint...",
"normal": "Tornar a obtenir la lletra"
},
"warnings": {
"duration-mismatch": "⚠️ - La lletra podria no estar ben sincronitzada, la durada no és coincident.",
"inexact": "⚠️ - La lletra d'aquesta cançó podria no ser exacta",
"instrumental": "⚠️ - Aquesta cançó és instrumental"
}
},
"taskbar-mediacontrol": {
"description": "Controla la reproducció des de la barra de tasques del Windows",
"name": "Control multimèdia a la barra de tasques"
@ -701,7 +797,7 @@
}
}
},
"name": "Commutador de vídeo",
"name": "Botó de vídeo",
"templates": {
"button": "Cançó"
}

View File

@ -220,7 +220,7 @@
},
"album-actions": {
"description": "Přidává Undislike, Dislike, Like, a Unlike tlačítka k aplikování tohoto ke všem písničkám v seznamu písniček nebo albumu",
"name": "Album akce"
"name": "Možnosti Albumu"
},
"album-color-theme": {
"description": "Používá dynamický motiv a vizuální efekty na základě palety barev alba",
@ -279,6 +279,49 @@
},
"name": "Ambientní režim"
},
"api-server": {
"description": "Vlož API server abys mohl ovládat přehrávač",
"dialog": {
"request": {
"buttons": {
"allow": "Povolit",
"deny": "Zakázat"
},
"message": "Povolit {{ID}} ({{origin}}) přístup k API?",
"title": "dotaz na přihlášení k API"
}
},
"menu": {
"auth-strategy": {
"label": "Možnosti přihlášení",
"submenu": {
"auth-at-first": {
"label": "Ověřit při prvním dotazu"
},
"none": {
"label": "Žádná autorizace"
}
}
},
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Port"
}
},
"name": "API server [Beta]",
"prompt": {
"hostname": {
"label": "Zadej hostname API serveru (ve tvaru 0.0.0.0):",
"title": "Hostname"
},
"port": {
"label": "Zadej port API serveru:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Apply compression k audiu (snižuje hlasitost nejhlasitěších částí signálu and zvyšuje hlasitost nejjemnějších částí)",
"name": "Audio kompresor"
@ -415,8 +458,18 @@
"menu": {
"choose-download-folder": "Vybrat složku pro stahování",
"download-finish-settings": {
"label": "Stáhnout po dokončení",
"prompt": {
"last-percent": "Po x procentech",
"last-seconds": "Posledních x vteřin",
"title": "Nastavit kdy stahovat"
},
"submenu": {
"advanced": "Pokoročile"
"advanced": "Pokoročile",
"enabled": "Zapnuto",
"mode": "Časový režim",
"percent": "Procent",
"seconds": "Sekundy"
}
},
"download-playlist": "Stáhnout seznam písniček",
@ -616,11 +669,13 @@
"name": "Scrobbler",
"prompt": {
"lastfm": {
"api-key": "Last,fm API klíč"
"api-key": "Last,fm API klíč",
"api-secret": "Tajný klíč API Last.fm"
},
"listenbrainz": {
"token": {
"label": "Vložte svůj Listenbrainz user token:"
"label": "Vložte svůj Listenbrainz user token:",
"title": "ListenBrainz token"
}
}
}
@ -656,6 +711,22 @@
"description": "Automaticky přeskakuje nehudební části jako intro/outro nebo části hudebních videí, kde nehraje písnčka",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Poskytuje synchronizaci textů do písní, pomocí poskytovatelů, jako je LRClib.",
"errors": {
"fetch": "Při hledání textu došlo k chybě. Prosím skuste to znovu později.",
"not-found": "Žáden text nebyl pro túto skladbu nalezen."
},
"menu": {
"default-text-string": {
"label": "Výchozí znak mezi texty",
"tooltip": "Vyberte výchozí znak pro mezeru mezi texty"
},
"line-effect": {
"label": "Efekt řádku"
}
}
},
"taskbar-mediacontrol": {
"description": "Ovládejte přehrávání z vašeho Windows hlavního panelu",
"name": "Hlavní panel Media Control"

View File

@ -279,6 +279,49 @@
},
"name": "Ambiente-Modus"
},
"api-server": {
"description": "Fügt einen API-Server hinzu, um die Wiedergabe zu steuern",
"dialog": {
"request": {
"buttons": {
"allow": "Erlauben",
"deny": "Ablehnen"
},
"message": "{{ID}} ({{origin}}) den Zugriff zur API erlauben?",
"title": "API-Autorisierungs-Anfrage"
}
},
"menu": {
"auth-strategy": {
"label": "Autorisations-Methode",
"submenu": {
"auth-at-first": {
"label": "Beim ersten Zugriff autorisieren"
},
"none": {
"label": "Keine Autorisierung"
}
}
},
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Port"
}
},
"name": "API-Server [Beta]",
"prompt": {
"hostname": {
"label": "Hostname des API-Servers vergeben (z. B. 0.0.0.0):",
"title": "Hostname"
},
"port": {
"label": "Port des API-Server:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Kompressor auf Audio anwenden (senkt die Lautstärke der lautesten Teile des Signals und hebt die Lautstärke der leisesten Teile an)",
"name": "Audio-Komprimierer"
@ -668,6 +711,59 @@
"description": "Überspringt automatisch nicht-musikalische Teile wie Intro/Outro oder Teile von Musikvideos, in denen der Song nicht gespielt wird",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Bietet synchronisierte Liedtexte zu Songs, verwendet Anbieter wie LRClib.",
"errors": {
"fetch": "⚠️ - Beim Abrufen des Liedtexts ist ein Fehler aufgetreten. Bitte versuchen Sie es später nochmal.",
"not-found": "⚠️ - Kein Text für diesen Song gefunden."
},
"menu": {
"default-text-string": {
"label": "Standardzeichen zwischen Texten",
"tooltip": "Standardzeichen für die Lücke zwischen Songtexten auswählen"
},
"line-effect": {
"label": "Zeileneffekt",
"submenu": {
"focus": {
"label": "Fokussieren",
"tooltip": "Nur aktive Zeile weiß darstellen"
},
"offset": {
"label": "Versatz",
"tooltip": "Verschiebe die aktuelle Zeile nach rechts"
},
"scale": {
"label": "Skalieren",
"tooltip": "Aktuelle Zeile skalieren"
}
},
"tooltip": "Effekt für aktive Zeile auswählen"
},
"precise-timing": {
"label": "Den Songtext perfekt synchronisieren",
"tooltip": "Auf die Millisekunde genau berechnen, wann die nächste Zeile angezeigt werden soll (Kann Einfluss auf die Leistung haben)"
},
"show-lyrics-even-if-inexact": {
"label": "Zeige die Liedtexte, auch wenn sie ungenau sind.",
"tooltip": "Die Erweiterung sucht mit anderen Suchparameter nochmals, wenn der Song nicht gefunden wurde.\nEs kann sein, dass das Ergebnis von der zweiten Anfrage nicht genau ist."
},
"show-time-codes": {
"label": "Zeitkodierungen anzeigen",
"tooltip": "Zeitkodierungen neben Songtext anzeigen"
}
},
"name": "Synchronisierte Texte",
"refetch-btn": {
"fetching": "Hole Songtext...",
"normal": "Songtext neu holen"
},
"warnings": {
"duration-mismatch": "⚠️ - Es kann sein, dass die Synchronization nicht stimmt, da die Songdauer nicht übereinstimmt.",
"inexact": "⚠️ - Es ist Möglich, dass der Songtext für diesen Song nicht übereinstimmt.",
"instrumental": "⚠️ - Das ist ein instrumentales Lied"
}
},
"taskbar-mediacontrol": {
"description": "Wiedergabe aus der Windows Taskleiste kontrollieren",
"name": "Mediensteuerung in der Taskleiste"

View File

@ -2,7 +2,7 @@
"common": {
"console": {
"plugins": {
"execute-failed": "Αποτυχία εκτέλεσης προσθέτου {{pluginName}}::{{contextName}}",
"execute-failed": "Απέτυχε η εκτέλεση του πρόσθετου {{pluginName}}::{{contextName}}",
"executed-at-ms": "Το πρόσθετο {{pluginName}}::{{contextName}} εκτελέστηκε σε {{ms}}ms",
"initialize-failed": "Απέτυχε η αρχικοποίηση του πρόσθετου \"{{pluginName}}\"",
"load-all": "Φόρτωση όλων των πρόσθετων",
@ -36,7 +36,7 @@
"details": "Σφάλμα ανταπόκρισης!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Εκκαθάριση της cache της εφαρμογής"
"clearing-cache-after-20s": "Εκκαθάριση μνήμης cache εφαρμογής"
},
"window": {
"tried-to-render-offscreen": "Το παράθυρο προσπάθησε να απεικονίσει εκτός οθόνης, windowSize={{windowSize}}, displaySize={{displaySize}}, position={{position}}"
@ -45,23 +45,23 @@
"dialog": {
"hide-menu-enabled": {
"detail": "Το μενού είναι κρυμμένο, χρησιμοποιήστε το 'Alt' για να το εμφανίσετε (ή το 'Escape' αν χρησιμοποιείτε το μενού εφαρμογής)",
"message": "Απόκρυψη μενού είναι ενεργοποιημένο",
"title": "Ενεργοποιήθηκε η Απόκρυψη του Μενού"
"message": "Η απόκρυψη μενού είναι ενεργοποιημένη",
"title": "Η απόκρυψη μενού ενεργοποιήθηκε"
},
"need-to-restart": {
"buttons": {
"later": "Αργότερα",
"restart-now": "Επανεκκίνηση Τώρα"
"restart-now": "Επανεκκίνηση τώρα"
},
"detail": "Το πρόσθετο \"{{pluginName}}\" απαιτεί επανεκκίνηση για να ισχύσει",
"message": "Το \"{{pluginName}}\" χρειάζεται επανεκκίνηση",
"title": "Απαιτείται Επανεκκίνηση"
"title": "Απαιτείται επανεκκίνηση"
},
"unresponsive": {
"buttons": {
"quit": "Έξοδος",
"relaunch": "Επανεκκίνηση",
"wait": "Περίμενε"
"wait": "Περιμένετε"
},
"detail": "Λυπούμαστε για την ταλαιπωρία! Παρακαλούμε επιλέξτε τι να κάνετε:",
"message": "Η εφαρμογή δεν ανταποκρίνεται",
@ -69,13 +69,13 @@
},
"update-available": {
"buttons": {
"disable": "Απενεργοποίηση Ενημερώσεων",
"disable": "Απενεργοποίηση ενημερώσεων",
"download": "Λήψη",
"ok": "Εντάξει"
"ok": "OK"
},
"detail": "Μια νέα έκδοση είναι διαθέσιμη και μπορεί να ληφθεί από τον σύνδεσμο {{downloadLink}}",
"message": "Μια νέα έκδοση είναι διαθέσιμη",
"title": "Υπάρχει Διαθέσιμη Ενημέρωση"
"title": "Υπάρχει διαθέσιμη ενημέρωση"
}
},
"menu": {
@ -87,7 +87,7 @@
"go-back": "Πήγαινε πίσω",
"go-forward": "Πήγαινε μπροστά",
"quit": "Έξοδος",
"restart": "Επανεκκίνηση Εφαρμογής"
"restart": "Επανεκκίνηση εφαρμογής"
}
},
"options": {
@ -106,7 +106,7 @@
"prompt": {
"label": "Εισαγωγή διεύθυνσης διακομιστή μεσολάβησης (proxy): (αφήστε κενό για απενεργοποίηση)",
"placeholder": "Παράδειγμα: SOCKS5://127.0.0.1:9999",
"title": "Ορισμός διακομιστή μεσολάβησης (proxy)"
"title": "Ορισμός μεσολάβησης"
}
},
"toggle-dev-tools": "Εναλλαγή DevTools"
@ -135,8 +135,8 @@
"single-instance-lock": "Κλείδωμα Μοναδικής Εκδοχής",
"start-at-login": "Έναρξη κατά την σύνδεση",
"starting-page": {
"label": "Σελίδα Έναρξης",
"unset": "Κατάργηση Ορισμού"
"label": "Σελίδα έναρξης",
"unset": "Κατάργηση ορισμού"
},
"tray": {
"label": "Δίσκος",
@ -148,13 +148,27 @@
}
},
"visual-tweaks": {
"label": "Τροποποιήσεις Εμφάνισης",
"submenu": {
"like-buttons": {
"default": "Default"
"default": "Default",
"force-show": "Αναγκαστική Εμφάνιση",
"hide": "Απόκρυψη",
"label": "Μου αρέσει"
},
"remove-upgrade-button": "Αφαίρεση κουμπιού αναβάθμισης",
"theme": {
"label": "Theme",
"dialog": {
"button": {
"cancel": "Άκυρο",
"remove": "Αφαίρεση"
},
"remove-theme": "Είστε βέβαιοι ότι θέλετε να αφαιρέσετε το προσαρμοσμένο θέμα;",
"remove-theme-message": "Αυτό θα αφαιρέσει το προσαρμοσμένο θέμα"
},
"label": "Θέμα",
"submenu": {
"import-css-file": "Εισαγωγή προσαρμοσμένου αρχείου CSS",
"no-theme": "No theme"
}
}
@ -163,29 +177,68 @@
}
},
"plugins": {
"label": "Plugins"
"enabled": "Ενεργοποιημένο",
"label": "Πρόσθετα",
"new": "ΝΕΟ"
},
"view": {
"label": "View"
"label": "Προβολή",
"submenu": {
"force-reload": "Αναγκαστική Eπαναφόρτωση",
"reload": "Επαναφόρτωση",
"reset-zoom": "Πραγματικό μέγεθος",
"toggle-fullscreen": "Εναλλαγή Πλήρους Οθόνης",
"zoom-in": "Μεγέθυνση",
"zoom-out": "Σμίκρυνση"
}
}
},
"tray": {
"next": "Επόμενο",
"play-pause": "Αναπαραγωγή/Παύση",
"previous": "Προηγούμενο",
"quit": "Έξοδος",
"restart": "Επανεκκίνηση εφαρμογής",
"show": "Εμφάνιση παραθύρου",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Εαν παίξει διαφήμιση κάνει σίγαση του ήχου και θέτει την ταχύτητα αναπαραγωγής στο 16x",
"name": "Γρήγορη Προώθηση Διαφημίσεων"
},
"adblocker": {
"description": "Αποκλεισμός όλων των διαφημίσεων και tracker",
"menu": {
"blocker": "Μέθοδος αποκλεισμού"
},
"name": "Adblocker"
"name": "Μπλοκάρισμα Διαφημίσεων"
},
"album-actions": {
"description": "Προσθέτει κουμπιά Like/Unlike και Dislike/Undislike που δρουν συνολικά σε όλα τα κομμάτια μιας playlist ή ενός άλμπουμ",
"name": "Ενέργειες σε Άλμπουμ"
},
"album-color-theme": {
"description": "Εφαρμόζει ένα δυναμικό θέμα και εφέ με βάση τη χρωματική παλέτα του άλμπουμ",
"menu": {
"color-mix-ratio": {
"label": "Αναλογία μίξης χρώματος",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Album Color Theme"
},
"ambient-mode": {
"description": "Εφαρμόζει ένα εφέ φωτισμού ρίχνοντας απαλά χρώματα από το βίντεο, στο φόντο της οθόνης σας.",
"menu": {
"blur-amount": {
"label": "Ένταση θαμπώματος",
"submenu": {
"pixels": "{{blurAmount}} pixels"
}
@ -197,25 +250,30 @@
}
},
"opacity": {
"label": "Ποσότητα αδιαφάνειας",
"label": "Αδιαφάνεια",
"submenu": {
"percent": "{{opacity}}%"
}
},
"quality": {
"label": "Ποιότητα",
"submenu": {
"pixels": "{{quality}} pixels"
}
},
"size": {
"label": "Μέγεθος",
"submenu": {
"percent": "{{size}}%"
}
},
"smoothness-transition": {
"submenu": {
"during": "Σε {{interpolationTime}} δεύτερα"
"during": "Σε {{interpolationTime}} δευτερόλεπτα"
}
},
"use-fullscreen": {
"label": "Χρήση πλήρους οθόνης"
}
}
},
@ -257,11 +315,14 @@
"description": "Κάνει τα τραγούδια να είναι αυτόματα σε παύση",
"menu": {
"apply-once": "Εφαρμόζεται μόνο στο πρώτο τραγούδι"
}
},
"name": "Απενεργοποίηση αυτόματης αναπαραγωγής"
},
"discord": {
"description": "Δείξτε στους φίλους σας τι ακούτε με το Rich Presence",
"menu": {
"auto-reconnect": "Αυτόματη επανασύνδεση",
"clear-activity": "Εκκαθάριση δραστηριότητας",
"hide-duration-left": "Απόκρυψη της διάρκειας που απομένει",
"hide-github-button": "Απόκρυψη του συνδέσμου προς GitHub",
"set-inactivity-timeout": "Ορισμός χρονικού ορίου αδράνειας"
@ -280,34 +341,113 @@
"buttons": {
"ok": "OK"
},
"message": "Λήψη λίστας αναπαραγωγής {{playlistTitle}}",
"title": "Λήψη ξεκίνησε"
"detail": "{{playlistSize}} τραγούδια)",
"message": "Λήψη της λίστας αναπαραγωγής {{playlistTitle}}",
"title": "Η λήψη ξεκίνησε"
}
},
"feedback": {
"conversion-progress": "Μετατροπή: {{percent}}%",
"download-progress": "Download: {{percent}}%",
"preparing-file": "Προετοιμασία αρχείου…"
"converting": "Μετατροπή…",
"download-info": "Λήψη του {{artist}} - {{title}} [{{videoId}}",
"download-progress": "Λήψη: {{percent}}%",
"downloading": "Λήψη…",
"downloading-counter": "Λήψη {{current}}/{{total}}…",
"downloading-playlist": "Λήψη της λίστας αναπαραγωγής \"{{playlistTitle}}\" - {{playlistSize}} τραγούδια ({{playlistId}})",
"folder-already-exists": "Ο φάκελος {{playlistFolder}} υπάρχει ήδη",
"loading": "Φόρτωση…",
"playlist-is-empty": "Η λίστα αναπραγωγής είναι άδεια",
"preparing-file": "Προετοιμασία αρχείου…",
"saving": "Αποθήκευση…",
"video-id-not-found": "Το βίντεο δεν βρέθηκε"
}
},
"menu": {
"download-finish-settings": {
"prompt": {
"last-seconds": "Τελευταία x δευτερόλεπτα"
},
"submenu": {
"percent": "Ποσοστό",
"seconds": "Δευτερόλεπτα"
}
},
"download-playlist": "Λήψη λίστας αναπαραγωγής",
"skip-existing": "Παράλειψη υπάρχοντων αρχείων"
},
"templates": {
"button": "Download"
"button": "Λήψη"
}
},
"music-together": {
"internal": {
"save": "Αποθήκευση",
"unknown-user": "Άγνωστος χρήστης"
},
"menu": {
"connected-users": "Συνδεδεμένοι χρήστες"
},
"toast": {
"add-song-failed": "Απέτυχε η προσθήκη τραγουδιού",
"remove-song-failed": "Απέτυχε η αφαίρεση τραγουδιού"
}
},
"navigation": {
"name": "Navigation"
"name": "Πλοήγηση"
},
"no-google-login": {
"name": "No Google Login"
},
"notifications": {
"name": "Notifications"
"name": "Ειδοποιήσεις"
},
"picture-in-picture": {
"menu": {
"always-on-top": "Πάντα σε πρώτο πλάνο",
"hotkey": {
"label": "Πλήκτρο πρόσβασης",
"prompt": {
"keybind-options": {
"hotkey": "Πλήκτρο πρόσβασης"
}
}
},
"save-window-position": "Αποθήκευση θέσης παραθύρου",
"save-window-size": "Αποθήκευση μεγέθους παραθύρου"
}
},
"playback-speed": {
"name": "Ταχύτητα αναπαραγωγής",
"templates": {
"button": "Ταχύτητα"
}
},
"precise-volume": {
"prompt": {
"global-shortcuts": {
"keybind-options": {
"decrease": "Μείωση έντασης",
"increase": "Αύξηση έντασης"
}
}
}
},
"quality-changer": {
"backend": {
"dialog": {
"quality-changer": {
"detail": "Τρέχουσα ποιότητα: {{quality}}"
}
}
}
},
"shortcuts": {
"prompt": {
"keybind": {
"keybind-options": {
"next": "Next"
"next": "Επόμενο",
"play-pause": "Αναπαραγωγή / Παύση",
"previous": "Προηγούμενο"
}
}
}

View File

@ -158,18 +158,18 @@
},
"remove-upgrade-button": "Remove upgrade button",
"theme": {
"dialog": {
"button": {
"cancel": "Cancel",
"remove": "Remove"
},
"remove-theme": "Are you sure you want to remove the custom theme?",
"remove-theme-message": "This will remove the custom theme"
},
"label": "Theme",
"submenu": {
"import-css-file": "Import custom CSS file",
"no-theme": "No theme"
},
"dialog": {
"remove-theme": "Are you sure you want to remove the custom theme?",
"remove-theme-message": "This will remove the custom theme",
"button": {
"cancel": "Cancel",
"remove": "Remove"
}
}
}
}
@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "If an ad play it mutes the audio and sets playback speed to 16x",
"name": "Ad Speedup"
},
"adblocker": {
"description": "Block all ads and tracking out of the box",
"menu": {
@ -214,17 +218,12 @@
},
"name": "Ad Blocker"
},
"ad-speedup": {
"name": "Ad Speedup",
"description": "If an ad play it mutes the audio and sets playback speed to 16x"
},
"album-actions": {
"description": "Adds Undislike, Dislike, Like, and Unlike buttons to apply this to all songs in a playlist or album",
"name": "Album Actions"
},
"album-color-theme": {
"description": "Applies a dynamic theme and visual effects based on the album color palette",
"name": "Album Color Theme",
"menu": {
"color-mix-ratio": {
"label": "Color mix ratio",
@ -232,7 +231,8 @@
"percent": "{{ratio}}%"
}
}
}
},
"name": "Album Color Theme"
},
"ambient-mode": {
"description": "Applies a lighting effect by casting gentle colors from the video, into your screens background",
@ -279,6 +279,56 @@
},
"name": "Ambient Mode"
},
"amuse": {
"description": "Adds YouTube Music support for the Amuse now playing widget by 6K Labs",
"name": "Amuse",
"response": {
"query": "Amuse API server is running. GET /query to get song info."
}
},
"api-server": {
"description": "Adds an API server to control the player",
"dialog": {
"request": {
"buttons": {
"allow": "Allow",
"deny": "Deny"
},
"message": "Allow {{ID}} ({{origin}}) to access the API?",
"title": "API authorization request"
}
},
"menu": {
"auth-strategy": {
"label": "Authorization strategy",
"submenu": {
"auth-at-first": {
"label": "Authorize at first request"
},
"none": {
"label": "No authorization"
}
}
},
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Port"
}
},
"name": "API Server [Beta]",
"prompt": {
"hostname": {
"label": "Enter the hostname (like 0.0.0.0) for the API server:",
"title": "Hostname"
},
"port": {
"label": "Enter the port for the API server:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Apply compression to audio (lowers the volume of the loudest parts of the signal and raises the volume of the softest parts)",
"name": "Audio Compressor"
@ -414,24 +464,24 @@
"description": "Downloads MP3 / source audio directly from the interface",
"menu": {
"choose-download-folder": "Choose download folder",
"download-playlist": "Download playlist",
"presets": "Presets",
"skip-existing": "Skip existing files",
"download-finish-settings": {
"label": "Download on finish",
"prompt": {
"last-percent": "After x percent",
"last-seconds": "Last x seconds",
"title": "Configure when to download"
},
"submenu": {
"advanced": "Advanced",
"enabled": "Enabled",
"mode": "Time mode",
"seconds": "Seconds",
"percent": "Percent",
"advanced": "Advanced"
"seconds": "Seconds"
}
},
"prompt": {
"title": "Configure when to download",
"last-seconds": "Last x seconds",
"last-percent": "After x percent"
}
}
"download-playlist": "Download playlist",
"presets": "Presets",
"skip-existing": "Skip existing files"
},
"name": "Downloader",
"renderer": {
@ -609,19 +659,19 @@
"dialog": {
"lastfm": {
"auth-failed": {
"title": "Authentication Failed",
"message": "Failed to authenticate with Last.fm\nHide the popup until the next restart."
"message": "Failed to authenticate with Last.fm\nHide the popup until the next restart.",
"title": "Authentication Failed"
}
}
},
"menu": {
"scrobble-other-media": "Scrobble other media",
"lastfm": {
"api-settings": "Last.fm API Settings"
},
"listenbrainz": {
"token": "Enter ListenBrainz user token"
}
},
"scrobble-other-media": "Scrobble other media"
},
"name": "Scrobbler",
"prompt": {
@ -670,19 +720,59 @@
},
"synced-lyrics": {
"description": "Provides synced lyrics to songs, using providers like LRClib.",
"name": "Synced Lyrics",
"errors": {
"fetch": "⚠️ - An error occurred while fetching the lyrics. Please try again later.",
"not-found": "⚠️ - No lyrics found for this song."
"fetch": "⚠️\tAn error occurred while fetching the lyrics.\n\tPlease try again later.",
"not-found": "⚠️ No lyrics found for this song."
},
"menu": {
"default-text-string": {
"label": "Default character between lyrics",
"tooltip": "Choose the default character to use for the gap between lyrics"
},
"line-effect": {
"label": "Line effect",
"submenu": {
"fancy": {
"label": "Fancy",
"tooltip": "Use large, app-like effects on the current line"
},
"focus": {
"label": "Focus",
"tooltip": "Make only the current line white"
},
"offset": {
"label": "Offset",
"tooltip": "Offset on the right the current line"
},
"scale": {
"label": "Scale",
"tooltip": "Scale the current line"
}
},
"tooltip": "Choose the effect to apply to the current line"
},
"precise-timing": {
"label": "Make the lyrics perfectly synced",
"tooltip": "Calculate to the milisecond the display of the next line (can have a small impact on performance)"
},
"show-lyrics-even-if-inexact": {
"label": "Show lyrics even if inexact",
"tooltip": "If the song is not found, the plugin tries again with a different search query.\nThe result from the second attempt may not be exact."
},
"show-time-codes": {
"label": "Show time codes",
"tooltip": "Show the time codes next to the lyrics"
}
},
"name": "Synced Lyrics",
"refetch-btn": {
"fetching": "Fetching...",
"normal": "Refetch lyrics"
},
"warnings": {
"instrumental": "⚠️ - This is an instrumental song",
"duration-mismatch": "⚠️ - The lyrics may be out of sync due to a duration mismatch.",
"inexact": "⚠️ - The lyrics for this song may not be exact",
"duration-mismatch": "⚠️ - The lyrics may be out of sync due to a duration mismatch."
},
"refetch-btn": {
"normal": "Refetch lyrics",
"fetching": "Fetching..."
"instrumental": "⚠️ - This is an instrumental song"
}
},
"taskbar-mediacontrol": {
@ -729,6 +819,18 @@
"visualizer-type": "Visualizer Type"
},
"name": "Visualizer"
},
"equalizer": {
"description": "Adds an equalizer to the player",
"name": "Equalizer",
"menu": {
"presets": {
"label": "Presets",
"list": {
"bass-booster": "Bass booster"
}
}
}
}
}
}

View File

@ -279,6 +279,49 @@
},
"name": "Modo ambiente"
},
"api-server": {
"description": "Añade un servidor API para controlar el reproductor",
"dialog": {
"request": {
"buttons": {
"allow": "Permitir",
"deny": "Denegar"
},
"message": "¿Permitir {{ID}} ({{origin}}) acceder a la API?",
"title": "Petición de autorización API"
}
},
"menu": {
"auth-strategy": {
"label": "Estrategia de autorización",
"submenu": {
"auth-at-first": {
"label": "Autorizar la primera solicitud"
},
"none": {
"label": "Sin autorización"
}
}
},
"hostname": {
"label": "Nombre del host"
},
"port": {
"label": "Puerto"
}
},
"name": "Servidor API [Beta]",
"prompt": {
"hostname": {
"label": "Introduzca el nombre de host (como 0.0.0.0) para el servidor API:",
"title": "Nombre de host"
},
"port": {
"label": "Introduzca el puerto para el servidor API:",
"title": "Puerto"
}
}
},
"audio-compressor": {
"description": "Aplicar compresión al audio (reduce la diferencia entre las partes más fuertes y más suaves de una pista para que tenga un nivel más consistente)",
"name": "Compresor de audio"
@ -441,6 +484,18 @@
"button": "Descargar"
}
},
"equalizer": {
"description": "Añade un ecualizador al reproductor",
"menu": {
"presets": {
"label": "Ajustes preestablecidos",
"list": {
"bass-booster": "Amplificador de graves"
}
}
},
"name": "Ecualizador"
},
"exponential-volume": {
"description": "Hace que el control deslizante de volumen sea exponencial para que sea más fácil seleccionar volúmenes más bajos.",
"name": "Volumen exponencial"
@ -668,6 +723,59 @@
"description": "Salta automáticamente las partes no musicales como la introducción/final o secciones de videos musicales donde la canción no está sonando",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Proporciona letras de canciones sincronizadas, utilizando proveedores como LRClib.",
"errors": {
"fetch": "⚠️ - Se ha producido un error al descargar la letra. Por favor, vuelve a intentarlo más tarde.",
"not-found": "⚠️ - No se ha encontrado ninguna letra para esta canción."
},
"menu": {
"default-text-string": {
"label": "Carácter predeterminado entre letras",
"tooltip": "Elige el carácter predeterminado que se utilizará para el espacio entre letras"
},
"line-effect": {
"label": "Efecto de la línea",
"submenu": {
"focus": {
"label": "Enfoque",
"tooltip": "Mostrar solo la línea actual en blanco"
},
"offset": {
"label": "Desplazamiento",
"tooltip": "Desplazamiento a la derecha de la línea actual"
},
"scale": {
"label": "Escala",
"tooltip": "Escala de la línea actual"
}
},
"tooltip": "Elige el efecto que deseas aplicar a la línea actual"
},
"precise-timing": {
"label": "Haz que la letra esté perfectamente sincronizada",
"tooltip": "Calcular al milisegundo la visualización de la línea siguiente (puede tener un pequeño impacto en el rendimiento)"
},
"show-lyrics-even-if-inexact": {
"label": "Mostrar la letra aunque sea inexacta",
"tooltip": "Si no se encuentra la canción, el complemento vuelve a intentarlo con una búsqueda diferente.\nEl resultado del segundo intento puede no ser exacto."
},
"show-time-codes": {
"label": "Visualización del código de tiempo",
"tooltip": "Mostrar los códigos de tiempo junto a la letra"
}
},
"name": "Letras sincronizadas",
"refetch-btn": {
"fetching": "Recuperando...",
"normal": "Volver a buscar letras"
},
"warnings": {
"duration-mismatch": "⚠️ - La letra puede estar desincronizada debido a un desajuste en la duración.",
"inexact": "⚠️ - La letra de esta canción puede no ser exacta",
"instrumental": "⚠️ - Se trata de una canción instrumental"
}
},
"taskbar-mediacontrol": {
"description": "Controla la reproducción desde la barra de tareas de Windows",
"name": "Control de medios de la barra de tareas"

195
src/i18n/resources/et.json Normal file
View File

@ -0,0 +1,195 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "{{pluginName}}::{{contextName}} lisamooduli käivitamine ei õnnestunud",
"executed-at-ms": "{{pluginName}}::{{contextName}} lisamoodul käivitus {{ms}} millisekundiga",
"initialize-failed": "„{{pluginName}}“ lisamooduli töö alustamine ei õnnestunud",
"load-all": "Laadime kõiki lisamooduleid",
"load-failed": "„{{pluginName}}“ lisamooduli laadimine ei õnnestunud",
"loaded": "„{{pluginName}}“ lisamoodul on laaditud",
"unload-failed": "„{{pluginName}}“ lisamooduli mälust eemaldamine ei õnnestunud",
"unloaded": "„{{pluginName}}“ lisamoodul on mälust eemaldatud"
}
}
},
"language": {
"code": "et",
"local-name": "Eesti",
"name": "Estonian"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "Laadimine lõppes, arendaja tarvikud on avatud"
},
"i18n": {
"loaded": "i18n on laaditud"
},
"second-instance": {
"receive-command": "„{{command}}“ käsk on vastu võetud"
},
"theme": {
"css-file-not-found": "CSS faili „{{cssFile}}“ pole olemas, seega eirame eelistust"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "Menüü on peidetud ja „Alt“ klahviga saad ta nähtavaks (rakenduse-siseses menüüs „Esc“ klahviga)",
"message": "Menüü peitmine on sisselülitatud",
"title": "Menüü peitmine on sisselülitatud"
},
"need-to-restart": {
"buttons": {
"later": "Hiljem",
"restart-now": "Taaskäivita kohe"
},
"detail": "„{{pluginName}}“ lisamooduli sisselülitamine eeldab rakenduse taaskäivitamist",
"message": "„{{pluginName}}“ lisamoodul eeldab rakenduse taaskäivitamist",
"title": "Palun käivita rakendus uuesti"
},
"unresponsive": {
"buttons": {
"quit": "Välju",
"relaunch": "Käivita uuesti",
"wait": "Oota"
}
}
},
"menu": {
"navigation": {
"label": "Liikumine",
"submenu": {
"copy-current-url": "Kopeeri esitamisel oleva pala URL",
"go-back": "Mine tagasi",
"go-forward": "Mine edasi",
"quit": "Välju",
"restart": "Käivita rakendus uuesti"
}
},
"options": {
"label": "Seadistused",
"submenu": {
"advanced-options": {
"label": "Lisaseadistused",
"submenu": {
"auto-reset-app-cache": "Rakenduse käivitamisel lähtesta puhverdatud andmed",
"disable-hardware-acceleration": "Lülita raudvaraline kiirendamine välja",
"edit-config-json": "Muuda config.json faili"
}
}
}
},
"plugins": {
"label": "Lisamoodulid",
"new": "UUS"
},
"view": {
"submenu": {
"zoom-in": "Suumi sisse",
"zoom-out": "Suumi välja"
}
}
},
"tray": {
"next": "Edasi",
"play-pause": "Esita/Peata esitus",
"previous": "Eelmine",
"quit": "Välju",
"restart": "Käivita rakendus uuesti",
"show": "Näita akent",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Reklaami esitamisel summutatakse heli ja keritakse edasi 16-kordse kiirusega",
"name": "Reklaamikiirendaja"
},
"adblocker": {
"description": "Blokeeri kõik reklaamid ja jälitajad",
"menu": {
"blocker": "Blokeerijad"
},
"name": "Reklaamiblokeerija"
},
"ambient-mode": {
"menu": {
"opacity": {
"submenu": {
"percent": "{{opacity}}%"
}
},
"quality": {
"label": "Kvaliteet",
"submenu": {
"pixels": "{{quality}} pikslit"
}
}
}
},
"blur-nav-bar": {
"description": "Muudab navigatsiooniriba läbipaistavaks ja hägusaks",
"name": "Hägus navigatsiooniriba"
},
"lyrics-genius": {
"description": "Lisa enamustele lugudele laulusõnad",
"menu": {
"romanized-lyrics": "Latiniseeritud laulusõnad"
},
"name": "Lyrics Genius",
"renderer": {
"fetched-lyrics": "Leidsime Geeniuse jaoks ühed laulusõnad"
}
},
"navigation": {
"name": "Liikumine"
},
"scrobbler": {
"description": "Lisa kraasimise tugi (last.fm, Listenbrainz, jne)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Last.fm'i autentimine ei õnnestunud\nPeida hüpikaken järgmise taaskäivituseni.",
"title": "Autentimine ei õnnestunud"
}
}
},
"menu": {
"lastfm": {
"api-settings": "Last.fm API seadistused"
},
"listenbrainz": {
"token": "Sisesta ListenBrainz'i kasutaja tunnusluba"
},
"scrobble-other-media": "Kraasi muud meediat"
},
"name": "Kraasija",
"prompt": {
"lastfm": {
"api-key": "Last.fm API võti",
"api-secret": "Last.fm API saladus"
},
"listenbrainz": {
"token": {
"label": "Sisesta oma ListenBrainz'i tunnusluba:",
"title": "ListenBrainz'i tunnusluba"
}
}
}
},
"synced-lyrics": {
"menu": {
"show-lyrics-even-if-inexact": {
"tooltip": "Kui lugu ei leidu, siis lisamoodul üritab uut otsingut teistsuguse päringuga.\nTeise katse puhul tulemused ei pruugi olla väga täpsed."
}
}
},
"tuna-obs": {
"description": "Lõimimine OBSi Tuna lisamooduliga"
}
}
}

585
src/i18n/resources/fa.json Normal file
View File

@ -0,0 +1,585 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "اجرای افزونه {{pluginName}}::{{contextName}} با خطا مواجه شد",
"executed-at-ms": "افزونه {{pluginName}}::{{contextName}} در {{ms}} میلی‌ثانیه اجرا شد",
"initialize-failed": "افزونه \"{{pluginName}}\" با خطا در حین مقداردهی اولیه مواجه شد",
"load-all": "در حال بارگذاری تمامی افزونه‌ها",
"load-failed": "افزونه \"{{pluginName}}\" بارگیری نشد",
"loaded": "افزونه \"{{pluginName}}\" بارگیری شد",
"unload-failed": "افزونه \"{{pluginName}}\" بارگذاری نشد",
"unloaded": "افزونه \"{{pluginName}}\" بارگذاری شد"
}
}
},
"language": {
"code": "fa",
"local-name": "فارسی",
"name": "Persian"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "بارگذاری کامل شد. DevTools باز شد"
},
"i18n": {
"loaded": "i18n بارگذاری شد"
},
"second-instance": {
"receive-command": "دریافت فرمان از طریق پروتکل: \"{{command}}\""
},
"theme": {
"css-file-not-found": "فایل CSS \"{{cssFile}}\" وجود ندارد، نادیده گرفته شد"
},
"unresponsive": {
"details": "خطای عدم پاسخگویی!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "پاکسازی حافظه کش برنامه"
},
"window": {
"tried-to-render-offscreen": "پنجره تلاش کرد خارج از صفحه نمایش داده شود، اندازه پنجره={{windowSize}}، اندازه نمایشگر={{displaySize}}، موقعیت={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "منو مخفی است، از 'Alt' برای نمایش آن استفاده کنید (یا 'Escape' اگر از منوی داخل برنامه استفاده می‌کنید)",
"message": "پنهان‌سازی منو فعال است",
"title": "پنهان کردن منو فعال شد"
},
"need-to-restart": {
"buttons": {
"later": "بعداً",
"restart-now": "هم‌اکنون راه‌اندازی مجدد کنید"
},
"detail": "افزونه \"{{pluginName}}\" برای اعمال تغییرات نیاز به راه‌اندازی مجدد دارد",
"message": "\"{{pluginName}}\" نیاز به راه‌اندازی مجدد دارد",
"title": "نیاز به راه‌اندازی مجدد"
},
"unresponsive": {
"buttons": {
"quit": "خروج",
"relaunch": "راه‌اندازی مجدد",
"wait": "منتظر بمانید"
},
"detail": "از بابت این مشکل متأسفیم! لطفاً انتخاب کنید که چه کاری انجام دهید:",
"message": "برنامه پاسخی نمی‌دهد",
"title": "پنجره بدون پاسخ"
},
"update-available": {
"buttons": {
"disable": "غیرفعال کردن به‌روزرسانی‌ها",
"download": "دانلود",
"ok": "تأیید"
},
"detail": "نسخه جدیدی در دسترس است و می‌توان آن را از {{downloadLink}} دانلود کرد",
"message": "نسخه جدیدی در دسترس است",
"title": "به‌روزرسانی موجود است"
}
},
"menu": {
"about": "درباره",
"navigation": {
"label": "ناوبری",
"submenu": {
"copy-current-url": "کپی کردن URL فعلی",
"go-back": "بازگشت",
"go-forward": "حرکت به جلو",
"quit": "خروجی",
"restart": "راه‌اندازی مجدد برنامه"
}
},
"options": {
"label": "گزینه‌ها",
"submenu": {
"advanced-options": {
"label": "گزینه‌های پیشرفته",
"submenu": {
"auto-reset-app-cache": "ریست کردن حافظه کش برنامه هنگام شروع",
"disable-hardware-acceleration": "غیرفعال کردن شتاب سخت‌افزاری",
"edit-config-json": "ویرایش config.json",
"override-user-agent": "تغییر User-Agent",
"restart-on-config-changes": "راه‌اندازی مجدد در صورت تغییرات در پیکربندی",
"set-proxy": {
"label": "تنظیم پراکسی",
"prompt": {
"label": "آدرس پراکسی را وارد کنید: (برای غیرفعال کردن، خالی بگذارید)",
"placeholder": "مثال: SOCKS5://127.0.0.1:9999",
"title": "تنظیم پراکسی"
}
},
"toggle-dev-tools": "باز کردن DevTools"
}
},
"always-on-top": "همیشه در بالا",
"auto-update": "به‌روزرسانی خودکار",
"hide-menu": {
"dialog": {
"message": "منو در اجرای بعدی مخفی خواهد بود، از [Alt] برای نمایش استفاده کنید (یا [`] اگر از منوی داخل برنامه استفاده می‌کنید)",
"title": "پنهان‌سازی منو فعال شد"
},
"label": "پنهان کردن منو"
},
"language": {
"dialog": {
"message": "زبان پس از راه‌اندازی مجدد تغییر خواهد کرد",
"title": "زبان تغییر کرد"
},
"label": "زبان",
"submenu": {
"to-help-translate": "می‌خواهید به ترجمه کمک کنید؟ اینجا کلیک کنید"
}
},
"resume-on-start": "ادامه آخرین آهنگ هنگام شروع برنامه",
"single-instance-lock": "قفل تنها یک نمونه",
"start-at-login": "شروع هنگام ورود",
"starting-page": {
"label": "صفحه شروع",
"unset": "لغو تنظیم"
},
"tray": {
"label": "نوار",
"submenu": {
"disabled": "غیرفعال",
"enabled-and-hide-app": "فعال و پنهان کردن برنامه",
"enabled-and-show-app": "فعال و نمایش برنامه",
"play-pause-on-click": "پخش/توقف با کلیک"
}
},
"visual-tweaks": {
"label": "تغییرات ظاهری",
"submenu": {
"like-buttons": {
"default": "پیش‌فرض",
"force-show": "اجبار به نمایش",
"hide": "پنهان کردن",
"label": "دکمه‌های پسندیدن"
},
"remove-upgrade-button": "حذف دکمه ارتقا",
"theme": {
"dialog": {
"button": {
"cancel": "لغو",
"remove": "حذف"
},
"remove-theme": "آیا مطمئن هستید که می‌خواهید تم سفارشی را حذف کنید؟",
"remove-theme-message": "این کار تم سفارشی را حذف خواهد کرد"
},
"label": "تم",
"submenu": {
"import-css-file": "وارد کردن فایل CSS سفارشی",
"no-theme": "بدون تم"
}
}
}
}
}
},
"plugins": {
"enabled": "فعال",
"label": "افزونه‌ها",
"new": "جدید"
},
"view": {
"label": "مشاهده",
"submenu": {
"force-reload": "اجبار به بارگذاری مجدد",
"reload": "بارگذاری مجدد",
"reset-zoom": "اندازه واقعی",
"toggle-fullscreen": "تغییر به تمام‌صفحه",
"zoom-in": "بزرگنمایی",
"zoom-out": "کوچکنمایی"
}
}
},
"tray": {
"next": "بعدی",
"play-pause": "پخش/توقف",
"previous": "قبلی",
"quit": "خروج",
"restart": "راه‌اندازی مجدد برنامه",
"show": "نمایش پنجره",
"tooltip": {
"default": "یوتیوب موسیقی",
"with-song-info": "یوتیوب موسیقی: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "اگر تبلیغ پخش شود، صدا را بی‌صدا کرده و سرعت پخش را به 16 برابر افزایش می‌دهد",
"name": "سرعت‌دهی به تبلیغ"
},
"adblocker": {
"description": "مسدود کردن تمامی تبلیغات و ردیابی‌ها از ابتدا",
"menu": {
"blocker": "مسدودکننده"
},
"name": "مسدودکننده تبلیغات"
},
"album-actions": {
"description": "افزودن دکمه‌های \"برگرفتن ناپسند\"، \"ناپسند\"، \"پسند\"، و \"حذف پسند\" برای اعمال آنها روی همه آهنگ‌ها در یک فهرست پخش یا آلبوم",
"name": "عملیات آلبوم"
},
"album-color-theme": {
"description": "اعمال یک تم پویا و جلوه‌های بصری بر اساس پالت رنگ آلبوم",
"menu": {
"color-mix-ratio": {
"label": "نسبت ترکیب رنگ",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "تم رنگ آلبوم"
},
"ambient-mode": {
"description": "اعمال یک اثر نوری با پخش رنگ‌های ملایم از ویدئو به پس‌زمینه صفحه نمایش شما",
"menu": {
"blur-amount": {
"label": "میزان تاری",
"submenu": {
"pixels": "{{blurAmount}} پیکسل"
}
},
"buffer": {
"label": "بافر",
"submenu": {
"buffer": "{{buffer}}"
}
},
"opacity": {
"label": "شفافیت"
},
"quality": {
"label": "کیفیت",
"submenu": {
"pixels": "{{quality}} پیکسل"
}
},
"size": {
"label": "اندازه"
},
"smoothness-transition": {
"label": "انتقال نرمی",
"submenu": {
"during": "در طول {{interpolationTime}} ثانیه"
}
},
"use-fullscreen": {
"label": "استفاده از تمام‌صفحه"
}
},
"name": "حالت محیطی"
},
"api-server": {
"description": "افزودن یک سرور API برای کنترل پخش‌کننده",
"dialog": {
"request": {
"buttons": {
"allow": "اجازه",
"deny": "رد کردن"
},
"message": "اجازه دادن به {{ID}} ({{origin}}) برای دسترسی به API؟",
"title": "درخواست مجوز API"
}
},
"menu": {
"auth-strategy": {
"label": "استراتژی مجوز",
"submenu": {
"auth-at-first": {
"label": "مجوز در اولین درخواست"
},
"none": {
"label": "بدون نیاز به مجوز"
}
}
},
"hostname": {
"label": "نام میزبان"
},
"port": {
"label": "پورت"
}
},
"name": "سرور API [بتا]",
"prompt": {
"hostname": {
"label": "نام میزبان را برای سرور API وارد کنید (مثل 0.0.0.0):",
"title": "نام میزبان"
},
"port": {
"label": "پورت را برای سرور API وارد کنید:",
"title": "پورت"
}
}
},
"audio-compressor": {
"description": "اعمال فشرده‌سازی به صدا (کاهش حجم بلندترین بخش‌های سیگنال و افزایش حجم بخش‌های نرم‌تر)",
"name": "فشرده‌ساز صدا"
},
"blur-nav-bar": {
"description": "شفاف و محو کردن نوار ناوبری",
"name": "محو کردن نوار ناوبری"
},
"bypass-age-restrictions": {
"description": "دور زدن تأیید سن یوتیوب",
"name": "دور زدن محدودیت‌های سنی"
},
"captions-selector": {
"description": "انتخاب زیرنویس برای آهنگ‌های یوتیوب موسیقی",
"menu": {
"autoload": "به طور خودکار انتخاب آخرین زیرنویس استفاده شده",
"disable-captions": "بدون زیرنویس به صورت پیش‌فرض"
},
"name": "انتخاب‌کننده زیرنویس",
"prompt": {
"selector": {
"label": "زبان زیرنویس فعلی: {{language}}",
"none": "هیچ‌کدام",
"title": "انتخاب زبان زیرنویس"
}
},
"templates": {
"title": "باز کردن انتخاب‌کننده زیرنویس"
}
},
"compact-sidebar": {
"description": "همیشه نوار کناری را در حالت فشرده تنظیم کن",
"name": "نوار کناری فشرده"
},
"crossfade": {
"description": "تداخل بین آهنگ‌ها",
"menu": {
"advanced": "پیشرفته"
},
"name": "تداخل [بتا]",
"prompt": {
"options": {
"multi-input": {
"fade-in-duration": "مدت زمان ورود تدریجی (میلی‌ثانیه)",
"fade-out-duration": "مدت زمان خروج تدریجی (میلی‌ثانیه)",
"fade-scaling": {
"label": "مقیاس‌بندی ورود تدریجی",
"linear": "خطی",
"logarithmic": "لگاریتمی"
},
"seconds-before-end": "تداخل N ثانیه قبل از پایان"
},
"title": "گزینه‌های تداخل"
}
}
},
"disable-autoplay": {
"description": "شروع آهنگ در حالت \"توقف\"",
"menu": {
"apply-once": "فقط در شروع اعمال می‌شود"
},
"name": "غیرفعال کردن پخش خودکار"
},
"discord": {
"backend": {
"already-connected": "تلاش برای اتصال با اتصال فعال",
"connected": "متصل به Discord",
"disconnected": "قطع اتصال از Discord"
},
"description": "نمایش آنچه گوش می‌دهید به دوستان با Rich Presence",
"menu": {
"auto-reconnect": "اتصال خودکار مجدد",
"clear-activity": "پاک کردن فعالیت",
"clear-activity-after-timeout": "پاک کردن فعالیت پس از تایم‌اوت",
"connected": "متصل",
"disconnected": "قطع شده",
"hide-duration-left": "مخفی کردن مدت زمان باقی‌مانده",
"hide-github-button": "مخفی کردن دکمه لینک GitHub",
"play-on-youtube-music": "پخش در یوتیوب موسیقی",
"set-inactivity-timeout": "تنظیم تایم‌اوت عدم فعالیت"
},
"name": "Rich Presence در Discord",
"prompt": {
"set-inactivity-timeout": {
"label": "ورود تایم‌اوت عدم فعالیت به ثانیه:",
"title": "تنظیم تایم‌اوت عدم فعالیت"
}
}
},
"downloader": {
"backend": {
"dialog": {
"error": {
"buttons": {
"ok": "تأیید"
},
"message": "اوه! متاسفیم، دانلود شکست خورد…",
"title": "خطا در دانلود!"
},
"start-download-playlist": {
"buttons": {
"ok": "تأیید"
},
"detail": "({{playlistSize}} آهنگ)",
"message": "دانلود فهرست پخش {{playlistTitle}}",
"title": "دانلود شروع شد"
}
},
"feedback": {
"conversion-progress": "تبدیل: {{percent}}%",
"converting": "در حال تبدیل…",
"done": "انجام شد: {{filePath}}",
"download-info": "در حال دانلود {{artist}} - {{title}} [{{videoId}}",
"download-progress": "دانلود: {{percent}}%",
"downloading": "در حال دانلود…",
"downloading-counter": "در حال دانلود {{current}}/{{total}}…",
"downloading-playlist": "در حال دانلود فهرست پخش \"{{playlistTitle}}\" - {{playlistSize}} آهنگ ({{playlistId}})",
"error-while-downloading": "خطا در دانلود \"{{author}} - {{title}}\": {{error}}",
"folder-already-exists": "پوشه {{playlistFolder}} از قبل وجود دارد",
"getting-playlist-info": "در حال دریافت اطلاعات فهرست پخش…",
"loading": "در حال بارگذاری…",
"playlist-has-only-one-song": "فهرست پخش فقط یک آیتم دارد، به طور مستقیم دانلود می‌شود",
"playlist-id-not-found": "شناسه فهرست پخش یافت نشد",
"playlist-is-empty": "فهرست پخش خالی است",
"playlist-is-mix-or-private": "خطا در دریافت اطلاعات فهرست پخش: اطمینان حاصل کنید که فهرست پخش خصوصی یا \"مختص شما\" نباشد\n\n{{error}}",
"preparing-file": "در حال آماده‌سازی فایل…",
"saving": "در حال ذخیره‌سازی…",
"trying-to-get-playlist-id": "تلاش برای دریافت شناسه فهرست پخش: {{playlistId}}",
"video-id-not-found": "ویدئو یافت نشد",
"writing-id3": "در حال نوشتن تگ‌های ID3…"
}
},
"description": "دانلود MP3 / صدای منبع به طور مستقیم از رابط",
"menu": {
"choose-download-folder": "انتخاب پوشه دانلود",
"download-finish-settings": {
"label": "دانلود پس از پایان",
"prompt": {
"last-percent": "پس از x درصد",
"last-seconds": "آخرین x ثانیه",
"title": "پیکربندی زمان دانلود"
},
"submenu": {
"advanced": "پیشرفته",
"enabled": "فعال",
"mode": "حالت زمان",
"percent": "درصد",
"seconds": "ثانیه"
}
},
"download-playlist": "دانلود فهرست پخش",
"presets": "پیش‌تنظیم‌ها",
"skip-existing": "رد کردن فایل‌های موجود"
},
"name": "دانلودر",
"renderer": {
"can-not-update-progress": "امکان به‌روزرسانی پیشرفت نیست"
},
"templates": {
"button": "دانلود"
}
},
"exponential-volume": {
"description": "نوار لغزنده حجم را به صورت نمایی می‌سازد تا انتخاب حجم‌های پایین‌تر آسان‌تر شود.",
"name": "حجم نمایی"
},
"in-app-menu": {
"description": "منوها را به صورت جذاب، تاریک یا با رنگ آلبوم نمایش می‌دهد",
"menu": {
"hide-dom-window-controls": "کنترل‌های پنجره DOM را مخفی کن"
},
"name": "منوی داخل برنامه"
},
"lumiastream": {
"description": "افزودن پشتیبانی از Lumia Stream",
"name": "Lumia Stream [بتا]"
},
"lyrics-genius": {
"description": "افزودن پشتیبانی از متن آهنگ برای بیشتر آهنگ‌ها",
"menu": {
"romanized-lyrics": "متن رومی‌شده"
},
"name": "متن آهنگ Genius",
"renderer": {
"fetched-lyrics": "متن آهنگ از Genius بازیابی شد"
}
},
"music-together": {
"description": "اشتراک‌گذاری فهرست پخش با دیگران. وقتی میزبان آهنگی را پخش می‌کند، همه بقیه همان آهنگ را می‌شنوند",
"dialog": {
"enter-host": "شناسه میزبان را وارد کنید"
},
"internal": {
"save": "ذخیره",
"track-source": "منبع آهنگ",
"unknown-user": "کاربر ناشناس"
},
"menu": {
"click-to-copy-id": "کپی کردن شناسه میزبان",
"close": "بستن Music Together",
"connected-users": "کاربران متصل",
"disconnect": "قطع اتصال Music Together",
"empty-user": "هیچ کاربر متصلی وجود ندارد",
"host": "میزبان Music Together",
"join": "پیوستن به Music Together",
"permission": {
"all": "اجازه دادن به مهمانان برای کنترل فهرست پخش و پخش‌کننده",
"host-only": "فقط میزبان می‌تواند فهرست پخش و پخش‌کننده را کنترل کند",
"playlist": "اجازه دادن به مهمانان برای کنترل فهرست پخش"
},
"set-permission": "تغییر مجوز کنترل",
"status": {
"disconnected": "قطع اتصال",
"guest": "متصل به عنوان مهمان",
"host": "متصل به عنوان میزبان"
}
},
"name": "Music Together [بتا]",
"toast": {
"add-song-failed": "افزودن آهنگ با شکست مواجه شد",
"closed": "Music Together بسته شد",
"disconnected": "قطع اتصال Music Together",
"host-failed": "میزبانی Music Together با شکست مواجه شد",
"id-copied": "شناسه میزبان به کلیپ‌بورد کپی شد",
"id-copy-failed": "کپی شناسه میزبان به کلیپ‌بورد با شکست مواجه شد",
"join-failed": "پیوستن به Music Together با شکست مواجه شد",
"joined": "به Music Together پیوست",
"permission-changed": "مجوز Music Together به \"{{permission}}\" تغییر یافت",
"remove-song-failed": "حذف آهنگ با شکست مواجه شد",
"user-connected": "{{name}} به Music Together پیوست",
"user-disconnected": "{{name}} Music Together را ترک کرد"
}
},
"navigation": {
"description": "بعدی/قبلی به طور مستقیم در رابط یکپارچه شده‌اند، مانند مرورگر مورد علاقه شما",
"name": "ناوبری"
},
"no-google-login": {
"description": "حذف دکمه‌های ورود به سیستم Google و لینک‌ها از رابط",
"name": "بدون ورود به Google"
},
"notifications": {
"description": "نمایش اعلان هنگامی که آهنگی شروع به پخش می‌کند (اعلان‌های تعاملی در ویندوز در دسترس هستند)",
"menu": {
"interactive": "اعلان‌های تعاملی",
"interactive-settings": {
"label": "تنظیمات تعاملی",
"submenu": {
"hide-button-text": "مخفی کردن متن دکمه",
"refresh-on-play-pause": "تازه‌سازی در پخش/توقف",
"tray-controls": "باز/بسته شدن با کلیک روی سینی"
}
},
"priority": "اولویت اعلان",
"toast-style": "سبک Toast",
"unpause-notification": "نمایش اعلان هنگام از سرگیری پخش"
},
"name": "اعلان‌ها"
},
"picture-in-picture": {
"description": "اجازه می‌دهد تا برنامه به حالت تصویر در تصویر تغییر کند",
"menu": {
"always-on-top": "همیشه در بالا"
}
}
}
}

View File

@ -201,16 +201,22 @@
"restart": "I-restart ang App",
"show": "Ipakita ang window",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Pag mag-play ng ad, I-mute ang audio at i-set ang bilis ng playback ng 16x"
"description": "Pag mag-play ng ad, I-mute ang audio at i-set ang bilis ng playback ng 16x",
"name": "Pagbilis ng Ad"
},
"adblocker": {
"description": "I-block ang lahat ng ad at tracking"
"description": "I-block ang lahat ng ad at tracking",
"menu": {
"blocker": "Blocker"
},
"name": "Pag-block ng Ad"
},
"album-actions": {
"description": "Idadagdag ang Undislike, Dislike, Like, at Unlike na button para ilapat ito sa lahat ng kanta sa isang playlist o album",
@ -220,7 +226,10 @@
"description": "Naglalapat ng dynamic na tema at visual effect batay sa color palette ng album",
"menu": {
"color-mix-ratio": {
"label": "Ratio ng paghahalo ng kulay"
"label": "Ratio ng paghahalo ng kulay",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Tema ng Kulay ng Album"
@ -259,6 +268,7 @@
}
},
"smoothness-transition": {
"label": "Ayos ng Transisyon",
"submenu": {
"during": "Habang {{interpolationTime}} s"
}
@ -266,6 +276,50 @@
"use-fullscreen": {
"label": "Gumamit ng fullscreen"
}
},
"name": "Ambient Mode"
},
"api-server": {
"description": "Nagdadagdag ng API Server upang kontrolin ang player",
"dialog": {
"request": {
"buttons": {
"allow": "Payagan",
"deny": "Tanggihan"
},
"message": "Payagan ang {{ID}} ({{origin}}) upang ma-access ang API?",
"title": "Awtorisasyon ng API request"
}
},
"menu": {
"auth-strategy": {
"label": "Estratehiya ng awtorisasyon",
"submenu": {
"auth-at-first": {
"label": "Mag-autorisa sa unang request"
},
"none": {
"label": "Walang awtorisasyon"
}
}
},
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Port"
}
},
"name": "API Server [Beta]",
"prompt": {
"hostname": {
"label": "Itala ang hostname (tulad ng 0.0.0.0) para sa API server:",
"title": "Hostname"
},
"port": {
"label": "Itala ang port para sa API server:",
"title": "Port"
}
}
},
"audio-compressor": {
@ -299,7 +353,8 @@
}
},
"compact-sidebar": {
"description": "Laging i-set ang sidebar sa compact mode"
"description": "Laging i-set ang sidebar sa compact mode",
"name": "Pinaliit na Sidebar"
},
"crossfade": {
"description": "I-crossfade kada kanta",
@ -353,7 +408,7 @@
"backend": {
"dialog": {
"error": {
"message": "Argh! Paumanhin, nabigo ang pag-download…",
"message": "Kainis! Paumanhin, nabigo ang pag-download…",
"title": "Nagkaroon ng error sa pag-download!"
},
"start-download-playlist": {
@ -392,6 +447,8 @@
"download-finish-settings": {
"label": "Kung natapos ang download",
"prompt": {
"last-percent": "Tapos ng x na porsyento",
"last-seconds": "Huling x na segundo",
"title": "I-configure kung kailan magda-download"
},
"submenu": {
@ -406,6 +463,9 @@
},
"renderer": {
"can-not-update-progress": "Hindi ma-update ang progress"
},
"templates": {
"button": "Mag-download"
}
},
"exponential-volume": {
@ -418,7 +478,8 @@
}
},
"lumiastream": {
"description": "Nabibigay suporta sa Lumia Stream"
"description": "Nabibigay suporta sa Lumia Stream",
"name": "Lumia Stream [Beta]"
},
"lyrics-genius": {
"description": "Nagdaragdag ng suporta sa lyrics para sa karamihan ng kanta",
@ -475,7 +536,8 @@
"name": "Nabigasyon"
},
"no-google-login": {
"description": "Tanggalin ang mga Google login na button at mga link mula sa interface"
"description": "Tanggalin ang mga Google login na button at mga link mula sa interface",
"name": "Walang Google na Login"
},
"notifications": {
"description": "Magpakita ng notification kapag nagsimulang tumugtog ang kanta (magagamit ang mga interactive na notification sa Windows)",
@ -490,8 +552,10 @@
}
},
"priority": "Prioridad ng Notification",
"toast-style": "Estilo ng toast",
"unpause-notification": "Ipakita ang notification sa pag-unpause"
}
},
"name": "Mga Abiso"
},
"picture-in-picture": {
"description": "Payagan ang pag-palit ng app sa picture-in-picture mode",
@ -572,7 +636,8 @@
},
"listenbrainz": {
"token": {
"label": "Ilagay ang ListenBrainz user token:"
"label": "Ilagay ang ListenBrainz user token:",
"title": "Token ng ListenBrainz"
}
}
}
@ -580,6 +645,7 @@
"shortcuts": {
"description": "Nagbibigay-daan sa pagtatakda ng mga global hotkey para sa playback (play/pause/susunod/nakaraan) at pag-off ng media OSD sa pamamagitan ng pag-override sa mga media key, pag-on sa Ctrl/CMD + F para maghanap, pag-on sa suporta ng Linux MPRIS para sa mga media key, at mga custom na hotkey para sa mga advanced na user",
"menu": {
"override-media-keys": "I-override ang mga Media Key",
"set-keybinds": "I-set ang Global Song Control"
},
"name": "Mga shortcut (at MPRIS)",
@ -587,6 +653,7 @@
"keybind": {
"keybind-options": {
"next": "Susunod",
"play-pause": "Mag-play / Mag-pause",
"previous": "Nakaraan"
},
"label": "Pumili ng Global na Keybind para sa Songs Control:"
@ -594,14 +661,65 @@
}
},
"skip-disliked-songs": {
"description": "Laktawan ang na-dislike na kanta"
"description": "Laktawan ang na-dislike na kanta",
"name": "I-skip ang mga Na-dislike na Kanta"
},
"skip-silences": {
"description": "Automatikong laktawan ang mga tahimik na mga seksyon sa kanta"
"description": "Automatikong laktawan ang mga tahimik na mga seksyon sa kanta",
"name": "I-skip ang mga Katahimikan"
},
"sponsorblock": {
"description": "Automatikong Laktawan ang di part ng kanta tulad ng intro/outro o part ng mga music video na ang kanta ay di nagple-play"
},
"synced-lyrics": {
"description": "Nagbibigay ng naka-sync na lyrics sa mga kanta, gamit ang mga provider tulad ng LRClib.",
"errors": {
"fetch": "⚠️ - Nagkaroon ng error habang kinukuha ang lyrics. Subukang muli mamaya.",
"not-found": "⚠️ - Walang nakitang lyrics para sa kantang ito."
},
"menu": {
"default-text-string": {
"label": "Default na character sa pagitan ng lyrics",
"tooltip": "Pumili ng default na character na gagamitin sa pagitan ng lyrics"
},
"line-effect": {
"label": "Effect ng Linya",
"submenu": {
"focus": {
"tooltip": "Gawing puti lamang ang kasalukuyang linya"
},
"offset": {
"tooltip": "I-offset sa kanan ang kasalukuyang linya"
},
"scale": {
"tooltip": "I-scale ang kasalukuyang linya"
}
},
"tooltip": "Pumili ng effect na ilalapat sa kasalukuyang linya"
},
"precise-timing": {
"label": "Gawing perpektong naka-sync ang lyrics",
"tooltip": "Kalkulahin sa millisecond ang pagpapakita ng susunod na linya (maaaring magkaroon ng maliit na epekto sa performance)"
},
"show-lyrics-even-if-inexact": {
"label": "Ipakita ang lyrics kahit di-eksakto",
"tooltip": "Kung hindi matagpuan ang kanta, susubukan muli ng plugin gamit ang ibang query sa paghahanap.\nAng resulta mula sa pangalawang pagsubok ay maaaring hindi eksakto."
},
"show-time-codes": {
"label": "Ipakita ang mga time code",
"tooltip": "Ipakita ang mga time code kasunod sa lyrics"
}
},
"refetch-btn": {
"fetching": "Nag-fe-fetch...",
"normal": "I-fetch muli ang lyrics"
},
"warnings": {
"duration-mismatch": "⚠️ - Maaaring hindi naka-sync ang lyrics dahil sa hindi pagkakatugma ng duration.",
"inexact": "⚠️ - Maaaring hindi eksakto ang lyrics para sa kantang ito",
"instrumental": "⚠️ - Ito ay isang instrumental na kanta"
}
},
"taskbar-mediacontrol": {
"description": "Kontrolin ang pag-play mula sa iyong taskbar ng Windows"
},
@ -633,7 +751,10 @@
}
},
"visualizer": {
"description": "Idaragdag ng visualizer sa player"
"description": "Idaragdag ng visualizer sa player",
"menu": {
"visualizer-type": "Uri ng Visualizer"
}
}
}
}

View File

@ -279,6 +279,49 @@
},
"name": "Mode ambiant"
},
"api-server": {
"description": "Ajouter un serveur API pour contrôler le lecteur",
"dialog": {
"request": {
"buttons": {
"allow": "Autoriser",
"deny": "Interdire"
},
"message": "Autoriser {{ID}} ({{origin}}) à accéder à l'API?",
"title": "Requête d'autorisation d'API"
}
},
"menu": {
"auth-strategy": {
"label": "Plan d'autorisation",
"submenu": {
"auth-at-first": {
"label": "Autoriser à la première requête"
},
"none": {
"label": "Pas d'autorisation"
}
}
},
"hostname": {
"label": "Nom de l'hôte"
},
"port": {
"label": "Port"
}
},
"name": "Serveur API [Beta]",
"prompt": {
"hostname": {
"label": "Entrer le nom de l'hôte (par exemple 0.0.0.0) pour le serveur API:",
"title": "Nom d'hôte"
},
"port": {
"label": "Entrer le port du serveur de l'API :",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Appliquer une compression à l'audio (diminue le volume des parties les plus fortes du signal et augmente le volume des parties les plus faibles)",
"name": "Compresseur audio"
@ -441,6 +484,18 @@
"button": "Télécharger"
}
},
"equalizer": {
"description": "Ajoute un égaliseur au lecteur",
"menu": {
"presets": {
"label": "Préréglages",
"list": {
"bass-booster": "Amplificateur de basses"
}
}
},
"name": "Égaliseur"
},
"exponential-volume": {
"description": "Rend le curseur de volume exponentiel afin qu'il soit plus facile de sélectionner des volumes plus faibles.",
"name": "Volume exponentiel"
@ -668,6 +723,59 @@
"description": "Saute automatiquement les parties non musicales comme l'intro/outro ou les parties de clips vidéo où la chanson n'est pas lue",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Ajoute des paroles synchronisées aux chansons, grâce à LRClib par exemple.",
"errors": {
"fetch": "⚠️ - Une erreur s'est produite en allant chercher les paroles. Merci de réessayer plus tard.",
"not-found": "⚠️ - Aucune paroles trouvées pour cette musique."
},
"menu": {
"default-text-string": {
"label": "Caractère par défaut entre les paroles",
"tooltip": "Choisi le caractère par défaut à utiliser pour l'espace entre les paroles"
},
"line-effect": {
"label": "Effet de ligne",
"submenu": {
"focus": {
"label": "Focus",
"tooltip": "Rend seulement la ligne actuelle blanche"
},
"offset": {
"label": "Décalage",
"tooltip": "Décale sur la droite la ligne actuelle"
},
"scale": {
"label": "Grossissement",
"tooltip": "Agrandis la ligne actuelle"
}
},
"tooltip": "Choisi l'effet à appliquer sur la ligne actuelle"
},
"precise-timing": {
"label": "Rend les paroles parfaitement synchronisées",
"tooltip": "Calcul à la milliseconde près l'affichage de la ligne suivante (peut avoir un faible impact sur les performances)"
},
"show-lyrics-even-if-inexact": {
"label": "Afficher les paroles même si inexactes",
"tooltip": "Si la musique n'est pas trouvé, le plugin essaye à nouveau avec une différence requête.\nLe résultat du deuxième essais peut ne pas être exacte."
},
"show-time-codes": {
"label": "Afficher les timecodes",
"tooltip": "Affiche à côté de chaque paroles son timecode"
}
},
"name": "Paroles Synchronisées",
"refetch-btn": {
"fetching": "Chargement...",
"normal": "Rafraîchir les paroles"
},
"warnings": {
"duration-mismatch": "⚠️ - Les paroles peuvent ne pas être synchronisées à cause d'une différence de durée.",
"inexact": "⚠️ - Les paroles de cette chanson peuvent ne pas être exactes",
"instrumental": "⚠️ - Cette musique n'a pas de paroles"
}
},
"taskbar-mediacontrol": {
"description": "Contrôlez la lecture depuis votre barre des tâches Windows",
"name": "Contrôle multimédia de la barre des tâches"

View File

@ -2,13 +2,14 @@
"common": {
"console": {
"plugins": {
"execute-failed": "נכשל ביצוע תוסף {{pluginName}}::{{contextName}}",
"execute-failed": "שגיאה בהרצת התוסף {{pluginName}}::{{contextName}}",
"executed-at-ms": "התוסף {{pluginName}}:{{contextName}} בוצע ב {{ms}}ms",
"initialize-failed": "טעינת התוסף \"{{pluginName}}\" נכשלה",
"load-all": "טוען את כל התוספים",
"load-failed": "טעינת התוסף \"{{pluginName}}\" נכשלה",
"load-failed": "שגיאה בטעינת התוסף \"{{pluginName}}\"",
"loaded": "התוסף \"{{pluginName}}\" נטען",
"unload-failed": "הסרת התוסף \"{{pluginName}} נכשלה"
"unload-failed": "הסרת התוסף \"{{pluginName}} נכשלה",
"unloaded": "תוסף {{pluginName}} הורד"
}
}
},
@ -25,18 +26,64 @@
"i18n": {
"loaded": "i18n נטען"
},
"second-instance": {
"receive-command": "התקבלה פקודה מעבר פרוטוקל: {{command}}"
},
"theme": {
"css-file-not-found": "קובץ ה-CSS \"{{cssFile}}\" לא קיים. מדלג"
},
"unresponsive": {
"details": "שגיאה ללא תגובה\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "מוחק קבצי מתמון"
},
"window": {
"tried-to-render-offscreen": "ווינדוס ניסה להציג תוכן מחוץ למסך, גודל חלון={{windowSize}}, גודל מסך={{displaySize}}, מיקום={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "התפריט מוחבא, השתמש \"Alt\" על להציג אותו (או \"Esacpe\" אם משתמשים בתפריט בתוך האפליקציה)",
"message": "הסתרת התפריט מופעלת",
"title": "הסתרת התפריט הופעלה"
},
"need-to-restart": {
"buttons": {
"later": "אחר כך",
"restart-now": "מתחיל את התוכנה מחדש עכשיו"
},
"title": "נדרשת הפעלה מחדש"
},
"unresponsive": {
"buttons": {
"quit": "יציאה",
"relaunch": "הפעל מחדש",
"wait": "המתן"
},
"detail": "אנו מצטערים על אי הנוחות! אנא בחר מה לעשות:",
"message": "האפליקציה אינה מגיבה",
"title": "החלון אינו מגיב"
},
"update-available": {
"buttons": {
"disable": "בטל עדכונים",
"download": "הורדה",
"ok": "אוקי"
},
"message": "גירסא חדשה זמינה כעת",
"title": "קיים עדכון חדש"
}
},
"menu": {
"about": "אודות",
"navigation": {
"label": "ניווט",
"submenu": {
"copy-current-url": "העתק את כתובת ה-URL",
"go-back": "חזור אחורה",
"go-forward": "לך קדימה",
"quit": "יציאה"
}
}
}

251
src/i18n/resources/hi.json Normal file
View File

@ -0,0 +1,251 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "{{pluginName}}::{{contextName}} प्लगइन निष्पादित करने में विफल",
"executed-at-ms": "{{pluginName}}::{{contextName}} प्लगिन {{ms}} में निष्पाशित हुआ",
"initialize-failed": "\"{{pluginName}}\" प्लगिन इनिशियलाइज़ होने में असफल रहा",
"load-all": "सारे प्लगिन लोड हो चुके हैं",
"load-failed": "\"{{pluginName}}\" प्लगिन लोड होने में असफल रहा",
"loaded": "प्लगिन \"{{pluginName}}\" लोड हो चुका है",
"unload-failed": "\"{{pluginName}}\" अनलोड होने में असफल रहा",
"unloaded": "प्लगिन \"{{pluginName}}\" अनलोड हो गया है"
}
}
},
"language": {
"code": "hi",
"local-name": "हिंदी",
"name": "Hindi"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "लोडिंग समाप्त हुई । डेवटूल्स खोले गए हैं"
},
"i18n": {
"loaded": "i18n लोड हो गया है"
},
"second-instance": {
"receive-command": "प्रोटोकॉल पर आदेश प्राप्त हुआ \"{{command}}\""
},
"theme": {
"css-file-not-found": "सीएसएस फाइल \"{{cssFile}}\" मौजूद नही है, अनदेखा किया जा रहा है"
},
"unresponsive": {
"details": "अनरेस्पॉन्सिव एरर\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "एप कैश साफ़ किया जा रहा है"
},
"window": {
"tried-to-render-offscreen": "विंडो ने ऑफस्क्रीन रेंडर करने का प्रयास किया, विंडो साइज={{windowSize}}, डिस्प्ले साइज={{displaySize}}, पोजिशन={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "मेनू छिपा हुआ है, देखने के लिए 'Alt' का इस्तेमाल करें (या 'Escape' अगर आप इन-एप मेनू का उपयोग कर रहे हैं)",
"message": "मेनू छिपाएँ सक्षम है",
"title": "मेनू छिपाएँ सक्षम"
},
"need-to-restart": {
"buttons": {
"later": "बाद में",
"restart-now": "पुनः आरंभ करें"
},
"detail": "\"{{pluginName}}\" प्रभाव लेने के लिए प्लगिन को पुनः शुरू करें",
"message": "\"{{pluginName}}\" पुनः आरंभ करने की आवश्यकता है",
"title": "पुनः आरंभ करने की आवश्यकता है"
},
"unresponsive": {
"buttons": {
"quit": "बंद करें",
"relaunch": "पुनः लॉन्च करें",
"wait": "रुकें"
},
"detail": "असुविधाए के लिए खेद हैं! कृपया चुनें कि क्या करना है:",
"message": "एप्लीकेशन अनुत्तरदायी है",
"title": "विंडो अनुत्तरदायी है"
},
"update-available": {
"buttons": {
"disable": "अपडेट्स बंद करें",
"download": "डाउनलोड",
"ok": "ठीक है"
},
"detail": "एक नया वर्जन उपलब्ध है, {{downloadLink}} से डाउनलोड किया जा सकता है",
"message": "एक नया वर्जन उपलब्ध है",
"title": "अपडेट उपलब्ध है"
}
},
"menu": {
"about": "के बारे में",
"navigation": {
"label": "मार्गदर्शन",
"submenu": {
"copy-current-url": "मौजूदा यूआरएल कापी करें",
"go-back": "पीछे जाएं",
"go-forward": "आगे जाएं",
"quit": "निकास",
"restart": "एप को पुनः शुरू करें"
}
},
"options": {
"label": "विकल्प",
"submenu": {
"advanced-options": {
"label": "उन्नत विकल्प",
"submenu": {
"auto-reset-app-cache": "एप शुरू होते समय कैश रीसेट करें",
"disable-hardware-acceleration": "हार्डवेयर एक्सीलरेशन बंद करें",
"edit-config-json": "config.json को एडिट करें",
"override-user-agent": "यूजर-एजेंट को रद्द करें",
"restart-on-config-changes": "कनफिग बदलने पे पुनः शुरू करें",
"set-proxy": {
"label": "प्रॉक्सी तय करें",
"prompt": {
"label": "प्प्रॉक्सी पता डालें: (बंद करने के लिए खाली छोड़ें)",
"placeholder": "उदाहरण: SOCKS5://127.0.0.1:9999",
"title": "प्रॉक्सी तय करें"
}
},
"toggle-dev-tools": "डेवटूल्स को टॉगल करें"
}
},
"always-on-top": "हमेशा ऊपर",
"auto-update": "ऑटो अपडेट",
"hide-menu": {
"dialog": {
"message": "अगले लॉन्च पे मेनू छुपा दिया जायेगा, देखने के लिए [Alt] का प्रयोग करें (या बैकटिक [`] अगर आप इन एप मेनू का प्रयोग कर रहे हैं)",
"title": "मेनू छुपाना सक्रिय है"
},
"label": "मेनू छुपाएं"
},
"language": {
"dialog": {
"message": "पुनः शुरू करने के बाद भाषा बदल दी जाएगी",
"title": "भाषा बदल दी गई है"
},
"label": "भाषा",
"submenu": {
"to-help-translate": "अनुवाद करने में सहायता करना चाहते हैं? यहां दबाएं"
}
},
"resume-on-start": "एप शुरू होने पर आखरी गाना फिर शुरू करें",
"single-instance-lock": "सिंगल इंस्टेंस लॉक",
"start-at-login": "शुरू होने पे लॉगिन करें",
"starting-page": {
"label": "स्टार्टिंग पेज",
"unset": "अनसेट"
},
"tray": {
"label": "ट्रे",
"submenu": {
"disabled": "बंद किया गया है",
"enabled-and-hide-app": "सक्रिय है और एप छुपाएं",
"enabled-and-show-app": "सक्रिय है और एप दिखाएं",
"play-pause-on-click": "क्लिक पर प्ले/पोज"
}
},
"visual-tweaks": {
"label": "दृश्य परिवर्तन",
"submenu": {
"like-buttons": {
"default": "डिफॉल्ट",
"force-show": "बल पूर्वक दिखाएं",
"hide": "छुपाएं",
"label": "लाइक बटंस"
},
"remove-upgrade-button": "अपग्रेड बटन हटाएं",
"theme": {
"dialog": {
"button": {
"cancel": "रद्द करें",
"remove": "हटाएं"
},
"remove-theme": "क्या आप निश्चित है आपको कस्टम थीम हटानी है?",
"remove-theme-message": "यह कस्टम थीम को हटा देगा"
},
"label": "थीम",
"submenu": {
"import-css-file": "कस्टम सीएसएस फाइल को आयात करें",
"no-theme": "कोई थीम नही"
}
}
}
}
}
},
"plugins": {
"enabled": "सक्रिय",
"label": "प्लगिंस",
"new": "नया"
},
"view": {
"label": "देखें",
"submenu": {
"force-reload": "बल पूर्वक रिलोड करें",
"reload": "रिलोड करें",
"reset-zoom": "वास्तविक आकार",
"toggle-fullscreen": "टागल फुल स्क्रीन",
"zoom-in": "ज़ूम इन",
"zoom-out": "ज़ूम आउट"
}
}
},
"tray": {
"next": "अगला",
"play-pause": "चलाएँ/रोकें",
"previous": "पिछला",
"quit": "निकास",
"restart": "ऐप पुनः प्रारंभ करें",
"show": "ऐप दिखाए",
"tooltip": {
"default": "यूट्यूब म्यूजिक",
"with-song-info": "यूट्यूब म्यूजिक: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "यदि कोई विज्ञापन चलता है तो यह ऑडियो को म्यूट कर देता है और प्लेबैक गति 16x पर सेट कर देता है",
"name": "विज्ञापन की गति बढ़ाना"
},
"adblocker": {
"description": "डिफ़ॉल्ट रूप से सभी विज्ञापनों और ट्रैकिंग को ब्लॉक करें",
"menu": {
"blocker": "ब्लॉकर"
},
"name": "विज्ञापन अवरोधक"
},
"album-actions": {
"description": "प्लेलिस्ट या एल्बम के सभी गानों पर लागू करने के लिए \"अंडिसलाइक,\" \"डिसलाइक,\" \"लाइक,\" और \"अनलाइक\" बटन जोड़ता है",
"name": "एल्बम एक्शन"
},
"album-color-theme": {
"description": "एल्बम रंग पैलेट के आधार पर एक गतिशील थीम और दृश्य प्रभाव लागू करता है",
"menu": {
"color-mix-ratio": {
"submenu": {
"percent": "{{ratio}}%"
}
}
}
},
"video-toggle": {
"menu": {
"align": {
"submenu": {
"left": "बाएं",
"middle": "मध्य",
"right": "दाहिने"
}
},
"force-hide": "वीडियो टैब को बलपूर्वक हटाएं",
"mode": {
"label": "तरीका"
}
}
}
}
}

View File

@ -7,8 +7,8 @@
"initialize-failed": "Nem sikerült inicializálni a \"{{pluginName}}\" plugint",
"load-all": "Összes bővítmény betöltése",
"load-failed": "Nem sikerült betölteni a \"{{pluginName}}\" plugint",
"loaded": "\"{{pluginName}}\" nevű plugin betöltve",
"unload-failed": "Nem sikerült a \"{{pluginName}}\" bővítményt letölteni",
"loaded": "\"{{pluginName}}\" plugin betöltve",
"unload-failed": "Nem sikerült a \"{{pluginName}}\" bővítményt kikapcsolni",
"unloaded": "A \"{{pluginName}}\" bővítmény kikapcsolva"
}
}
@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Ha reklám szól, elnémítja a hangot és a lejátszási sebességet 16x-ra állítja",
"name": "Gyorsítás hozzáadása"
},
"adblocker": {
"description": "Alapértelmezés szerint blokkolja az összes hirdetést és nyomkövetést",
"menu": {
@ -368,6 +372,9 @@
"backend": {
"dialog": {
"error": {
"buttons": {
"ok": "Rendben"
},
"message": "Hoppá! Elnézést, a letöltés sikertelen volt…",
"title": "A letöltés során hiba történt!"
},
@ -407,7 +414,22 @@
"description": "MP3 / forrás hanganyag letöltése közvetlenül az interfészről",
"menu": {
"choose-download-folder": "Letöltési mappa kiválasztása",
"download-finish-settings": {
"label": "Letöltés befejezéskor",
"prompt": {
"last-percent": "x százalék után",
"last-seconds": "Utolsó x másodperc"
},
"submenu": {
"advanced": "Speciális",
"enabled": "Engedélyezve",
"mode": "Időmód",
"percent": "Százalék",
"seconds": "Másodpercek"
}
},
"download-playlist": "Lejátszási lista letöltése",
"presets": "Sablonok",
"skip-existing": "Meglévő fájlok kihagyása"
},
"name": "Letöltő",
@ -489,6 +511,7 @@
}
},
"navigation": {
"description": "Következő/Vissza navigációs nyilak közvetlenül az interfészbe integrálva, mint a kedvenc böngésződben",
"name": "Navigáció"
},
"no-google-login": {
@ -502,10 +525,14 @@
"interactive-settings": {
"label": "Interaktív beállítások",
"submenu": {
"hide-button-text": "Gombok szövegének elrejtése"
"hide-button-text": "Gombok szövegének elrejtése",
"refresh-on-play-pause": "Frissítés lejátszás/szünet megnyomásakor",
"tray-controls": "Megnyitás/Bezárás tálca ikonra kattintva"
}
},
"priority": "Értesítési prioritás"
"priority": "Értesítési prioritás",
"toast-style": "Értesítés stílusa",
"unpause-notification": "Értesítés megjelenítése a lejátszás folytatásakor"
},
"name": "Értesítések"
},
@ -542,7 +569,9 @@
"precise-volume": {
"description": "A hangerő precíz szabályozása egérgörgővel/gyorsbillentyűkkel, egy egyedi HUD és testreszabható hangerő csuszka segítségével",
"menu": {
"global-shortcuts": "Globális gyorsbillentyűk"
"arrows-shortcuts": "Helyi nyíl-billentyűkkel való vezérlés",
"custom-volume-steps": "Egyedi hangerőléptetés beállítása",
"global-shortcuts": "Globális Gyorsbillentyűk"
},
"name": "Precíz hangerő",
"prompt": {
@ -553,6 +582,10 @@
},
"label": "Válaszd ki a globális hangerő gyorsbillentyűket:",
"title": "Globális hangerő gyorsbillentyűk"
},
"volume-steps": {
"label": "Hangerő növelés/csökkentés léptékének kiválasztása",
"title": "Hangerő lépték"
}
}
},
@ -566,7 +599,8 @@
}
}
},
"description": "Lehetővé teszi a videó minőségének megváltoztatását egy gombbal a videó fedvényen"
"description": "Lehetővé teszi a videó minőségének megváltoztatását egy gombbal a videó fedvényen",
"name": "Videóminőség modosító"
},
"scrobbler": {
"description": "Scrobbling támogatás hozzáadása (pl. last.fm, ListenBrainz)",
@ -613,6 +647,7 @@
"play-pause": "Lejátszás / Szünet",
"previous": "Előző"
},
"label": "Globális billentyűparancsok választása a dalok vezérléséhez:",
"title": "Globális gyorsbillentyűk"
}
}
@ -629,8 +664,38 @@
"description": "Automatikusan kihagyja a nem zenés részeket, mint például az intro/outro vagy a zenei videók olyan részeit, ahol a zene nem szól",
"name": "SzponzorBlokk"
},
"synced-lyrics": {
"description": "Szinkronizált dalszövegeket biztosít dalokhoz, LRClib-hez hasonló szolgáltatókat használva.",
"errors": {
"fetch": "⚠️ - Hiba történt a dalszövegek lekérése közben. Kérlek, próbáld újra később.",
"not-found": "⚠️ - Nem található dalszöveg ehhez a zenéhez."
},
"menu": {
"line-effect": {
"submenu": {
"scale": {
"label": "Mérték"
}
}
},
"precise-timing": {
"label": "Dalszöveg tökéletes szinkronizálása"
}
},
"name": "Szinkronizált dalszövegek",
"refetch-btn": {
"fetching": "Lekérés folyamatban...",
"normal": "Dalszöveg újra lekérése"
},
"warnings": {
"duration-mismatch": "⚠️ - A dalszövegek időzítése eltérhet a zene hossza miatt.",
"inexact": "⚠️ - Ennek a zenének a dalszövege pontatlan lehet",
"instrumental": "⚠️ - Ez egy hangszerekkel játszott zene"
}
},
"taskbar-mediacontrol": {
"description": "Lejátszás vezérlése a Windows tálcáról"
"description": "Lejátszás vezérlése a Windows tálcáról",
"name": "Médiavezérlés a tálcán"
},
"touchbar": {
"description": "macOS felhasználók számára hozzáad egy widgetet a TouchBar-hoz",
@ -667,6 +732,7 @@
}
},
"visualizer": {
"description": "Vizualizációt ad a lejátszóhoz",
"menu": {
"visualizer-type": "Vizualizáció típus"
},

View File

@ -202,11 +202,15 @@
"show": "Tampilkan jendela",
"tooltip": {
"default": "YouTube Musik",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
"with-song-info": "YouTube Musik: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Jika iklan diputar, audio akan dimatikan dan kecepatan pemutaran akan diatur ke 16x",
"name": "Percepatan Iklan"
},
"adblocker": {
"description": "Blokir semua iklan dan pelacakan di luar kotak",
"menu": {
@ -275,6 +279,49 @@
},
"name": "Mode ambient"
},
"api-server": {
"description": "Menambahkan server API untuk mengontrol pemutar",
"dialog": {
"request": {
"buttons": {
"allow": "Izinkan",
"deny": "Menolak"
},
"message": "Izinkan {{ID}} ({{origin}}) untuk mengakses API?",
"title": "Permintaan otorisasi API"
}
},
"menu": {
"auth-strategy": {
"label": "Strategi otorisasi",
"submenu": {
"auth-at-first": {
"label": "Otorisasi pada permintaan pertama"
},
"none": {
"label": "Tidak ada otorisasi"
}
}
},
"hostname": {
"label": "Nama host"
},
"port": {
"label": "Port"
}
},
"name": "API Server [Beta]",
"prompt": {
"hostname": {
"label": "Masukkan nama host (seperti 0.0.0.0) untuk server API:",
"title": "Nama host"
},
"port": {
"label": "Masukkan port untuk server API:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Menerapkan kompresi pada audio (mengurangi volume pada bagian paling keras dari sinyal dan meningkatkan volume pada bagian paling lembut)",
"name": "Kompresi suara"
@ -410,6 +457,21 @@
"description": "Unduh MP3 / sumber suara secara langsung via antarmuka",
"menu": {
"choose-download-folder": "Pilih folder unduhan",
"download-finish-settings": {
"label": "Unduh setelah selesai",
"prompt": {
"last-percent": "x persen terakhir",
"last-seconds": "x detik terakhir",
"title": "Konfigurasikan kapan akan mengunduh"
},
"submenu": {
"advanced": "Lanjutan",
"enabled": "Diaktifkan",
"mode": "Mode waktu",
"percent": "Persen",
"seconds": "Detik"
}
},
"download-playlist": "Unduh daftar putar",
"presets": "Prasetel",
"skip-existing": "Lewati berkas yang sudah ada"
@ -422,6 +484,18 @@
"button": "Unduh"
}
},
"equalizer": {
"description": "Menambahkan equalizer ke pemutar",
"menu": {
"presets": {
"label": "Prasetel",
"list": {
"bass-booster": "Penguat Bass"
}
}
},
"name": "Equalizer"
},
"exponential-volume": {
"description": "Buat penggeser volume menjadi eksponen sehingga memudahkan memilih volume yang lebih rendah.",
"name": "Volume Eksponen"
@ -649,6 +723,59 @@
"description": "Otomatis Melewati bagian yang bukan musik seperti intro/outro atau bagian dari video musik di mana lagu tidak dimainkan",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Menyediakan lirik lagu yang disinkronkan, menggunakan penyedia seperti LRClib.",
"errors": {
"fetch": "⚠️ - Terjadi kesalahan saat mengambil lirik. Coba lagi nanti.",
"not-found": "⚠️ - Tidak ada lirik yang ditemukan untuk lagu ini."
},
"menu": {
"default-text-string": {
"label": "Karakter default antara lirik",
"tooltip": "Pilih karakter default yang akan digunakan untuk celah antar lirik"
},
"line-effect": {
"label": "Efek garis",
"submenu": {
"focus": {
"label": "Fokus",
"tooltip": "Jadikan hanya baris saat ini berwarna putih"
},
"offset": {
"label": "Offset",
"tooltip": "Mengimbangi garis saat ini di sebelah kanan"
},
"scale": {
"label": "Skala",
"tooltip": "Skala garis saat ini"
}
},
"tooltip": "Pilih efek yang akan diterapkan ke baris saat ini"
},
"precise-timing": {
"label": "Buat liriknya tersinkronisasi dengan sempurna",
"tooltip": "Hitung hingga milidetik tampilan baris berikutnya (dapat berdampak kecil pada kinerja)"
},
"show-lyrics-even-if-inexact": {
"label": "Tampilkan lirik meskipun tidak tepat",
"tooltip": "Jika lagu tidak ditemukan, plugin akan mencoba lagi dengan kueri pencarian yang berbeda.\nHasil dari percobaan kedua mungkin tidak tepat."
},
"show-time-codes": {
"label": "Tampilkan kode waktu",
"tooltip": "Tampilkan kode waktu di samping lirik"
}
},
"name": "Lirik yang Disinkronkan",
"refetch-btn": {
"fetching": "Mengambil...",
"normal": "Ambil ulang lirik"
},
"warnings": {
"duration-mismatch": "⚠️ - Liriknya mungkin tidak sinkron karena ketidakcocokan durasi.",
"inexact": "⚠️ - Lirik lagu ini mungkin tidak tepat",
"instrumental": "⚠️ - Ini adalah lagu instrumental"
}
},
"taskbar-mediacontrol": {
"description": "Kendalikan pemutaran dari bilah alat Windows",
"name": "Pengendali Media di Bilah Alat"

View File

@ -158,6 +158,14 @@
},
"remove-upgrade-button": "Fjarlægja uppgræðartakkan",
"theme": {
"dialog": {
"button": {
"cancel": "Hætta við",
"remove": "Fjarlægja"
},
"remove-theme": "Ertu viss um að þú viljir fjarlægja þetta sérsniðna þema?",
"remove-theme-message": "Þetta mun fjarlægja sérsniðna þema"
},
"label": "Þema",
"submenu": {
"import-css-file": "Flytja inn sérsniðna CSS skrá",
@ -199,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Ef auglýsing spilar slökknar hún á hljóðinu og stillir spilunarhraðann á 16x",
"name": "Auglýsingahraða"
},
"adblocker": {
"description": "Lokaðu fyrir allar auglýsingar og rakningar úr kassanum",
"menu": {
@ -267,6 +279,49 @@
},
"name": "Umhverfishamur"
},
"api-server": {
"description": "Bætir API netþjóni til að stjórna spilaranum",
"dialog": {
"request": {
"buttons": {
"allow": "Leyfa",
"deny": "Óleyfa"
},
"message": "Leyfa {{ID}} ({{origin}}) að aðganga API-ið?",
"title": "API heimildarbeiðni"
}
},
"menu": {
"auth-strategy": {
"label": "Heimildarstefna",
"submenu": {
"auth-at-first": {
"label": "Heimila á fyrst beiðni"
},
"none": {
"label": "Nei heimild"
}
}
},
"hostname": {
"label": "Hýsitölvunafn"
},
"port": {
"label": "Tengi"
}
},
"name": "API-Netþjónn [Beta]",
"prompt": {
"hostname": {
"label": "Sláðu inn hýsitölvunafnið (eins og 0.0.0.0) fyrir API-netþjónninn:",
"title": "Hýsitölvunafn"
},
"port": {
"label": "Sláðu inn tengið fyrir API-netþjónninn:",
"title": "Tengi"
}
}
},
"audio-compressor": {
"description": "Notaðu þjöppun á hljóð (lækkar hljóðstyrk háværustu hluta merkis og hækkar hljóðstyrk í mýkstu hlutunum)",
"name": "Hljóðþjöppu"
@ -402,6 +457,21 @@
"description": "Niðurhalar MP3 / upprunahljóði beint úr viðmótinu",
"menu": {
"choose-download-folder": "Veldu niðurhalsmöppu",
"download-finish-settings": {
"label": "Sækja þegar lokið",
"prompt": {
"last-percent": "Eftir x sekúndur",
"last-seconds": "Síðustu x sekúndur",
"title": "Stilla hvenær á að hlaða niður"
},
"submenu": {
"advanced": "Ítarlegri",
"enabled": "Virkt",
"mode": "Tímastilling",
"percent": "Hlutfall",
"seconds": "Sekúndur"
}
},
"download-playlist": "Sækja spilunarlista",
"presets": "Forstillingar",
"skip-existing": "Slepptu núverandi skrám"
@ -641,6 +711,59 @@
"description": "Sleppur sjálfkrafa hlutum sem ekki eru tónlist, eins og inngangur/lok eða hlutar af tónlistarmyndböndum þar sem lag er ekki að spila",
"name": "Styrktarblokk"
},
"synced-lyrics": {
"description": "Veitir samstillta texta við lög, með því að nota veitur eins og LRClib.",
"errors": {
"fetch": "⚠️ - Villa kom upp við að sækja textann. Vinsamlegast reyndu aftur síðar.",
"not-found": "⚠️ - Enginn texti fannst við þetta lag."
},
"menu": {
"default-text-string": {
"label": "Sjálfgefið tákn á milli texta",
"tooltip": "Veldu sjálfgefna tákn til að nota fyrir bilið á milli texta"
},
"line-effect": {
"label": "Línuafleiðing",
"submenu": {
"focus": {
"label": "Brennidepill",
"tooltip": "Gerðu aðeins núverandi línu hvíta"
},
"offset": {
"label": "Fararbyrjun",
"tooltip": "Fararbyrjun á hægri af núverandi línan"
},
"scale": {
"label": "Skali",
"tooltip": "Skala núverandi línu"
}
},
"tooltip": "Veldu áhrif til að nota á núverandi línu"
},
"precise-timing": {
"label": "Gera textana fullkomlega samstillta",
"tooltip": "Reikna upp á millisekúndu birtingu næstu línu (getur haft lítil áhrif á frammistöðu)"
},
"show-lyrics-even-if-inexact": {
"label": "Sýna texta, jafnvel þótt hann sé ónákvæmur",
"tooltip": "Ef lagið finnst ekki reynir tengiforritið aftur með annarri leitarfyrirspurn.\nNiðurstaðan úr annarri tilraun er kannski ekki nákvæm."
},
"show-time-codes": {
"label": "Sýna tímikóðar",
"tooltip": "Sýna tímakóðana við hliðina á textanum"
}
},
"name": "Samstilltur texti",
"refetch-btn": {
"fetching": "Er að sækja",
"normal": "Endursækja texta"
},
"warnings": {
"duration-mismatch": "⚠️ - Textarnir gætu verið ekki samstilltir vegna tímalengdar.",
"inexact": "⚠️ - Textinn við þetta lag er kannski ekki nákvæmur",
"instrumental": "⚠️ - Þetta er hljóðfærilegt lag"
}
},
"taskbar-mediacontrol": {
"description": "Stjórnaðu spilun frá Windows verkefnastikunni þinni",
"name": "Miðlunarstýringarverkefnastikunnar"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Se viene riprodotto un annuncio, l'audio viene disattivato e viene impostata la velocità di riproduzione su 16x",
"name": "Accelerazione ad"
},
"adblocker": {
"description": "Blocca tutti gli annunci e i tracker",
"menu": {
@ -275,6 +279,56 @@
},
"name": "Modalità Ambiente"
},
"amuse": {
"description": "Aggiunge il supporto a YouTube Music per il widget Amuse Now Playing di 6K Labs",
"name": "Amuse",
"response": {
"query": "Il server API di Amuse è in funzione. GET /query per ottenere informazioni sui brani."
}
},
"api-server": {
"description": "Aggiunge un server API per controllare il player",
"dialog": {
"request": {
"buttons": {
"allow": "Permetti",
"deny": "Nega"
},
"message": "Consentire a {{ID}} ({{origin}}) di accedere all'API?",
"title": "Autorizzazione API richiesta"
}
},
"menu": {
"auth-strategy": {
"label": "Metodo di autorizzazione",
"submenu": {
"auth-at-first": {
"label": "Autorizza alla prima richiesta"
},
"none": {
"label": "Nessuna autorizzazione"
}
}
},
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Porta"
}
},
"name": "API Server [Beta]",
"prompt": {
"hostname": {
"label": "Inserisci il nome host (ad esempio 0.0.0.0) per il server API:",
"title": "Hostname"
},
"port": {
"label": "Inserisci la porta per il server API:",
"title": "Porta"
}
}
},
"audio-compressor": {
"description": "Attiva la compressione audio (abbassa il volume delle parti più alte e alza quello delle parti più basse del segnale)",
"name": "Compressore audio"
@ -410,6 +464,21 @@
"description": "Download MP3 / sorgenti audio direttamente dall'interfaccia",
"menu": {
"choose-download-folder": "Scegli cartella download",
"download-finish-settings": {
"label": "Scarica al termine",
"prompt": {
"last-percent": "Dopo x percento",
"last-seconds": "Ultimi x secondi",
"title": "Configura quando scaricare"
},
"submenu": {
"advanced": "Avanzato",
"enabled": "Abilitato",
"mode": "Modalità tempo",
"percent": "Percentuale",
"seconds": "Secondi"
}
},
"download-playlist": "Scarica la playlist",
"presets": "Preimpostazioni",
"skip-existing": "Salta i file esistenti"
@ -422,6 +491,18 @@
"button": "Scarica"
}
},
"equalizer": {
"description": "Aggiunge un equalizzatore al player",
"menu": {
"presets": {
"label": "Presets",
"list": {
"bass-booster": "Booster dei bassi"
}
}
},
"name": "Equalizzatore"
},
"exponential-volume": {
"description": "Rende esponenziale il cursore del volume, in modo da facilitare la selezione di volumi più bassi.",
"name": "Volume esponenziale"
@ -649,6 +730,59 @@
"description": "Salta automaticamente le parti non musicali, come l'intro/outro delle canzoni o le parti dei video musicali in cui non viene riprodotto il brano",
"name": "Blocco sponsor"
},
"synced-lyrics": {
"description": "Fornisce testi sincronizzati alle canzoni, utilizzando provider come LRClib.",
"errors": {
"fetch": "⚠️ - Si è verificato un errore nel recuperare il testo. Per favore riprova più tardi.",
"not-found": "⚠️ - Nessun testo trovato per questa canzone."
},
"menu": {
"default-text-string": {
"label": "Carattere predefinito tra i testi",
"tooltip": "Scegliere il carattere predefinito da utilizzare per l'intervallo tra i testi"
},
"line-effect": {
"label": "Effetto linea",
"submenu": {
"focus": {
"label": "Focus",
"tooltip": "Rendi bianca solo la riga corrente"
},
"offset": {
"label": "Offset",
"tooltip": "Offset a destra della riga corrente"
},
"scale": {
"label": "Ingrandimento",
"tooltip": "Ingrandisci la linea corrente"
}
},
"tooltip": "Scegli l'effetto da applicare alla linea corrente"
},
"precise-timing": {
"label": "Rendi i testi perfettamente sincronizzati",
"tooltip": "Calcola al millisecondo la visualizzazione della riga successiva (può avere un piccolo impatto sulle prestazioni)"
},
"show-lyrics-even-if-inexact": {
"label": "Mostra le lyric anche se incorrette",
"tooltip": "Se il brano non viene trovato, il plugin riprova con un'altra query di ricerca.\nIl risultato del secondo tentativo potrebbe non essere esatto."
},
"show-time-codes": {
"label": "Mostra time code",
"tooltip": "Mostra i codici temporali accanto ai testi"
}
},
"name": "Testi sincronizzati",
"refetch-btn": {
"fetching": "Sto recuperando...",
"normal": "Recupera i testi"
},
"warnings": {
"duration-mismatch": "⚠️ - I testi potrebbero non essere sincronizzati a causa di una mancata corrispondenza della durata.",
"inexact": "⚠️ - Il testo di questa canzone potrebbe essere inesatto",
"instrumental": "⚠️ - Questo è un brano strumentale"
}
},
"taskbar-mediacontrol": {
"description": "Controlla riproduzione dalla taskbar di Windows",
"name": "Controlli multimediali sulla taskbar"

View File

@ -65,7 +65,7 @@
},
"detail": "ご不便をおかけして申し訳ございません! 何をするか選んでください:",
"message": "アプリケーションは応答していません",
"title": "ウィンドウが応答しません"
"title": "ウィンドウが応答していません"
},
"update-available": {
"buttons": {
@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "広告が再生されると、自動的にミュートされ、再生速度が16倍に設定されます",
"name": "広告のスピードを上げる"
},
"adblocker": {
"description": "すべての広告とトラッカーをブロックj",
"menu": {
@ -275,6 +279,49 @@
},
"name": "アンビエント モード"
},
"api-server": {
"description": "プレイヤーを制御するAPIサーバーを追加",
"dialog": {
"request": {
"buttons": {
"allow": "許可",
"deny": "拒否"
},
"message": "{{ID}}が{{origin}}にアクセスすることを許可しますか?",
"title": "API承認リクエスト"
}
},
"menu": {
"auth-strategy": {
"label": "許可方法",
"submenu": {
"auth-at-first": {
"label": "初回リクエスト時に承認"
},
"none": {
"label": "不許可"
}
}
},
"hostname": {
"label": "ホスト名"
},
"port": {
"label": "ポート"
}
},
"name": "APIサーバー(Beta)",
"prompt": {
"hostname": {
"label": "APIサーバーのポート名(0.0.0.0など)を入力:",
"title": "ホスト名"
},
"port": {
"label": "APIサーバーのポートを入力:",
"title": "ポート"
}
}
},
"audio-compressor": {
"description": "オーディオにコンプレッサーを適用します(信号での一番大きい部分の音量を下げ、小さい部分の音量を上げる)",
"name": "オーディオコンプレッサー"
@ -410,6 +457,21 @@
"description": "UIから直にMP3・ソースオーディオをダウンロードします",
"menu": {
"choose-download-folder": "ダウンロードフォルダ",
"download-finish-settings": {
"label": "完了時にダウンロード",
"prompt": {
"last-percent": "x パーセント後",
"last-seconds": "最後の x 秒",
"title": "保存するタイミング"
},
"submenu": {
"advanced": "高度な設定",
"enabled": "有効",
"mode": "時間モード",
"percent": "パーセント",
"seconds": "秒"
}
},
"download-playlist": "プレイリストをダウンロード",
"presets": "プリセット",
"skip-existing": "存在するファイルをスキップ"
@ -422,6 +484,18 @@
"button": "ダウンロード"
}
},
"equalizer": {
"description": "プレイヤーにイコライザーを追加",
"menu": {
"presets": {
"label": "プリセット",
"list": {
"bass-booster": "ベースブースター"
}
}
},
"name": "イコライザー"
},
"exponential-volume": {
"description": "音量スライダを指数関数的にさせ、低い音量に設定しやすくなります。",
"name": "指数音量"
@ -649,6 +723,59 @@
"description": "イントロ/アウトロなどの音楽以外の部分や、曲が再生されていないミュージック ビデオの部分を自動的にスキップします",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "LRClibのようなプロバイダを使って、楽曲に同期した歌詞を使用する。",
"errors": {
"fetch": "⚠️ - 歌詞の取得中にエラーが発生しました。 後でもう一度お試しください。",
"not-found": "⚠️ - この曲の歌詞は見つかりませんでした。"
},
"menu": {
"default-text-string": {
"label": "デフォルトの歌詞間の文字",
"tooltip": "歌詞と歌詞の間に使用するデフォルトの文字を選択してください"
},
"line-effect": {
"label": "歌詞表示のエフェクト",
"submenu": {
"focus": {
"label": "フォーカス",
"tooltip": "現在の行だけを白くする"
},
"offset": {
"label": "オフセット",
"tooltip": "オフセットを現在の行の右側にする"
},
"scale": {
"label": "サイズ",
"tooltip": "現在の行のサイズ変更をする"
}
},
"tooltip": "現在の行に適用するエフェクトを選択"
},
"precise-timing": {
"label": "歌詞を完璧に同期させる",
"tooltip": "次の行の表示をミリ秒単位で計算する(パフォーマンスに若干の影響を与える可能性があります)"
},
"show-lyrics-even-if-inexact": {
"label": "歌詞が不正確でも表示する",
"tooltip": "曲が見つからなかった場合、プラグインは別の検索クエリで再試行します。\nただし、再試行の結果は正確でない可能性があります。"
},
"show-time-codes": {
"label": "タイムコードを表示",
"tooltip": "歌詞の横にタイムコードを表示"
}
},
"name": "歌詞を同期",
"refetch-btn": {
"fetching": "取得中...",
"normal": "歌詞を再取得"
},
"warnings": {
"duration-mismatch": "⚠️ - タイミングが合わないため、歌詞が同期されていない可能性があります。",
"inexact": "⚠️ - この曲の歌詞は正確ではないかもしれません",
"instrumental": "⚠️ - これは演奏のみの曲です"
}
},
"taskbar-mediacontrol": {
"description": "Windowsタスクバーから再生をコントロール",
"name": "タスクバーメディアコントロール"

View File

@ -279,6 +279,56 @@
},
"name": "앰비언트 모드"
},
"amuse": {
"description": "6K Labs Amuse의 'now playing' 위젯에 YouTube Music 지원 추가",
"name": "Amuse",
"response": {
"query": "Amuse API 서버가 실행 중입니다. GET /query로 노래 정보를 가져오세요."
}
},
"api-server": {
"description": "플레이어를 제어하기 위한 API 서버를 추가합니다",
"dialog": {
"request": {
"buttons": {
"allow": "허용",
"deny": "거부"
},
"message": "{{ID}} ({{origin}})이(가) API에 액세스하도록 허용하시겠습니까?",
"title": "API 권한 요청"
}
},
"menu": {
"auth-strategy": {
"label": "인증 정책",
"submenu": {
"auth-at-first": {
"label": "첫 번째 요청 시 인증"
},
"none": {
"label": "인증 없음"
}
}
},
"hostname": {
"label": "호스트 명"
},
"port": {
"label": "포트"
}
},
"name": "API 서버 [베타]",
"prompt": {
"hostname": {
"label": "API 서버가 사용할 호스트 명(예: 0.0.0.0)을 입력하세요:",
"title": "호스트 명"
},
"port": {
"label": "API 서버가 사용할 포트를 입력하세요:",
"title": "포트"
}
}
},
"audio-compressor": {
"description": "오디오에 컴프레서를 적용합니다 (신호에서 가장 시끄러운 부분의 음량을 낮추고 가장 조용한 부분의 음량을 높임)",
"name": "오디오 컴프레서"
@ -441,6 +491,18 @@
"button": "다운로드"
}
},
"equalizer": {
"description": "플레이어에 이퀄라이저를 추가합니다",
"menu": {
"presets": {
"label": "프리셋",
"list": {
"bass-booster": "베이스 부스터"
}
}
},
"name": "이퀄라이저"
},
"exponential-volume": {
"description": "음량 슬라이더를 지수적으로 만들어 더 낮은 음량을 쉽게 선택할 수 있도록 합니다.",
"name": "지수 음량"
@ -671,8 +733,48 @@
"synced-lyrics": {
"description": "LRClib등의 가사 제공자에서 싱크 가사를 불러옵니다.",
"errors": {
"fetch": "⚠️ - 가사를 불러오는 동안 오류가 발생했습니다. 나중에 다시 시도해 주세요.",
"not-found": "⚠️ - 이 노래의 가사를 찾을 수 없습니다."
"fetch": "⚠️\t가사를 불러오는 동안 오류가 발생했습니다.\n\t나중에 다시 시도해 주세요.",
"not-found": "⚠️ 이 노래의 가사를 찾을 수 없습니다."
},
"menu": {
"default-text-string": {
"label": "가사 사이에 표시할 문자",
"tooltip": "가사 사이의 빈 공간에 사용할 문자를 선택합니다"
},
"line-effect": {
"label": "줄 표시 효과",
"submenu": {
"fancy": {
"label": "예쁘게",
"tooltip": "유튜브 뮤직 앱처럼 커다란 효과를 현재 라인에 사용합니다"
},
"focus": {
"label": "포커스",
"tooltip": "현재 줄만 하얀색으로 표시"
},
"offset": {
"label": "오프셋",
"tooltip": "현재 줄의 오른쪽에 오프셋 적용"
},
"scale": {
"label": "스케일",
"tooltip": "현재 줄에 스케일 적용"
}
},
"tooltip": "현재 줄에 적용할 효과를 선택합니다"
},
"precise-timing": {
"label": "가사를 최대한 정교하게 동기화",
"tooltip": "다음 줄의 표시를 밀리초 단위로 계산합니다 (성능에 약간의 영향을 미칠 수 있음)"
},
"show-lyrics-even-if-inexact": {
"label": "가사가 정확하지 않더라도 표시",
"tooltip": "노래를 찾을 수 없는 경우, 플러그인이 다른 검색어로 다시 검색합니다.\n두번째 검색 결과는 정확하지 않을 수 있습니다."
},
"show-time-codes": {
"label": "시간 코드 표시",
"tooltip": "가사 옆에 시간 코드 표시"
}
},
"name": "싱크 가사",
"refetch-btn": {

View File

@ -5,6 +5,7 @@
"execute-failed": "Pelaksaan plugin gagal {{pluginName}}::{{contextName}}",
"executed-at-ms": "Plugin {{pluginName}}::{{contextName}} dilaksanakan pada {{ms}}ms",
"initialize-failed": "Gagal untuk memulakan plugin \"{{pluginName}}\"",
"load-all": "Memuatkan semua plugin",
"loaded": "Plugin \"{{pluginName}}\" dimuatkan",
"unload-failed": "Gagal untuk memunggah plugin \"{{pluginName}}\"",
"unloaded": "Plugin \"{{pluginName}}\" dipunggahkan"
@ -39,15 +40,22 @@
"detail": "Menu telah disembunyikan, guna 'Alt' untuk menunjukkannya (atau 'Escape' jika menggunakan In-App Menu)"
},
"need-to-restart": {
"buttons": {
"later": "Nanti",
"restart-now": "Restart Sekarang"
},
"message": "\"{{pluginName}}\" perlu dimulakan semula",
"title": "Mulakan Semula Diperlukan"
},
"unresponsive": {
"buttons": {
"quit": "Berhenti",
"relaunch": "Lancar Semula",
"wait": "Tunggu"
},
"detail": "Kami memohon maaf atas kesulitan! sila pilih apa yang perlu dilakukan:"
"detail": "Kami memohon maaf atas kesulitan! sila pilih apa yang perlu dilakukan:",
"message": "Aplikasi Tidak Responsif",
"title": "Window Tidak Responsif"
},
"update-available": {
"buttons": {
@ -58,16 +66,137 @@
}
},
"menu": {
"about": "Mengenai",
"navigation": {
"label": "Navigasi",
"submenu": {
"copy-current-url": "Salin URL semasa",
"go-back": "Pulang",
"go-back": "Belakang",
"go-forward": "Depan",
"quit": "Keluar"
}
},
"options": {
"label": "Pilihan"
"label": "Tetapan",
"submenu": {
"advanced-options": {
"label": "Tetapan Lanjutan",
"submenu": {
"set-proxy": {
"prompt": {
"placeholder": "Contoh: SOCKS5://127.0.0.1:9999",
"title": "Set proksi"
}
}
}
},
"always-on-top": "Sentiasa di atas",
"auto-update": "Kemas Kini Automatik",
"hide-menu": {
"dialog": {
"message": "Menu akan disembunyikan pada pelancaran seterusnya, gunakan [Alt] untuk menunjukkannya (atau backtick [`] jika menggunakan dalam aplikasi-menu)"
}
},
"language": {
"dialog": {
"message": "Bahasa akan ditukar selepas dimulakan semula",
"title": "Bahasa Berubah"
},
"label": "Bahasa",
"submenu": {
"to-help-translate": "Ingin membantu menterjemah? Klik di sini"
}
},
"resume-on-start": "Mulakan semula lagu terakhir apabila aplikasi dimulakan",
"start-at-login": "Mulakan semasa log masuk",
"starting-page": {
"label": "Halaman Permulaan"
},
"tray": {
"submenu": {
"play-pause-on-click": "Main / Hentikan pada klik"
}
},
"visual-tweaks": {
"label": "Pembaikan Visual",
"submenu": {
"like-buttons": {
"default": "Lalai",
"hide": "Sembunyi"
},
"theme": {
"dialog": {
"button": {
"cancel": "Batalkan",
"remove": "Padam"
}
},
"label": "Tema"
}
}
}
}
}
},
"tray": {
"next": "Seterusnya",
"play-pause": "Main / Jeda",
"previous": "Sebelumnya",
"quit": "Keluar",
"restart": "Mulakan Semula Aplikasi"
}
},
"plugins": {
"ambient-mode": {
"menu": {
"quality": {
"label": "Kualiti"
},
"size": {
"label": "Saiz"
}
}
},
"captions-selector": {
"prompt": {
"selector": {
"title": "Pilih bahasa kapsyen"
}
}
},
"synced-lyrics": {
"menu": {
"show-lyrics-even-if-inexact": {
"label": "Tunjukkan lirik walaupun tidak tepat",
"tooltip": "Jika lagu tidak ditemui, plugin cuba lagi dengan pertanyaan carian yang berbeza. \nHasil dari percubaan kedua mungkin tidak tepat."
},
"show-time-codes": {
"tooltip": "Tunjukkan kod masa di sebelah lirik"
}
}
},
"taskbar-mediacontrol": {
"description": "Kawalan main balik dari bar tugas Windows anda",
"name": "Kawalan Media Bar Tugas"
},
"video-toggle": {
"menu": {
"align": {
"submenu": {
"left": "Kiri",
"middle": "Tengah",
"right": "Kanan"
}
},
"force-hide": "Alih Keluar Tab Video",
"mode": {
"submenu": {
"disabled": "Tidak Aktif"
}
}
},
"templates": {
"button": "Lagu"
}
}
}

View File

@ -158,6 +158,14 @@
},
"remove-upgrade-button": "Upgrade-knop verwijderen",
"theme": {
"dialog": {
"button": {
"cancel": "Annuleren",
"remove": "Verwijderen"
},
"remove-theme": "Weet je zeker dat je het aangepaste thema wilt verwijderen?",
"remove-theme-message": "Dit verwijderd het aangepaste thema"
},
"label": "Thema",
"submenu": {
"import-css-file": "Aangepast CSS-bestand importeren",
@ -199,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Wanneer een advertentie afspeelt, dempt het geluid en versnelt de playback naar 16x",
"name": "Snellere advertenties"
},
"adblocker": {
"description": "Blokkeer alle advertenties en tracking vanuit de doos",
"menu": {
@ -402,6 +414,21 @@
"description": "Download MP3 / bron-audio rechtstreeks vanuit de interface",
"menu": {
"choose-download-folder": "Kies de downloadmap",
"download-finish-settings": {
"label": "Downloaden bij voltooiing",
"prompt": {
"last-percent": "Na x procent",
"last-seconds": "Laatste x seconden",
"title": "Configureren wanneer te downloaden"
},
"submenu": {
"advanced": "Geavanceerd",
"enabled": "Ingeschakeld",
"mode": "Tijd-modus",
"percent": "Procent",
"seconds": "Seconden"
}
},
"download-playlist": "Afspeellijst downloaden",
"presets": "Voorinstellingen",
"skip-existing": "Bestaande bestanden overslaan"
@ -523,8 +550,20 @@
"save-window-size": "Sla schermgrootte op"
}
},
"video-toggle": {
"menu": {
"mode": {
"submenu": {
"disabled": "Uitgeschakeld"
}
}
}
},
"visualizer": {
"description": "Voeg een visuele equalizer toe",
"menu": {
"visualizer-type": "Type visualisator"
},
"name": "Visualisator"
}
}

View File

@ -279,6 +279,52 @@
},
"name": "Tryb otoczenia"
},
"amuse": {
"name": "Amuse"
},
"api-server": {
"description": "Pozwala na kontrolowanie YouTube Music poprzez podłączenie specjalnego serwera API",
"dialog": {
"request": {
"buttons": {
"allow": "Zezwól",
"deny": "Odmów"
},
"message": "Zezwolić {{ID}} (pochodzenie: {{origin}}) na dostęp do API?",
"title": "Prośba o autoryzację API"
}
},
"menu": {
"auth-strategy": {
"label": "Strategia autoryzacji",
"submenu": {
"auth-at-first": {
"label": "Autoryzuj przy pierwszej prośbie"
},
"none": {
"label": "Nie autoryzuj"
}
}
},
"hostname": {
"label": "Nazwa hosta (IP)"
},
"port": {
"label": "Port"
}
},
"name": "YouTube Music API",
"prompt": {
"hostname": {
"label": "Wpisz nazwę hosta (IP, np. 0.0.0.0), który będzie użyty do serwera API:",
"title": "Nazwa hosta"
},
"port": {
"label": "Wpisz port, z którego będzie korzystać serwer API:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Zastosuj kompresję do dźwięku (obniża głośność najgłośniejszych części sygnału i zwiększa głośność najcichszych części)",
"name": "Kompresor dźwięku"
@ -441,6 +487,18 @@
"button": "Pobierz"
}
},
"equalizer": {
"description": "Dodaje equalizer do odtwarzacza",
"menu": {
"presets": {
"label": "Presety",
"list": {
"bass-booster": "Wzmacniacz basu"
}
}
},
"name": "Equalizer"
},
"exponential-volume": {
"description": "Sprawia, że suwak głośności jest proporcjonalna, dzięki czemu łatwiej jest wybrać niższą głośność.",
"name": "Proporcjonalna głośność"
@ -668,6 +726,62 @@
"description": "Automatycznie pomija fragmenty niebędące muzyką, takie jak wstęp/zakończenie lub fragmenty teledysków, w których utwór nie jest odtwarzany",
"name": "Pomiń nieistotne fragmenty"
},
"synced-lyrics": {
"description": "Dodaje zsynchronizowane napisy do utworów używając między innymi LRClib.",
"errors": {
"fetch": "⚠️ - Wystąpił błąd podczas pobierania tekstu utworu. Spróbuj ponownie później.",
"not-found": "⚠️ - Nie znaleziono napisów dla tego utworu."
},
"menu": {
"default-text-string": {
"label": "Standardowy znak luki",
"tooltip": "Wybierz domyślny znak, który ma być wyświetlany jako pauza między słowami"
},
"line-effect": {
"label": "Efekty linijki",
"submenu": {
"fancy": {
"label": "Facy"
},
"focus": {
"label": "Fokus",
"tooltip": "Spraw, aby tylko obecna linijka była biała"
},
"offset": {
"label": "Przesunięcie",
"tooltip": "Przesuń w prawo obecną linijkę"
},
"scale": {
"label": "Skala",
"tooltip": "Zmień skalę aktualnej linijki"
}
},
"tooltip": "Wybierz efekt, by zastosować go do aktualnej linijki"
},
"precise-timing": {
"label": "Zsynchronizuj tekst utworu do perfekcji",
"tooltip": "Wylicz czas wyświetlania następnej linijki co do milisekundy (może mieć mały wpływ na wydajność systemu)"
},
"show-lyrics-even-if-inexact": {
"label": "Pokaż teksty, mimo niezgodności",
"tooltip": "Jeżeli nie znaleziono tekstu piosenki z bazy danych, wtyczka spróbuje ponownie przez wyszukanie przybliżonej frazy.\nNależy jednak pamiętać, że następne próby mogą nie być trafne co do oryginału."
},
"show-time-codes": {
"label": "Pokaż znaczniki czasu",
"tooltip": "Pokaż znaczniki czasu obok linijek"
}
},
"name": "Napisy zsynchronizowane",
"refetch-btn": {
"fetching": "Pobieranie napisów...",
"normal": "Odśwież napisy"
},
"warnings": {
"duration-mismatch": "⚠️ - Napisy mogą nie być zsynchronizowane z powodu różnicy w czasie trwania utworu.",
"inexact": "⚠️ - Tekst utworu może się różnić od oryginału",
"instrumental": "⚠️ - To jest utwór instrumentalny"
}
},
"taskbar-mediacontrol": {
"description": "Steruj odtwarzaniem z paska zadań systemu Windows",
"name": "Kontroler odtwarzania z paska zadań"

View File

@ -0,0 +1,836 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "Falha ao executar plugin {{pluginName}}::{{contextName}}",
"executed-at-ms": "Plugin {{pluginName}}::{{contextName}} executado em {{ms}} ms",
"initialize-failed": "Falha ao inicializar o plugin \"{{pluginName}}\"",
"load-all": "Carregando todos os plugins",
"load-failed": "Falha ao carregar o plugin \"{{pluginName}}\"",
"loaded": "Plugin \"{{pluginName}}\" carregado",
"unload-failed": "Falha ao descarregar o plugin \"{{pluginName}}\"",
"unloaded": "Plugin \"{{pluginName}}\" descarregado"
}
}
},
"language": {
"code": "pt-BR",
"local-name": "Português (Brasil)",
"name": "Portuguese (Brazil)"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "Carregamento concluído. DevTools aberto"
},
"i18n": {
"loaded": "i18n carregado"
},
"second-instance": {
"receive-command": "Comando recebido pelo protocolo: \"{{command}}\""
},
"theme": {
"css-file-not-found": "Arquivo CSS \"{{cssFile}}\" não existe, ignorando"
},
"unresponsive": {
"details": "Erro de falta de resposta!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Limpando cache do aplicativo"
},
"window": {
"tried-to-render-offscreen": "A janela tentou renderizar fora da tela, tamanho da janela={{windowSize}}, tamanho da tela={{displaySize}}, posição={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "O menu está oculto, use 'Alt' para mostrá-lo (ou 'Esc' ao usar o menu dentro do aplicativo)",
"message": "Ocultar menu está ativado",
"title": "Ocultar menu ativado"
},
"need-to-restart": {
"buttons": {
"later": "Depois",
"restart-now": "Reiniciar agora"
},
"detail": "O plugin \"{{pluginName}}\" requer uma reinicialização para entrar em vigor",
"message": "\"{{pluginName}}\" precisa reiniciar",
"title": "Necessário reiniciar"
},
"unresponsive": {
"buttons": {
"quit": "Fechar",
"relaunch": "Reiniciar",
"wait": "Aguardar"
},
"detail": "Lamentamos o inconveniente! Por favor, escolha o que fazer:",
"message": "O aplicativo não está respondendo",
"title": "Janela não responde"
},
"update-available": {
"buttons": {
"disable": "Desativar atualizações",
"download": "Baixar",
"ok": "OK"
},
"detail": "Uma versão mais recente está disponível em {{downloadLink}}",
"message": "Nova versão disponível",
"title": "Atualização disponível"
}
},
"menu": {
"about": "Sobre",
"navigation": {
"label": "Navegação",
"submenu": {
"copy-current-url": "Copiar URL atual",
"go-back": "Voltar",
"go-forward": "Avançar",
"quit": "Sair",
"restart": "Reiniciar aplicativo"
}
},
"options": {
"label": "Opções",
"submenu": {
"advanced-options": {
"label": "Opções avançadas",
"submenu": {
"auto-reset-app-cache": "Limpar cache ao iniciar aplicativo",
"disable-hardware-acceleration": "Desativar aceleração de hardware",
"edit-config-json": "Editar config.json",
"override-user-agent": "Substituir User-Agent",
"restart-on-config-changes": "Reiniciar ao alterar configurações",
"set-proxy": {
"label": "Definir proxy",
"prompt": {
"label": "Digite o endereço do proxy: (deixe em branco para desativar)",
"placeholder": "Exemplo: SOCKS5://127.0.0.1:9999",
"title": "Definir proxy"
}
},
"toggle-dev-tools": "Alternar DevTools"
}
},
"always-on-top": "Sempre no topo",
"auto-update": "Atualização automática",
"hide-menu": {
"dialog": {
"message": "O menu ficará oculto na próxima inicialização, use [Alt] para exibi-lo (ou a tecla de crase [`] se estiver usando o menu do aplicativo)",
"title": "Ocultar menu ativado"
},
"label": "Ocultar menu"
},
"language": {
"dialog": {
"message": "O idioma será alterado depois de reiniciar",
"title": "Idioma alterado"
},
"label": "Idioma",
"submenu": {
"to-help-translate": "Quer ajudar a traduzir? Clique aqui"
}
},
"resume-on-start": "Continuar última música ao iniciar o aplicativo",
"single-instance-lock": "Bloqueio de instância única",
"start-at-login": "Iniciar com o sistema",
"starting-page": {
"label": "Página inicial",
"unset": "Limpar"
},
"tray": {
"label": "Área de Notificação",
"submenu": {
"disabled": "Desativado",
"enabled-and-hide-app": "Ativado e aplicativo oculto",
"enabled-and-show-app": "Ativado e mostrar aplicativo",
"play-pause-on-click": "Reproduzir/Pausar ao clicar"
}
},
"visual-tweaks": {
"label": "Ajustes visuais",
"submenu": {
"like-buttons": {
"default": "Padrão",
"force-show": "Forçar exibir",
"hide": "Ocultar",
"label": "Botões de 'Curtir'"
},
"remove-upgrade-button": "Remover botão de atualização",
"theme": {
"dialog": {
"button": {
"cancel": "Cancelar",
"remove": "Remover"
},
"remove-theme": "Deseja realmente remover o tema personalizado?",
"remove-theme-message": "Isto removerá o tema personalizado"
},
"label": "Tema",
"submenu": {
"import-css-file": "Importar arquivo CSS personalizado",
"no-theme": "Sem tema"
}
}
}
}
}
},
"plugins": {
"enabled": "Ativado",
"label": "Plugins",
"new": "NOVO"
},
"view": {
"label": "Visualização",
"submenu": {
"force-reload": "Forçar recarregar",
"reload": "Recarregar",
"reset-zoom": "Tamanho atual",
"toggle-fullscreen": "Alternar tela cheia",
"zoom-in": "Ampliar",
"zoom-out": "Reduzir"
}
}
},
"tray": {
"next": "Próximo",
"play-pause": "Reproduzir/Pausar",
"previous": "Anterior",
"quit": "Sair",
"restart": "Reiniciar aplicativo",
"show": "Mostrar janela",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Se um anúncio for reproduzido, ele silencia o áudio e define a velocidade de reprodução para 16x",
"name": "Acelerador de Anúncios"
},
"adblocker": {
"description": "Bloqueio de todos os anúncios e rastreamentos imediatamente",
"menu": {
"blocker": "Bloqueador"
},
"name": "Bloqueador de Anúncios"
},
"album-actions": {
"description": "Adiciona botões Remover Não curtir, Não curtir, Curtir e Remover Curtir para aplicar em todas as músicas em uma lista ou álbum",
"name": "Ações do álbum"
},
"album-color-theme": {
"description": "Aplica um tema dinâmico e efeitos visuais com base na paleta de cores do álbum",
"menu": {
"color-mix-ratio": {
"label": "Proporção de mistura de cores",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Tema da cor do álbum"
},
"ambient-mode": {
"description": "Aplica um efeito de iluminação projetando cores suaves do vídeo no fundo da tela",
"menu": {
"blur-amount": {
"label": "Quantidade de desfoque",
"submenu": {
"pixels": "{{blurAmount}} pixels"
}
},
"buffer": {
"label": "Buffer",
"submenu": {
"buffer": "{{buffer}}"
}
},
"opacity": {
"label": "Opacidade",
"submenu": {
"percent": "{{opacity}}%"
}
},
"quality": {
"label": "Qualidade",
"submenu": {
"pixels": "{{quality}} pixels"
}
},
"size": {
"label": "Tamanho",
"submenu": {
"percent": "{{size}}%"
}
},
"smoothness-transition": {
"label": "Transição suave",
"submenu": {
"during": "Durante {{interpolationTime}} s"
}
},
"use-fullscreen": {
"label": "Usando tela cheia"
}
},
"name": "Modo ambiente"
},
"amuse": {
"description": "Adiciona suporte ao YouTube Music ao widget 'Reproduzindo agora' do Amuse da 6K Labs",
"name": "Amuse",
"response": {
"query": "Servidor API do Amuse em execução. GET /query para obter informações da música."
}
},
"api-server": {
"description": "Adiciona um servidor API para controlar o player",
"dialog": {
"request": {
"buttons": {
"allow": "Permitir",
"deny": "Negar"
},
"message": "Permitir que {{ID}} {{origin}} acesse o API?",
"title": "Pedido de autorização API"
}
},
"menu": {
"auth-strategy": {
"label": "Estratégia de autorização",
"submenu": {
"auth-at-first": {
"label": "Autorizar na primeira solicitação"
},
"none": {
"label": "Não autorizar"
}
}
},
"hostname": {
"label": "Nome do anfitrião"
},
"port": {
"label": "Porta"
}
},
"name": "Servidor API [Beta]",
"prompt": {
"hostname": {
"label": "Entre o nome do host (como 0.0.0.0) para o servidor API:",
"title": "Nome do anfitrião"
},
"port": {
"label": "Entre a porta do servidor API:",
"title": "Porta"
}
}
},
"audio-compressor": {
"description": "Aplicar compressão ao áudio (reduz o volume das partes mais altas e aumenta o volume das partes mais baixas)",
"name": "Compressor de áudio"
},
"blur-nav-bar": {
"description": "Torna a barra de navegação transparente e desfocada",
"name": "Desfocar barra de navegação"
},
"bypass-age-restrictions": {
"description": "Pular a verificação de idade do YouTube",
"name": "Ignorar restrições de idade"
},
"captions-selector": {
"description": "Seletor de legendas para faixas de áudio do YouTube Music",
"menu": {
"autoload": "Selecionar automaticamente a última legenda usada",
"disable-captions": "Sem legendas por padrão"
},
"name": "Seletor de legendas",
"prompt": {
"selector": {
"label": "Idioma atual da legenda: {{language}}",
"none": "Nenhum",
"title": "Selecionar idioma da legenda"
}
},
"templates": {
"title": "Abrir seletor de legendas"
}
},
"compact-sidebar": {
"description": "Sempre definir a barra lateral no modo compacto",
"name": "Barra lateral compacta"
},
"crossfade": {
"description": "Crossfade entre músicas",
"menu": {
"advanced": "Avançado"
},
"name": "Crossfade [Beta]",
"prompt": {
"options": {
"multi-input": {
"fade-in-duration": "Duração do fade (ms)",
"fade-out-duration": "Duração do fade out (ms)",
"fade-scaling": {
"label": "Escala do fade",
"linear": "Linear",
"logarithmic": "Logarítmico"
},
"seconds-before-end": "Crossfade N segundos antes do fim"
},
"title": "Opções de crossfade"
}
}
},
"disable-autoplay": {
"description": "Faz a música começar no modo \"pausado\"",
"menu": {
"apply-once": "Aplicar somente ao iniciar"
},
"name": "Desativar reprodução automática"
},
"discord": {
"backend": {
"already-connected": "Tentativa de conectar-se com conexão ativa",
"connected": "Conectado no Discord",
"disconnected": "Desconectado do Discord"
},
"description": "Mostre aos seus amigos o que você ouve com Rich Presence",
"menu": {
"auto-reconnect": "Reconexão automática",
"clear-activity": "Limpar atividades",
"clear-activity-after-timeout": "Limpar atividades após tempo limite",
"connected": "Conectado",
"disconnected": "Desconectado",
"hide-duration-left": "Ocultar duração restante",
"hide-github-button": "Ocultar botão do GitHub",
"play-on-youtube-music": "Reproduzir no YouTube Music",
"set-inactivity-timeout": "Definir tempo limite de inatividade"
},
"name": "Rich Presence do Discord",
"prompt": {
"set-inactivity-timeout": {
"label": "Digite o tempo de inatividade em segundos:",
"title": "Definir tempo limite de inatividade"
}
}
},
"downloader": {
"backend": {
"dialog": {
"error": {
"buttons": {
"ok": "OK"
},
"message": "Ah! Desculpe, o download falhou…",
"title": "Erro no download!"
},
"start-download-playlist": {
"buttons": {
"ok": "OK"
},
"detail": "({{playlistSize}} músicas)",
"message": "Baixando lista de reprodução {{playlistTitle}}",
"title": "Download iniciado"
}
},
"feedback": {
"conversion-progress": "Convertendo: {{percent}}%",
"converting": "Convertendo…",
"done": "Concluído: {{filePath}}",
"download-info": "Baixando {{artist}} - {{title}} [{{videoId}}",
"download-progress": "Download: {{percent}}%",
"downloading": "Baixando…",
"downloading-counter": "Baixando {{current}}/{{total}}…",
"downloading-playlist": "Baixando lista de reprodução \"{{playlistTitle}}\" - {{playlistSize}} músicas ({{playlistId}})",
"error-while-downloading": "Erro ao baixar \"{{author}} - {{title}}\": {{error}}",
"folder-already-exists": "A pasta {{playlistFolder}} já existe",
"getting-playlist-info": "Obtendo informações da playlist…",
"loading": "Carregando…",
"playlist-has-only-one-song": "Playlist possui apenas um item, baixando diretamente",
"playlist-id-not-found": "Nenhum playlist ID encontrado",
"playlist-is-empty": "Playlist está vazia",
"playlist-is-mix-or-private": "Erro ao obter informações da playlist: verifique se não é uma playlist privada ou “”Mixada para você”\n\n{{error}}",
"preparing-file": "Preparando arquivo…",
"saving": "Salvando…",
"trying-to-get-playlist-id": "Tentando obter playlist ID: {{playlistId}}",
"video-id-not-found": "Vídeo não encontrado",
"writing-id3": "Salvando tags ID3…"
}
},
"description": "Faça download do MP3 / fonte de áudio diretamente da interface",
"menu": {
"choose-download-folder": "Escolha a pasta de download",
"download-finish-settings": {
"label": "Baixar ao finalizar",
"prompt": {
"last-percent": "Após x %",
"last-seconds": "Últimos x segundos",
"title": "Configurar quando baixar"
},
"submenu": {
"advanced": "Avançado",
"enabled": "Ativado",
"mode": "Modo de tempo",
"percent": "Porcento",
"seconds": "Segundos"
}
},
"download-playlist": "Baixar playlist",
"presets": "Predefinições",
"skip-existing": "Pular arquivos existentes"
},
"name": "Downloader",
"renderer": {
"can-not-update-progress": "Não é possível atualizar o progresso"
},
"templates": {
"button": "Baixar"
}
},
"equalizer": {
"description": "Adiciona um equalizador ao player",
"menu": {
"presets": {
"label": "Predefinições",
"list": {
"bass-booster": "Reforço de graves"
}
}
},
"name": "Equalizador"
},
"exponential-volume": {
"description": "Torna o controle deslizante de volume exponencial para que seja mais fácil selecionar volumes mais baixos.",
"name": "Volume Exponencial"
},
"in-app-menu": {
"description": "Dá às barras de menu uma aparência elegante, escura ou com a cor do álbum",
"menu": {
"hide-dom-window-controls": "Ocultar controles da janela DOM"
},
"name": "Menu no aplicativo"
},
"lumiastream": {
"description": "Adiciona suporte ao Lumia Stream",
"name": "Lumia Stream [Beta]"
},
"lyrics-genius": {
"description": "Adiciona suporte a letras para a maioria das músicas",
"menu": {
"romanized-lyrics": "Letras Romanizadas"
},
"name": "Letras Genius",
"renderer": {
"fetched-lyrics": "Letras buscadas por Genius"
}
},
"music-together": {
"description": "Compartilhe uma playlist com outras pessoas. Quando o anfitrião toca uma música, todos os outros ouvirão",
"dialog": {
"enter-host": "Insira o ID do host"
},
"internal": {
"save": "Salvar",
"track-source": "Fonte da Faixa",
"unknown-user": "Usuário Desconhecido"
},
"menu": {
"click-to-copy-id": "Copiar ID do host",
"close": "Fechar Music Together",
"connected-users": "Usuários Conectados",
"disconnect": "Desconectar Music Together",
"empty-user": "Nenhum usuário conectado",
"host": "Anfitrião do Music Together",
"join": "Entrar no Music Together",
"permission": {
"all": "Permitir que os convidados controlem a lista de reprodução e o player",
"host-only": "Somente o host pode controlar a lista de reprodução e o player",
"playlist": "Permitir que os convidados controlem a lista de reprodução"
},
"set-permission": "Mudar Permissões de Controle",
"status": {
"disconnected": "Desconectado",
"guest": "Conectado como convidado",
"host": "Conectado como Anfitrião"
}
},
"name": "Music Together [Beta]",
"toast": {
"add-song-failed": "Falha ao adicionar música",
"closed": "Music Together fechado",
"disconnected": "Music Together desconectado",
"host-failed": "Falha ao hospedar o Music Together",
"id-copied": "ID do anfitrião copiado para a área de transferência",
"id-copy-failed": "Falha ao copiar o ID do anfitrião para a área de transferência",
"join-failed": "Falha ao ingressar no Music Together",
"joined": "Entrou no Music Together",
"permission-changed": "A permissão do Music Together foi alterada para \"{{permission}}\"",
"remove-song-failed": "Falha ao remover música",
"user-connected": "{{name}} juntou-se ao Music Together",
"user-disconnected": "{{name}} saiu do Music Together"
}
},
"navigation": {
"description": "Setas de navegação para avançar/retornar diretamente integradas na interface, como no seu navegador favorito",
"name": "Navegação"
},
"no-google-login": {
"description": "Remova os botões e links de login do Google da interface",
"name": "Sem login do Google"
},
"notifications": {
"description": "Exibir uma notificação quando uma música começar a tocar (notificações interativas estão disponíveis no Windows)",
"menu": {
"interactive": "Notificações interativas",
"interactive-settings": {
"label": "Configurações interativas",
"submenu": {
"hide-button-text": "Ocultar texto do botão",
"refresh-on-play-pause": "Atualizar ao Reproduzir/Pausar",
"tray-controls": "Abrir/Fechar ao clicar na área de notificação"
}
},
"priority": "Prioridade da notificação",
"toast-style": "Estilo de alerta",
"unpause-notification": "Mostrar notificação ao despausar"
},
"name": "Notificações"
},
"picture-in-picture": {
"description": "Permite alternar o aplicativo para o modo picture-in-picture",
"menu": {
"always-on-top": "Sempre no topo",
"hotkey": {
"label": "Tecla de atalho",
"prompt": {
"keybind-options": {
"hotkey": "Tecla de atalho"
},
"label": "Escolha uma tecla de atalho para alternar entre picture-in-picture",
"title": "Atalho do picture-in-picture"
}
},
"save-window-position": "Salvar posição da janela",
"save-window-size": "Salvar tamanho da janela",
"use-native-pip": "Usar PiP nativo do navegador"
},
"name": "Picture-in-picture",
"templates": {
"button": "Picture-in-picture"
}
},
"playback-speed": {
"description": "Ouça rápido, ouça devagar! Adiciona um controle deslizante que controla a velocidade da música",
"name": "Velocidade de reprodução",
"templates": {
"button": "Velocidade"
}
},
"precise-volume": {
"description": "Controle o volume com precisão usando a roda do mouse/teclas de atalho, com um HUD personalizado e etapas de volume personalizáveis",
"menu": {
"arrows-shortcuts": "Controles de teclas de seta locais",
"custom-volume-steps": "Definir etapas de volume personalizadas",
"global-shortcuts": "Teclas de atalho globais"
},
"name": "Volume preciso",
"prompt": {
"global-shortcuts": {
"keybind-options": {
"decrease": "Diminuir volume",
"increase": "Aumentar volume"
},
"label": "Selecione as teclas de atalho global do volume:",
"title": "Teclas de atalho global de volume"
},
"volume-steps": {
"label": "Escolha as etapas de aumento/diminuição do volume",
"title": "Fases de volume"
}
}
},
"quality-changer": {
"backend": {
"dialog": {
"quality-changer": {
"detail": "Qualidade atual: {{quality}}",
"message": "Escolher qualidade do vídeo:",
"title": "Escolher qualidade do vídeo"
}
}
},
"description": "Permite alterar a qualidade do vídeo com um botão na sobreposição de vídeo",
"name": "Alterador de qualidade do vídeo"
},
"scrobbler": {
"description": "Adicionar suporte para scrobbling (last.fm, Listenbrainz, etc.)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Falha ao autenticar com Last.fm\nOcultar o pop-up até a próxima reinicialização.",
"title": "Falha na autenticação"
}
}
},
"menu": {
"lastfm": {
"api-settings": "Configurações da API do Last.fm"
},
"listenbrainz": {
"token": "Insira o token de usuário ListenBrainz"
},
"scrobble-other-media": "Scrobble outras mídias"
},
"name": "Scrobbler",
"prompt": {
"lastfm": {
"api-key": "Chave de API do Last.fm",
"api-secret": "Chave secreta da API do Last.fm"
},
"listenbrainz": {
"token": {
"label": "Insira seu token de usuário do ListenBrainz:",
"title": "ListenBrainz token"
}
}
}
},
"shortcuts": {
"description": "Permite definir teclas de atalho globais para reprodução (reproduzir/pausar/próximo/anterior) e desativar o OSD de mídia substituindo as teclas de mídia, ativando Ctrl/CMD + F para pesquisar, ativando o suporte Linux MPRIS para teclas de mídia e teclas de atalho personalizadas para usuários avançados",
"menu": {
"override-media-keys": "Substituir chaves de multimédia",
"set-keybinds": "Definir controles globais de música"
},
"name": "Atalhos (& MPRIS)",
"prompt": {
"keybind": {
"keybind-options": {
"next": "Próximo",
"play-pause": "Reproduzir / Pausar",
"previous": "Anterior"
},
"label": "Escolha atalhos de teclado globais para controle de músicas:",
"title": "Atalhos de teclado global"
}
}
},
"skip-disliked-songs": {
"description": "Ignora músicas marcadas com \"não gostei\"",
"name": "Pular músicas marcadas com \"não gostei\""
},
"skip-silences": {
"description": "Pular automaticamente seções de silêncio em músicas",
"name": "Pular silêncios"
},
"sponsorblock": {
"description": "Pula automaticamente partes não musicais, como introdução/finalização ou partes de videoclipes onde a música não está tocando",
"name": "SponsorBlock [Bloquear patrocínios]"
},
"synced-lyrics": {
"description": "Fornece letras sincronizadas para músicas, usando provedores como LRClib.",
"errors": {
"fetch": "⚠️\tOcorreu um erro ao buscar a letra.\n\tTente novamente mais tarde.",
"not-found": "⚠️ Nenhuma letra encontrada para esta música."
},
"menu": {
"default-text-string": {
"label": "Caractere padrão entre letras",
"tooltip": "Escolha o caractere padrão a ser usado para o intervalo entre as letras"
},
"line-effect": {
"label": "Efeito de linha",
"submenu": {
"fancy": {
"label": "Fancy",
"tooltip": "Use efeitos grandes, semelhantes a aplicativos, na linha atual"
},
"focus": {
"label": "Foco",
"tooltip": "Deixe apenas a linha atual branca"
},
"offset": {
"label": "Deslocar",
"tooltip": "Deslocamento à direita da linha atual"
},
"scale": {
"label": "Aumentar",
"tooltip": "Aumentar a linha atual"
}
},
"tooltip": "Escolha o efeito a ser aplicado à linha atual"
},
"precise-timing": {
"label": "Deixa as letras perfeitamente sincronizadas",
"tooltip": "Calcular até o milissegundo a exibição da próxima linha (pode ter um pequeno impacto no desempenho)"
},
"show-lyrics-even-if-inexact": {
"label": "Mostrar letras mesmo que não sejam exatas",
"tooltip": "Se a música não for encontrada, o plugin tenta novamente com uma consulta de pesquisa diferente.\nO resultado da segunda tentativa pode não ser exato."
},
"show-time-codes": {
"label": "Mostrar códigos de tempo",
"tooltip": "Mostrar os códigos de tempo ao lado das letras"
}
},
"name": "Letras sincronizadas",
"refetch-btn": {
"fetching": "Buscando...",
"normal": "Buscar letras novamente"
},
"warnings": {
"duration-mismatch": "⚠️ - A letra pode estar dessincronizada devido a uma incompatibilidade de duração.",
"inexact": "⚠️ - A letra desta música pode não ser exata",
"instrumental": "⚠️ - Esta é uma música instrumental"
}
},
"taskbar-mediacontrol": {
"description": "Controle a reprodução na barra de tarefas do Windows",
"name": "Controle de mídia da barra de tarefas"
},
"touchbar": {
"description": "Adiciona um widget TouchBar para usuários do macOS",
"name": "TouchBar"
},
"tuna-obs": {
"description": "Integração com o plugin Tuna do OBS",
"name": "Tuna OBS"
},
"video-toggle": {
"description": "Adiciona um botão para alternar entre o modo Vídeo/Música. Também é possível remover opcionalmente toda a aba de vídeo",
"menu": {
"align": {
"label": "Alinhamento",
"submenu": {
"left": "Esquerda",
"middle": "Meio",
"right": "Direita"
}
},
"force-hide": "Forçar remoção da aba de vídeo",
"mode": {
"label": "Modo",
"submenu": {
"custom": "Alternância personalizada",
"disabled": "Desativado",
"native": "Alternância nativa"
}
}
},
"name": "Alternar vídeo",
"templates": {
"button": "Música"
}
},
"visualizer": {
"description": "Adiciona um visualizador ao player",
"menu": {
"visualizer-type": "Tipo de visualizador"
},
"name": "Visualizador"
}
}
}

View File

@ -279,6 +279,37 @@
},
"name": "Modo Ambiente"
},
"api-server": {
"dialog": {
"request": {
"buttons": {
"allow": "Permitir",
"deny": "Negar"
}
}
},
"menu": {
"auth-strategy": {
"label": "Estratégia de Autorização",
"submenu": {
"auth-at-first": {
"label": "Autorizar ao primeiro pedido"
},
"none": {
"label": "Sem autorização"
}
}
},
"port": {
"label": "Porta"
}
},
"prompt": {
"port": {
"title": "Porta"
}
}
},
"audio-compressor": {
"description": "Aplicar compressão ao áudio (diminui o volume das partes mais altas do sinal e aumenta o volume das partes mais suaves)",
"name": "Compressor de áudio"
@ -668,6 +699,59 @@
"description": "Ignora automaticamente partes não musicais, como introdução/final ou partes de videoclipes onde a música não está tocando",
"name": "SponsorBlock (bloqueador de patrocínios)"
},
"synced-lyrics": {
"description": "Fornece letras sincronizadas de músicas, utilizando fornecedores como o LRClib.",
"errors": {
"fetch": "⚠️ - Ocorreu um erro ao obter as letras da música. Por favor, tenta novamente mais tarde.",
"not-found": "⚠️ - Não foram encontradas letras para esta música."
},
"menu": {
"default-text-string": {
"label": "Caractere padrão entre as letras",
"tooltip": "Escolha o caractere padrão para usar no espaço entre as letras"
},
"line-effect": {
"label": "Efeito de linha",
"submenu": {
"focus": {
"label": "Foco",
"tooltip": "Deixe apenas a linha atual branca"
},
"offset": {
"label": "Deslocamento",
"tooltip": "Desloque a linha atual para a direita"
},
"scale": {
"label": "Escala",
"tooltip": "Escalar a linha atual"
}
},
"tooltip": "Escolha o efeito a ser aplicado à linha atual"
},
"precise-timing": {
"label": "Sincronize perfeitamente as letras",
"tooltip": "Calcule até o milissegundo a exibição da próxima linha (pode ter um pequeno impacto no desempenho)"
},
"show-lyrics-even-if-inexact": {
"label": "Mostrar letras mesmo que imprecisas",
"tooltip": "Se a música não for encontrada, o plugin tenta novamente com uma consulta de pesquisa diferente.\nO resultado da segunda tentativa pode não ser exato."
},
"show-time-codes": {
"label": "Mostrar códigos de tempo",
"tooltip": "Mostrar os códigos de tempo ao lado das letras"
}
},
"name": "Letras Sincronizadas",
"refetch-btn": {
"fetching": "Buscando...",
"normal": "Buscar as letras novamente"
},
"warnings": {
"duration-mismatch": "⚠️ - As letras da música pode estar dessincronizada devido a um erro de duração.",
"inexact": "⚠️ - As letras desta música podem não ser exactas.",
"instrumental": "⚠️ - Esta é uma música instrumental."
}
},
"taskbar-mediacontrol": {
"description": "Controle a reprodução na barra de tarefas do Windows",
"name": "Controle de mídia da barra de tarefas"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Reclamele au sunetul dezactivat si viteza de redare este x16",
"name": "Accelerare reclame"
},
"adblocker": {
"description": "Blocheaza toate reclamele si trackers",
"menu": {
@ -275,6 +279,49 @@
},
"name": "Mod ambiental"
},
"api-server": {
"description": "Adauga un server API pentru a controla player-ul",
"dialog": {
"request": {
"buttons": {
"allow": "Permite",
"deny": "Respinge"
},
"message": "Permite {{ID}} {{origin}} sa acceseze API-ul?",
"title": "Cerere autorizare API"
}
},
"menu": {
"auth-strategy": {
"label": "Strategie autorizare",
"submenu": {
"auth-at-first": {
"label": "Autorizare la prima cerere"
},
"none": {
"label": "Fara autorizare"
}
}
},
"hostname": {
"label": "Nume host"
},
"port": {
"label": "Port"
}
},
"name": "Server API [Beta]",
"prompt": {
"hostname": {
"label": "Introduceti nume host (0.0.0.0 de ex.) pentru server-ul API:",
"title": "Nume host"
},
"port": {
"label": "Introduceti port-ul pentru server-ul API:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Aplica compresie pe audio (scade volumul partilor cele mai sonore si creste volumul partilor mai putin sonore)",
"name": "Compresor audio"
@ -410,6 +457,21 @@
"description": "Descarca MP3 / sursa audio direct din interfata",
"menu": {
"choose-download-folder": "Alege folderul de descarcari",
"download-finish-settings": {
"label": "Descarcare la finalizare",
"prompt": {
"last-percent": "Dupa x la suta",
"last-seconds": "Ultimele x secunde",
"title": "Configureaza cand sa descarce"
},
"submenu": {
"advanced": "Avansat",
"enabled": "Activat",
"mode": "Mod timp",
"percent": "Procentaj",
"seconds": "Secunde"
}
},
"download-playlist": "Descarca playlist-ul",
"presets": "Setari implicite",
"skip-existing": "Treci peste fisierele existente"
@ -649,6 +711,59 @@
"description": "Treci automat peste partile non-muzicale precum intro/outro sau parti din video-ul catecului, cand nu se aude cantecul",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Furnizeaza versuri sincronizate melodiilor, folosind furnizori precum LRClib.",
"errors": {
"fetch": "⚠️ - A aparut o eroare in timpul incarcarii versurilor. Te rog incearca din nou mai tarziu.",
"not-found": "⚠️ - Nu au fost gasite versuri pentru aceasta melodie."
},
"menu": {
"default-text-string": {
"label": "Caracter implicit intre versuri",
"tooltip": "Alege caracterul implicit folosit pentru spatiul dintre versuri"
},
"line-effect": {
"label": "Efect de linie",
"submenu": {
"focus": {
"label": "Focalizare",
"tooltip": "Doar linia curenta este alba"
},
"offset": {
"label": "Offset",
"tooltip": "Deplasare la dreapta pentru linia curenta"
},
"scale": {
"label": "Marime",
"tooltip": "Schimba dimensiunea liniei curente"
}
},
"tooltip": "Alege efectul aplicat liniei curente"
},
"precise-timing": {
"label": "Sincronizeaza versurile perfect",
"tooltip": "Calculeaza afisarea urmatoarei linii pana la milisecunda (poate afecta performanta)"
},
"show-lyrics-even-if-inexact": {
"label": "Afiseaza versurile chiar daca sunt inexacte",
"tooltip": "Daca melodia nu este gasita, plugin-ul incearca din nou cu o cautare diferita.\nRezultatul acestei incercari poate sa nu fie exact."
},
"show-time-codes": {
"label": "Afiseaza timecode-urile",
"tooltip": "Afiseaza codurile de timp langa versuri"
}
},
"name": "Versuri Sincronizate",
"refetch-btn": {
"fetching": "Incarcare...",
"normal": "Reincarcare versuri"
},
"warnings": {
"duration-mismatch": "⚠️ - Versurile pot fi desincronizate din cauza unei nepotriviri de duratie.",
"inexact": "⚠️ - Versurile pentru aceasta melodie pot fi inexacte",
"instrumental": "⚠️ - Aceasta melodie este instrumentala"
}
},
"taskbar-mediacontrol": {
"description": "Controleaza redarea din Bara de Activitati Windows",
"name": "Control media in Bara de Activitate"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Если воспроизводится реклама, аудио заглушается и скорость воспроизведения устанавливается на 16х",
"name": "Ускоренная перемотка"
},
"adblocker": {
"description": "Блокируйте всю рекламу и трекинг сразу после установки",
"menu": {
@ -275,9 +279,59 @@
},
"name": "Режим Ambient"
},
"amuse": {
"description": "Добавляет поддержку виджета Amuse „сейчас играет“ от 6K Labs",
"name": "Amuse",
"response": {
"query": "Сервер Amuse API запущен. GET /query чтобы получить информацию о треке."
}
},
"api-server": {
"description": "Добавляет API сервер для контроля за плеером",
"dialog": {
"request": {
"buttons": {
"allow": "Разрешить",
"deny": "Отказать"
},
"message": "Разрешить {{ID}} ({{origin}}) доступ к API?",
"title": "Запрос на авторизацию в API"
}
},
"menu": {
"auth-strategy": {
"label": "Способ авторизации",
"submenu": {
"auth-at-first": {
"label": "Авторизация при первом запросе"
},
"none": {
"label": "Без авторизации"
}
}
},
"hostname": {
"label": "Имя хоста"
},
"port": {
"label": "Порт"
}
},
"name": "API Сервер [БЕТА]",
"prompt": {
"hostname": {
"label": "Введите имя хоста (на подобии 0.0.0.0) для API сервера:",
"title": "Имя хоста"
},
"port": {
"label": "Введите порт для API сервера:",
"title": "Порт"
}
}
},
"audio-compressor": {
"description": "Применяет компрессию к аудио (уменьшает громкость самых громких частей сигнала и повышает громкость самых тихих частей)",
"name": "Аудио компрессор"
"name": "Нормализация аудио"
},
"blur-nav-bar": {
"description": "Делает панель навигации прозрачной и размытой",
@ -410,6 +464,21 @@
"description": "Скачивать MP3 / исходное аудио напрямую из интерфейса",
"menu": {
"choose-download-folder": "Выберите папку для загрузок",
"download-finish-settings": {
"label": "Скачать по завершению",
"prompt": {
"last-percent": "После х процентов",
"last-seconds": "Осталось x сек",
"title": "Условия скачивания"
},
"submenu": {
"advanced": "Расширенные настройки",
"enabled": "Включено",
"mode": "Режим по времени",
"percent": "Процент",
"seconds": "Секунды"
}
},
"download-playlist": "Скачать плейлист",
"presets": "Пресеты",
"skip-existing": "Пропускать уже существующие файлы"
@ -422,6 +491,18 @@
"button": "Скачать"
}
},
"equalizer": {
"description": "Добавляет эквалайзер к плееру",
"menu": {
"presets": {
"label": "Предустановки",
"list": {
"bass-booster": "Усилитель баса"
}
}
},
"name": "Эквалайзер"
},
"exponential-volume": {
"description": "Делает слайдер громкости расширенным чтобы было легче понижать громкость.",
"name": "Расширенная громкость"
@ -590,7 +671,7 @@
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Не удалось войти с помощью Last.fm\nСкрыть сообщение до следующего запуска",
"message": "Не удалось войти с помощью Last.fm\nСкрыть сообщение до следующего запуска.",
"title": "Ошибка аунтефикации"
}
}
@ -649,6 +730,63 @@
"description": "Автоматически пропускает не музыкальные фрагменты, например интро/аутро или фрагменты музыкальных клипов, в которых песня не звучит (тишина)",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Предоставляет синхронизированные слова для песен из таких источников, как LRClib.",
"errors": {
"fetch": "⚠️\tПроизошла ошибка во время получения слов.\n\tПовторите попытку позже.",
"not-found": "⚠️ Для этой песни не найдено слов."
},
"menu": {
"default-text-string": {
"label": "Стандартный символ между словами",
"tooltip": "Выберите стандартный символ для заполнения пространства между словами"
},
"line-effect": {
"label": "Эффект строки",
"submenu": {
"fancy": {
"label": "Красивый",
"tooltip": "Использовать большие эффекты строки, как в приложении"
},
"focus": {
"label": "Фокусировка",
"tooltip": "Делает только текущую строку белой"
},
"offset": {
"label": "Сдвиг",
"tooltip": "Сдвигает текущую строку вправо"
},
"scale": {
"label": "Увеличение",
"tooltip": "Увеличивает текущую строку"
}
},
"tooltip": "Выберите эффект применяемый к текущей строке"
},
"precise-timing": {
"label": "Идеально синхронизировать слова",
"tooltip": "До миллисекунды рассчитывает отображение следующей строки(может оказать небольшое влияние на производительность)"
},
"show-lyrics-even-if-inexact": {
"label": "Показывать слова, даже если неточные",
"tooltip": "Если песня не найдена, плагин попытается снова с другим поисковым запросом.\nСо второй попытки результат может быть неточным."
},
"show-time-codes": {
"label": "Показывать временные метки",
"tooltip": "Показывает временные метки рядом со словами"
}
},
"name": "Синхронизированные тексты песен",
"refetch-btn": {
"fetching": "Сбор данных...",
"normal": "Обновить слова"
},
"warnings": {
"duration-mismatch": "⚠️ - Слова могут быть неточно синхронизированы из-за несовпадения длины трека.",
"inexact": "⚠️ - Слова для этой песни могут быть неточными",
"instrumental": "⚠️ - Это инструментальная музыка"
}
},
"taskbar-mediacontrol": {
"description": "Управляйте воспроизведением с панели задач Windows",
"name": "Управление мультимедиа на панели задач"
@ -692,7 +830,7 @@
"menu": {
"visualizer-type": "Вид визуализации"
},
"name": "Визуалайзер"
"name": "Визуализатор"
}
}
}

View File

@ -31,11 +31,74 @@
},
"theme": {
"css-file-not-found": "සීඑස්එස් ගොනුව \"{{cssFile}}\" නොපවතී, නොසලකා හැරීම"
},
"unresponsive": {
"details": "ප්‍රතිචාර නොදක්වන දෝෂයක් {{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "යෙදුම් කෑශ් නිදහස් කරමින්"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "මෙනුව සැගවී ඇත, 'Alt' යතුර නැවත පෙන්වීමට භාවිතා කරන්න. (හෝ In-App මෙනුවේ 'Escape')",
"message": "මෙනුව සැගවීම සාර්තකයි",
"title": "මෙනුව සැගවීම සක්‍රීයයි"
},
"need-to-restart": {
"buttons": {
"later": "පසුව",
"restart-now": "යෙදුම වසා නැවත ආරම්භ කරන්න"
},
"detail": "\"{{pluginName}}\" ප්ලගිනය යෙදුම නැවත ආරම්භ කිරීමක් ඉල්ලයි",
"message": "\"{{pluginName}}\" නැවත ආරම්භ කළ යුතුය",
"title": "නැවත ආරම්භ කිරීම අවශ්‍යයි"
},
"unresponsive": {
"buttons": {
"quit": "ඉවත් වන්න",
"relaunch": "නැවත ආරම්භ කරන්න",
"wait": "රැදී සිටින්න"
},
"detail": "සිදු වූ දේ සම්බන්ධව අපගේ කණගාටුව! කළ යුතු දේ තෝරන්න:",
"message": "යෙදුම ප්‍රතිචාර නොදක්වයි",
"title": "වින්ඩෝව ප්‍රතිචාර නොදක්වයි"
},
"update-available": {
"buttons": {
"disable": "යාවත්කාලීන කිරීම් නවතන්න",
"download": "බාගත කිරීම",
"ok": "හරි"
},
"detail": "නව අනුවාදයක් ඇති අතර එය මෙයින් බාගන්න {{downloadLink}}",
"message": "නව අනුවාදයක් ඇත",
"title": "යාවත්කාලීන කිරීමක් ඇත"
}
},
"menu": {
"about": "පිළිබදව",
"navigation": {
"label": "සංචලනය",
"submenu": {
"copy-current-url": "යොමුව පිටපත් කරගන්න",
"go-back": "පිටුපසට",
"go-forward": "ඉදිරියට",
"quit": "පිටවන්න",
"restart": "යෙදුම යලි අරඹන්න"
}
},
"options": {
"label": "විකල්ප",
"submenu": {
"advanced-options": {
"label": "උසස් විකල්ප",
"submenu": {
"auto-reset-app-cache": "යෙදුම් කෑච් යෙදුම ආරම්භයේදී යලි පිහිටුවන්න",
"disable-hardware-acceleration": "දෘඩාංග භාවිත වේගවත් කිරීම් අක්‍රීය කරන්න",
"edit-config-json": "config.json සකසන්න"
}
}
}
}
}
}

View File

@ -3,7 +3,7 @@
"console": {
"plugins": {
"execute-failed": "Napaka pri inicilizaciji dodatka {{pluginName}}::{{contextName}}",
"executed-at-ms": "Dodatek {{pluginName}}::{{contextName}} izvešen pri {{ms}}ms",
"executed-at-ms": "Dodatek {{pluginName}}::{{contextName}} izvršen pri {{ms}}ms",
"initialize-failed": "Napaka pri inicilizaciji dodatka \"{{pluginName}}\"",
"load-all": "Nalaganje dodatkov",
"load-failed": "Napaka pri nalaganju dodatka \"{{pluginName}}\"",
@ -36,7 +36,7 @@
"details": "Neodzivna napaka!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Čiščenje predpolnilnika"
"clearing-cache-after-20s": "Čiščenje predpomnilnika"
},
"window": {
"tried-to-render-offscreen": "Okno se je poskusilo prikazati izven ekrana, windowSize={{windowSize}}, displaySize={{displaySize}}, position={{position}}"
@ -46,13 +46,14 @@
"hide-menu-enabled": {
"detail": "Meni je skrit, pritisni 'Alt' za odpiranje (ali 'Escape' če uporabljaš In-App Meni)",
"message": "Skriti meni je prižgan",
"title": "Skrij meni uklopljen"
"title": "Skrij meni vklopljen"
},
"need-to-restart": {
"buttons": {
"later": "Kasneje",
"restart-now": "Ponovno zaženi zdaj"
},
"detail": "\"{{pluginName}}\" dodatek potrebuje ponovni zagon za začetek",
"detail": "\"{{pluginName}}\" dodatek potrebuje ponovni zagon",
"message": "\"{{pluginName}}\" je potrebno ponovno zagnati",
"title": "Potreben je ponovni zagon"
},
@ -62,7 +63,7 @@
"relaunch": "Ponovno zaženi",
"wait": "Počakaj"
},
"detail": "Opravičujemo se za neprijetnost! Prosim odločite se kaj narediti:",
"detail": "Opravičujemo se za nevšečnost! Prosim odločite se kaj narediti:",
"message": "Aplikacija se ne odziva",
"title": "Okno se ne odziva"
},
@ -82,7 +83,7 @@
"navigation": {
"label": "Navigacija",
"submenu": {
"copy-current-url": "Kopiraj trenuten URL",
"copy-current-url": "Kopiraj trenutni URL",
"go-back": "Nazaj",
"go-forward": "Naprej",
"quit": "Izhod",
@ -95,7 +96,7 @@
"advanced-options": {
"label": "Dodatne nastavitve",
"submenu": {
"auto-reset-app-cache": "Resetiraj predpolnilnik aplikacije ob zagonu",
"auto-reset-app-cache": "Resetiraj predpomnilnik aplikacije ob zagonu",
"disable-hardware-acceleration": "Izklopi strojno pospeševanje",
"edit-config-json": "Spremeni config.json",
"override-user-agent": "Prepiši User-Agent",
@ -103,7 +104,7 @@
"set-proxy": {
"label": "Nastavi proxy",
"prompt": {
"label": "Napiši naslov Proxy: (pusti prazno, da izklopiš)",
"label": "Napiši Proxy naslov: (pusti prazno, da izklopiš)",
"placeholder": "Primer: SOCKS5://127.0.0.1:9999",
"title": "Nastavi Proxy"
}
@ -115,7 +116,7 @@
"auto-update": "Avtomatsko posodobi",
"hide-menu": {
"dialog": {
"message": "Meni se bo skrit pri naslednjem zagonu, uporabi [Alt] da se prikaže (ali [`] v in-app-menu)",
"message": "Meni se bo skrit pri naslednjem zagonu, uporabi [Alt] da se prikaže (ali [`] v meniju aplikacije)",
"title": "Skrij meni vklopljen"
},
"label": "Skrij meni"
@ -127,12 +128,12 @@
},
"label": "Jezik",
"submenu": {
"to-help-translate": "Želiš pomagati prevediti? Klikni tukaj"
"to-help-translate": "Želiš pomagati pri prevajanju? Klikni tukaj"
}
},
"resume-on-start": "Predvajaj zadnjo pesem, ko se aplikacija prižge",
"resume-on-start": "Predvajaj zadnjo pesem, ko se aplikacija zažene",
"single-instance-lock": "Zaklep ene instance",
"start-at-login": "Prižgi pri zagonu",
"start-at-login": "Zaženi pri zagonu",
"starting-page": {
"label": "Začetna stran",
"unset": "Ni nastavljeno"
@ -153,7 +154,7 @@
"default": "Privzeto",
"force-show": "Prisilno pokaži",
"hide": "Skrij",
"label": "Gumb všeč mi je"
"label": "Gumbi za všečkanje"
},
"remove-upgrade-button": "Odstrani gumb za nadgradnjo",
"theme": {
@ -162,8 +163,8 @@
"cancel": "Prekliči",
"remove": "Odstrani"
},
"remove-theme": "Ali želite odstraniti poljubno temo?",
"remove-theme-message": "Poljubna tema bo odtranjena"
"remove-theme": "Ali želite odstraniti temo po meri?",
"remove-theme-message": "Tema po meri bo odstranjena"
},
"label": "Tema",
"submenu": {
@ -206,12 +207,16 @@
}
},
"plugins": {
"adblocker": {
"description": "Izklopi vse oglase od začetka",
"menu": {
"blocker": "Blocker"
"ad-speedup": {
"description": "Če se predvaja oglas se zvok utišja. Prav tako se hitrost predvajanja nastavi na 16 krat",
"name": "Pospeševanje oglasov"
},
"name": "Ad Blocker"
"adblocker": {
"description": "Izklopi vse oglase in sledenje",
"menu": {
"blocker": "Blokator"
},
"name": "Blokator reklam"
},
"album-actions": {
"description": "Doda Undislike, Dislike, Like, in Unlike gumbe vsem glasbam v seznamu predvajanja ali albumu",
@ -221,31 +226,31 @@
"description": "Doda dinamično temo in vizualne efekte glede na barve albuma",
"menu": {
"color-mix-ratio": {
"label": "Raznerje barv",
"label": "Razmerje barv",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Tema Brav Albuma"
"name": "Barvna tema Albuma"
},
"ambient-mode": {
"description": "Doda bravn efekt iz video posnetka na ozadje",
"description": "Doda barvni učinek iz video posnetka na ozadje",
"menu": {
"blur-amount": {
"label": "količina zameglitve",
"label": "Stopnja zameglitve",
"submenu": {
"pixels": "{{blurAmount}} pikslov"
}
},
"buffer": {
"label": "Medpolnilnik",
"label": "Medpomnilnik",
"submenu": {
"buffer": "{{buffer}}"
}
},
"opacity": {
"label": "Nepreglednost",
"label": "Prozornost",
"submenu": {
"percent": "{{opacity}}%"
}
@ -269,11 +274,54 @@
}
},
"use-fullscreen": {
"label": "Uporablja cel zaslon"
"label": "Uporablja celoten zaslon"
}
},
"name": "Ambienten način"
},
"api-server": {
"description": "Doda API strežnik za nadzor predvajalnika",
"dialog": {
"request": {
"buttons": {
"allow": "Dovoli",
"deny": "Zavrni"
},
"message": "Dovolite {{ID}} ({{origin}}) da dostopa do API-ja?",
"title": "Prošnja za avtomatizacijo API-ja"
}
},
"menu": {
"auth-strategy": {
"label": "Strategija avtorizacije",
"submenu": {
"auth-at-first": {
"label": "Avtorizacija ob prvem zahtevku"
},
"none": {
"label": "Ni avtorizacije"
}
}
},
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Port"
}
},
"name": "API strežnik [Beta]",
"prompt": {
"hostname": {
"label": "Vnesite hostname (npr. 0.0.0.0) za API strežnik:",
"title": "Hostname"
},
"port": {
"label": "Vnesite port za API strežnik:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Doda kompresijo zvoka (izenači ravni zvoka, zniža glasnost najglasnejših delov in zviša najtišje)",
"name": "Kompresija zvoka"
@ -289,7 +337,7 @@
"captions-selector": {
"description": "Izberi podnapise za YouTube Music zvočne posnetke",
"menu": {
"autoload": "Avtomatsko uporabi zanje izbrane podnapise",
"autoload": "Avtomatsko uporabi zadnje izbrane podnapise",
"disable-captions": "Avtomatsko brez podnapisov"
},
"name": "Izberi podnapise",
@ -301,7 +349,7 @@
}
},
"templates": {
"title": "Odpri izbir podnapisov"
"title": "Odpri izbiro podnapisov"
}
},
"compact-sidebar": {
@ -320,15 +368,186 @@
"fade-in-duration": "Čas zbledenja (v pesem) (ms)",
"fade-out-duration": "Čas zbledenja (izven pesemi) (ms)",
"fade-scaling": {
"label": "Fade scaling",
"label": "Zbledi skaliranje",
"linear": "Linearno",
"logarithmic": "Logaritmično"
},
"seconds-before-end": "Crossfade N seconds before end"
"seconds-before-end": "Bledenje (crossfade) N sekund pred koncem"
},
"title": "Možnosti zbledenja"
}
}
},
"disable-autoplay": {
"description": "Začne pesem v zaustavljenem načinu",
"menu": {
"apply-once": "Uporabi samo ob zagonu"
},
"name": "Onemogoči samodejno predvajanje"
},
"discord": {
"backend": {
"already-connected": "Poizkus povezave z aktivno povezavo",
"connected": "Povezan na Discord",
"disconnected": "Povezava z Discord-om prekinjena"
},
"description": "Pokaži svojim prijateljem kaj poslušaš z bogato prisotnostjo (Rich Presence)",
"menu": {
"auto-reconnect": "Samodejna unovična povezava",
"clear-activity": "Počisti dejavnost",
"clear-activity-after-timeout": "Počisti dejavnost po časovni omejitvi",
"connected": "Povezan",
"disconnected": "Prekinjena povezava",
"hide-duration-left": "Skrij preostali čas",
"hide-github-button": "Skrij povezavo do GitHub-a",
"play-on-youtube-music": "Predvajaj v YouTube Music",
"set-inactivity-timeout": "Nastavite časovno omejitev neaktivnosti"
},
"name": "Discord bogata prisotnost (Rich Presence)",
"prompt": {
"set-inactivity-timeout": {
"label": "Vnesite časovno omejitev neaktivnosti v sekundah:",
"title": "Nastavite časovno omejitev nedejavnosti"
}
}
},
"downloader": {
"backend": {
"dialog": {
"error": {
"buttons": {
"ok": "OK"
},
"message": "Uff! Se opravičujemo, prenos neuspešen…",
"title": "Napaka v prenosu!"
},
"start-download-playlist": {
"buttons": {
"ok": "OK"
},
"detail": "({{playlistSize}} pesmi)",
"message": "Prenašanje seznama {{playlistTitle}}",
"title": "Prenos se je začel"
}
},
"feedback": {
"conversion-progress": "Konverzija: {{percent}}%",
"converting": "Pretvarjanje…",
"done": "Končano: {{filePath}}",
"download-info": "Prenašanje {{artist}} - {{title}} [{{videoId}}",
"download-progress": "Prenos: {{percent}}%",
"downloading": "Prenašanje…",
"downloading-counter": "Prenašanje {{current}}/{{total}}…",
"downloading-playlist": "Prenašanje seznama \"{{playlistTitle}}\" - {{playlistSize}} pesmi ({{playlistId}})",
"error-while-downloading": "Napaka pri prenosu \"{{author}} - {{title}}\": {{error}}",
"folder-already-exists": "Ta mapa {{playlistFolder}} že obstaja",
"getting-playlist-info": "Pridobivam informacije o seznamu…",
"loading": "Nalaganje…",
"playlist-has-only-one-song": "Ta seznam ima samo eno pesem, uporabljam direkten prenos",
"playlist-id-not-found": "ID seznama ni najden",
"playlist-is-empty": "Seznam je prazen",
"playlist-is-mix-or-private": "Napaka v pridobivanju informacij o seznamu: poskrbite da seznam ni zaseben ali \"Mixed for you\" seznam\n\n{{error}}",
"preparing-file": "Pripravljanje datoteke…",
"saving": "Shranjujem…",
"trying-to-get-playlist-id": "Poizkušam pridobiti ID seznama: {{playlistId}}",
"video-id-not-found": "Videoposnetek ni najden",
"writing-id3": "Zapisujem ID3 oznake…"
}
},
"description": "Prenese MP3 / izviren zvok direktno iz vmesnika",
"menu": {
"choose-download-folder": "Izberite mapo s prenosi",
"download-finish-settings": {
"label": "Prenesi ob koncu",
"prompt": {
"last-percent": "Po x odstotkov",
"last-seconds": "Zadnjih x sekund",
"title": "Nastavite čas prenosa"
},
"submenu": {
"advanced": "Napredno",
"enabled": "Omogočen",
"mode": "Časovni način",
"percent": "Odstotek",
"seconds": "Sekunde"
}
},
"download-playlist": "Prenesi seznam",
"presets": "Prednastavitve",
"skip-existing": "Preskoči obstoječe datoteke"
},
"name": "Prenaševalec",
"renderer": {
"can-not-update-progress": "Nemorem osvežiti napredka"
},
"templates": {
"button": "Prenos"
}
},
"exponential-volume": {
"description": "Drsnik za glasnost naredi eksponenten, da bo lažje izbrati nižje glasnosti.",
"name": "Eksponentna glasnost"
},
"in-app-menu": {
"description": "Menijem doda eleganten videz v temnih barvah ali barvah albuma",
"menu": {
"hide-dom-window-controls": "Skrije DOM gumbe za okno"
},
"name": "Meni v aplikaciji"
},
"lumiastream": {
"description": "Doda podporo za Lumia pretočno predvajanje",
"name": "Lumina pretočno predavanje [Beta]"
},
"lyrics-genius": {
"description": "Doda podporo besedil za večino pesmi",
"menu": {
"romanized-lyrics": "Romanizerana besedila"
},
"name": "Besedila Genius",
"renderer": {
"fetched-lyrics": "Prestregel besedila za Genius"
}
},
"music-together": {
"description": "Delite seznam predvajanja z drugimi. Ko gostitelj predvaja skladbo, bodo vsi ostali slišali isto skladbo",
"dialog": {
"enter-host": "Vnesite Host ID"
},
"internal": {
"save": "Shrani",
"track-source": "Vir pesmi",
"unknown-user": "Neznan uporabnik"
},
"menu": {
"click-to-copy-id": "Kopiraj Host ID",
"close": "Zapri Glasba Skupaj",
"connected-users": "Povezani uporabniki",
"disconnect": "Prekini povezavo z Pesmi Skupaj",
"empty-user": "Ni povezanih uporabnikov",
"host": "Gkasba Skupaj gostitelj",
"join": "Pridruži se Glasba Skupaj",
"permission": {
"all": "Dovoli da gosti nadzorujejo seznam predvajanja in predvajalnik",
"host-only": "Samo gostitelj lahko spreminja seznam predvajanja in predvajalnik",
"playlist": "Dovoli da gostje nadzorujejo predvajalnik"
},
"set-permission": "Spremeni dovoljenje nadzora",
"status": {
"disconnected": "Odklopljen",
"guest": "Povezan kot Gost",
"host": "Povezan kot Gostitelj"
}
},
"name": "Gkasba Skupaj [Beta]",
"toast": {
"add-song-failed": "Skladba ni bila dodana",
"closed": "Glasba Skupaj zaprto",
"disconnected": "Gkasba Skupaj odklopljena",
"host-failed": "Gkasba Skupaj nisem mogel gostiti",
"id-copied": "Host ID je kopiran v odložišče",
"id-copy-failed": "Host ID ni bilo mogoče kopirati"
}
}
}
}

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "หากมีการเล่นโฆษณา เสียงจะถูกปิดและตั้งค่าความเร็วในการเล่นเป็น 16x",
"name": "เพิ่มความเร็วโฆษณา"
},
"adblocker": {
"description": "บล็อกโฆษณาและการติดตามทั้งหมดอย่างอัตโนมัติ",
"menu": {
@ -275,6 +279,18 @@
},
"name": "โหมดสภาพแวดล้อม"
},
"api-server": {
"description": "เพิ่มเซิร์ฟเวอร์ API เพื่อควบคุมการเล่น",
"dialog": {
"request": {
"buttons": {
"allow": "อนุญาต",
"deny": "ปฏิเสธ"
},
"message": "อนุญาตให้ {{ID}} ({{origin}}) เข้าถึง API หรือไม่?"
}
}
},
"audio-compressor": {
"description": "ใช้การบีบอัดเสียง (ลดระดับเสียงของส่วนที่ดังที่สุดของสัญญาณและเพิ่มระดับเสียงของส่วนที่เบาที่สุด)",
"name": "เครื่องมือบีบอัดเสียง"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Bir reklam oynatılırsa sesi kapatır ve oynatma hızını 16x olarak ayarlar",
"name": "Hızlandırma"
},
"adblocker": {
"description": "Tüm reklamları ve izleyicileri engelle",
"menu": {
@ -275,6 +279,49 @@
},
"name": "Ambiyans Modu"
},
"api-server": {
"description": "APİ ekle ve oynatıcıyı kontrol et",
"dialog": {
"request": {
"buttons": {
"allow": "İzin ver",
"deny": "Reddet"
},
"message": "{{ID}} ({{origin}}) 'nın APIye erişmesine izin verilsin mi?",
"title": "APİ yetkilendirme isteği"
}
},
"menu": {
"auth-strategy": {
"label": "Yetkilendirme stratejisi",
"submenu": {
"auth-at-first": {
"label": "İlk istekte yetkilendir"
},
"none": {
"label": "Yetkilendirme Yok"
}
}
},
"hostname": {
"label": "Ana bilgisayar adı"
},
"port": {
"label": "Port"
}
},
"name": "API sunucusu [Beta]",
"prompt": {
"hostname": {
"label": "API sunucusu için hostname (örneğin 0.0.0.0) girin:",
"title": "Hostname"
},
"port": {
"label": "API sunucusu için port girin:",
"title": "Bağlantı Noktası"
}
}
},
"audio-compressor": {
"description": "Ses sıkıştırma (dalganın en gürültülü bölümlerinin ses düzeyini azaltır ve daha yumuşak bölümlerin ses düzeyini artırır)",
"name": "Ses Sıkıştırma"
@ -664,6 +711,59 @@
"description": "Giriş/Çıkış gibi müzik olmayan kısımları veya müzik videolarında şarkının çalmadığı kısımları otomatik olarak atlar",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "LRClib gibi sağlayıcıları kullanarak şarkılara senkronize şarkı sözleri sağlar.",
"errors": {
"fetch": "⚠️ - Şarkı sözleri getirilirken bir hata oluştu. Lütfen daha sonra tekrar deneyin.",
"not-found": "⚠️ - Bu şarkı için şarkı sözü bulunamadı."
},
"menu": {
"default-text-string": {
"label": "Şarkı sözleri arasında varsayılan karakter",
"tooltip": "Şarkı sözleri arasındaki boşluk için kullanılacak varsayılan karakteri seçin"
},
"line-effect": {
"label": "Çizgi etkisi",
"submenu": {
"focus": {
"label": "odak",
"tooltip": "Yalnızca geçerli satırı beyaz yapın"
},
"offset": {
"label": "telafi etmek,ofset",
"tooltip": "Geçerli satırın sağındaki ofset"
},
"scale": {
"label": "ölçek",
"tooltip": "Geçerli satırı ölçeklendirir"
}
},
"tooltip": "Geçerli satıra uygulanacak efekti seçin"
},
"precise-timing": {
"label": "Şarkı sözlerini mükemmel şekilde senkronize edin",
"tooltip": "Bir sonraki satırın görüntülenmesini milisaniyesine kadar hesaplayın (performans üzerinde küçük bir etkisi olabilir)"
},
"show-lyrics-even-if-inexact": {
"label": "Kesin olmasa bile şarkı sözlerini gösterin",
"tooltip": "Şarkı bulunamazsa, eklenti farklı bir arama sorgusuyla tekrar dener. \nİkinci denemenin sonucu tam olmayabilir."
},
"show-time-codes": {
"label": "Zaman kodlarını göster",
"tooltip": "Şarkı sözlerinin yanında zaman kodlarını gösterin"
}
},
"name": "Senkronize Şarkı Sözleri",
"refetch-btn": {
"fetching": "Getiriliyor...",
"normal": "Refetch şarkı sözleri"
},
"warnings": {
"duration-mismatch": "⚠️ - Süre uyuşmazlığı nedeniyle şarkı sözleri senkronize olmayabilir.",
"inexact": "⚠️ - Bu şarkının sözleri tam olmayabilir",
"instrumental": "⚠️ - Bu enstrümantal bir şarkıdır"
}
},
"taskbar-mediacontrol": {
"description": "Windows görev çubuğu üzerinden oynatmayı kontrol edebilmenize olanak sağlar",
"name": "Görev Çubuğu Medya Kontrolü"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "При програванні реклами звук вимикається і встановлюється швидкість відтворення 16х",
"name": "Пришвидшення релками"
},
"adblocker": {
"description": "Блокувати всю рекламу та відстеження з коробки",
"menu": {
@ -275,6 +279,49 @@
},
"name": "Режим навколишнього середовища"
},
"api-server": {
"description": "Додає API сервер для контролю плеєра",
"dialog": {
"request": {
"buttons": {
"allow": "Дозволити",
"deny": "Відмінити"
},
"message": "Дозволити {{ID}} ({{origin}}) доступ до API?",
"title": "Запит авторизації до API"
}
},
"menu": {
"auth-strategy": {
"label": "Стратегія авторизації",
"submenu": {
"auth-at-first": {
"label": "Авторизувати при першому запиті"
},
"none": {
"label": "Немає авторизації"
}
}
},
"hostname": {
"label": "Назва серверу"
},
"port": {
"label": "Порт"
}
},
"name": "API сервер [Бета]",
"prompt": {
"hostname": {
"label": "Введіть ім'я хоста (наприклад 0.0.0.0) для API серверу:",
"title": "Ім'я хоста"
},
"port": {
"label": "Введіть порт API серверу:",
"title": "Порт"
}
}
},
"audio-compressor": {
"description": "Застосувати стиснення аудіо (зменшити гучність найгучніших фрагментів сигналу та збільшити гучність тихих фрагментів)",
"name": "Аудіокомпресор"
@ -410,6 +457,21 @@
"description": "Завантажує MP3 / джерело аудіо безпосередньо з інтерфейсу",
"menu": {
"choose-download-folder": "Оберіть папку для завантаження",
"download-finish-settings": {
"label": "Скачати по завершенню",
"prompt": {
"last-percent": "Після Х відсотків",
"last-seconds": "Останні Х секунд",
"title": "Налаштувати коли завантажувати"
},
"submenu": {
"advanced": "Розширені",
"enabled": "Увімкнено",
"mode": "Режим часу",
"percent": "Відсоток",
"seconds": "Секунди"
}
},
"download-playlist": "Завантажити плейлист",
"presets": "Попередні налаштування",
"skip-existing": "Пропустити наявні файли"
@ -649,6 +711,59 @@
"description": "Автоматично пропускати немузичні частини, такі як вступ/закінчення або частини музичних відеороликів, де не відтворюється музика",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Додає синхронізовані тексти до пісень використовуючи провайдери, такі як LRClib.",
"errors": {
"fetch": "⚠️ - При завантаженні тексту сталась помилка. Спробуйте ще раз пізніше.",
"not-found": "⚠️ - До цієї пісні текст не знайдено."
},
"menu": {
"default-text-string": {
"label": "Символ за замовчуванням між текстами пісень",
"tooltip": "Виберіть символ за замовчуванням, який буде використовуватися для проміжку між текстами пісень"
},
"line-effect": {
"label": "Лінійний ефект",
"submenu": {
"focus": {
"label": "Зосереджитись",
"tooltip": "Зробити білим лише поточний рядок"
},
"offset": {
"label": "Офсет",
"tooltip": "Офсет з права від нинішньої лінії"
},
"scale": {
"label": "Масштабувати",
"tooltip": "Масштабуваты поточну лінію"
}
},
"tooltip": "Виберіть ефект, який потрібно застосувати до поточної лінії"
},
"precise-timing": {
"label": "Зробити текст пісні ідеально синхронізованим",
"tooltip": "Обчисли до мілісекунд відображення наступного рядка (може мати невеликий вплив на продуктивність)"
},
"show-lyrics-even-if-inexact": {
"label": "Показувати текст пісні, навіть якщо він неточний",
"tooltip": "Якщо пісня не знайдена, плагін повторює спробу з іншим пошуковим запитом.\nРезультат з другої спроби може бути не точним."
},
"show-time-codes": {
"label": "Показувати часові марки",
"tooltip": "Показує часові маркы поруч із текстом пісні"
}
},
"name": "Синхронізовані тексти",
"refetch-btn": {
"fetching": "Завантаження...",
"normal": "Перезавантажити текст"
},
"warnings": {
"duration-mismatch": "⚠️ - Тексти цієї пісні можуть бути не синхронізовані через не співпадіння довжини пісні.",
"inexact": "⚠️ - Текст цієї пісні може не співпадати",
"instrumental": "⚠️ - Це інструментал"
}
},
"taskbar-mediacontrol": {
"description": "Керування відтворенням з панелі завдань Windows",
"name": "Керування медіа на панелі завдань"

134
src/i18n/resources/ur.json Normal file
View File

@ -0,0 +1,134 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "پلگ ان {{pluginName}}::{{contextName}} پر عمل کرنے میں ناکام",
"executed-at-ms": "پلگ ان {{pluginName}}::{{contextName}} کو {{ms}}ms پر عمل میں لایا گیا",
"initialize-failed": "پلگ ان \"{{pluginName}}\" کو شروع کرنے میں ناکام",
"load-all": "تمام پلگ ان لوڈ ہو رہے ہیں",
"load-failed": "\"{{pluginName}}\" پلگ ان لوڈ کرنے میں ناکام",
"loaded": "پلگ ان \"{{pluginName}}\" لوڈ ہو گیا",
"unload-failed": "پلگ ان \"{{pluginName}}\" کو لوڈ کرنے میں ناکام",
"unloaded": "پلگ ان \"{{pluginName}}\" کو لوڈ نہیں کیا گیا"
}
}
},
"language": {
"code": "ur",
"local-name": "اردو",
"name": "Urdu"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "لوڈنگ مکمل ہو گئی۔ DevTools کھل گیا"
},
"i18n": {
"loaded": "i18n لوڈ ہو گیا"
},
"second-instance": {
"receive-command": "پروٹوکول پر کمانڈ موصول ہوئی: \"{{command}}\""
},
"theme": {
"css-file-not-found": "CSS فائل \"{{cssFile}}\" موجود نہیں ہے، نظر انداز کر رہے ہیں"
},
"unresponsive": {
"details": "غیر جوابی غلطی!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "ایپ کیشے کو صاف کرنا"
},
"window": {
"tried-to-render-offscreen": "ونڈو نے آف اسکرین رینڈر کرنے کی کوشش کی، windowSize={{windowSize}}، displaySize={{displaySize}}، position={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "مینو پوشیدہ ہے، اسے دکھانے کے لیے 'Alt' استعمال کریں (یا 'Escape' اگر ایپ مینیو استعمال کر رہے ہیں)",
"message": "پوشیدہ مینو فعال ہے",
"title": "پوشیدہ مینو فعال ہو گیا"
},
"need-to-restart": {
"buttons": {
"later": "بعد میں",
"restart-now": "ابھی دوبارہ شروع کریں"
},
"detail": "\"{{pluginName}}\" پلگ ان کو اثر انداز ہونے کے لیے دوبارہ شروع کرنے کی ضرورت ہے",
"message": "\"{{pluginName}}\" کو دوبارہ شروع کرنے کی ضرورت ہے",
"title": "دوبارہ شروع کرنے کی ضرورت ہے"
},
"unresponsive": {
"buttons": {
"quit": "چھوڑو",
"relaunch": "دوبارہ لانچ کریں",
"wait": "انتظار کرو"
},
"detail": "ہم زحمت کے لیے معذرت خواہ ہیں! براہ کرم منتخب کریں کہ کیا کرنا ہے:",
"message": "پروگرام غیر ذمہ دار ہے",
"title": "ونڈو غیر جوابدہ"
},
"update-available": {
"buttons": {
"disable": "اپ ڈیٹس کو غیر فعال کریں",
"download": "ڈاؤن لوڈ کریں",
"ok": "ٹھیک ہے"
},
"detail": "ایک نیا ورژن دستیاب ہے اور اسے {{downloadLink}} پر ڈاؤن لوڈ کیا جا سکتا ہے",
"message": "ایک نیا ورژن دستیاب ہے",
"title": "اپ ڈیٹ دستیاب ہے"
}
},
"menu": {
"about": "پروگرام کے بارے میں",
"navigation": {
"label": "نیویگیشن",
"submenu": {
"copy-current-url": "موجودہ URL کاپی کریں",
"go-back": "واپس جاؤ",
"go-forward": "آگے بڑھو",
"quit": "باہر نکلیں",
"restart": "ایپ کو دوبارہ شروع کریں"
}
},
"options": {
"label": "آپشنز",
"submenu": {
"advanced-options": {
"label": "اعلی درجے کے آپشنز",
"submenu": {
"auto-reset-app-cache": "ایپ شروع ہونے پر ایپ کیشے کو دوبارہ ترتیب دیں",
"disable-hardware-acceleration": "ہارڈ ویئر ایکسلریشن کو غیر فعال کریں",
"edit-config-json": "config.json میں ترمیم کریں",
"override-user-agent": "یوزر ایجنٹ کو اوور رائیڈ کریں",
"restart-on-config-changes": "کنفیگریشن تبدیلیوں پر دوبارہ شروع کریں",
"set-proxy": {
"label": "پراکسی سیٹ کریں",
"prompt": {
"label": "پراکسی ایڈریس درج کریں: (غیر فعال کرنے کے لیے خالی چھوڑ دیں)",
"placeholder": "مثال: SOCKS5://127.0.0.1:9999",
"title": "پراکسی سیٹ کریں"
}
},
"toggle-dev-tools": "DevTools ٹوگل کریں"
}
},
"always-on-top": "ہمیشہ اوپر",
"auto-update": "خودکار اپ ڈیٹ",
"hide-menu": {
"dialog": {
"message": "اگلے لانچ پر مینو کو چھپایا جائے گا، اسے دکھانے کے لیے [Alt] استعمال کریں (یا in-app-menu استعمال کرنے پر بیک ٹک [`] کریں)",
"title": "پوشیدہ مینو کو فعال کر دیا گیا"
},
"label": "مینو کو چھپائیں"
},
"language": {
"dialog": {
"message": "دوبارہ شروع کرنے کے بعد زبان بدل دی جائے گی",
"title": "زبان بدل گئی ہے"
}
}
}
}
}
}
}

View File

@ -279,6 +279,49 @@
},
"name": "Chế độ Môi trường xung quanh"
},
"api-server": {
"description": "Thêm máy chủ API để điều khiển trình phát",
"dialog": {
"request": {
"buttons": {
"allow": "Cho phép",
"deny": "Từ chối"
},
"message": "Cho phép {{ID}} ({{origin}}) truy cập API?",
"title": "Yêu cầu cho phép API"
}
},
"menu": {
"auth-strategy": {
"label": "Chiến thuật xác thực",
"submenu": {
"auth-at-first": {
"label": "Xác thực ngay yêu cầu đầu tiên"
},
"none": {
"label": "Không/Chưa xác thực (Need context)"
}
}
},
"hostname": {
"label": "Tên máy chủ"
},
"port": {
"label": "Cổng"
}
},
"name": "Máy chủ API [Beta]",
"prompt": {
"hostname": {
"label": "Điền tên máy chủ (như 0.0.0.0) cho máy chủ API:",
"title": "Tên máy chủ"
},
"port": {
"label": "Nhập cổng cho máy chủ API:",
"title": "Cổng"
}
}
},
"audio-compressor": {
"description": "Áp dụng tính năng nén cho âm thanh (giảm âm lượng của phần to nhất của tín hiệu và tăng âm lượng của phần nhỏ nhất)",
"name": "Bộ nén âm thanh"
@ -668,6 +711,59 @@
"description": "Tự động bỏ qua các phần không phải âm nhạc như phần giới thiệu/kết thúc hoặc các phần của video nhạc mà bài hát không được phát",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "Cung cấp lời bài hát được đồng bộ hoá với các bài hát, sử dụng những nhà cung cấp như LRClib.",
"errors": {
"fetch": "⚠️ - Đã xảy ra lỗi khi tìm lời bài hát, Vui lòng thử lại sau.",
"not-found": "⚠️ - Không tìm thấy lời cho bài hát này."
},
"menu": {
"default-text-string": {
"label": "Kí tự mặc định giữa các lời bài hát",
"tooltip": "Chọn kí tự mặc định cho khoảng trống giữa các lời bài hát"
},
"line-effect": {
"label": "Kiểu đường thẳng",
"submenu": {
"focus": {
"label": "Tập trung",
"tooltip": "Chỉ làm cho dòng hiện tại có màu trắng"
},
"offset": {
"label": "Độ lệch",
"tooltip": "Độ lệch bên phải của dòng hiện tại"
},
"scale": {
"label": "Tỉ lệ",
"tooltip": "Áp dụng tỉ lệ cho dòng hiện tại"
}
},
"tooltip": "Chọn kiểu để áp dụng cho dòng hiện tại"
},
"precise-timing": {
"label": "Làm cho lời bài hát được đồng bộ hoàn hảo",
"tooltip": "Tính toán chính xác đến mili giây thời gian hiển thị dòng tiếp theo (có thể có tác động nhỏ đến hiệu suất)"
},
"show-lyrics-even-if-inexact": {
"label": "Hiển thị lời bài hát ngay cả khi không chính xác",
"tooltip": "Nếu không tìm thấy bài hát, plugin sẽ thử lại bằng truy vấn tìm kiếm khác.\nKết quả từ lần thử thứ hai có thể không chính xác."
},
"show-time-codes": {
"label": "Hiện mốc thời gian",
"tooltip": "Hiện mốc thời gian bên cạnh lời bài hát"
}
},
"name": "Lời bài hát được đồng bộ hoá",
"refetch-btn": {
"fetching": "Đang tìm nạp...",
"normal": "Tải lại lời bài hát"
},
"warnings": {
"duration-mismatch": "⚠️ - Lời bài hát có thể không đồng bộ do thời lượng không khớp.",
"inexact": "⚠️ - Lời bài hát này có thể không chính xác",
"instrumental": "⚠️ - Đây là một bài hát trình diễn bằng nhạc khí"
}
},
"taskbar-mediacontrol": {
"description": "Kiểm soát phát lại từ thanh tác vụ Windows của bạn",
"name": "Kiểm soát phương tiện trên thanh tác vụ"

View File

@ -39,7 +39,7 @@
"clearing-cache-after-20s": "正在清理应用缓存"
},
"window": {
"tried-to-render-offscreen": "窗口试图于屏幕外绘制, windowSize={{windowSize}}, displaySize={{displaySize}}, position={{position}}"
"tried-to-render-offscreen": "窗口试图于屏幕外绘制,窗口大小={{windowSize}},显示尺寸={{displaySize}},位置={{position}}"
}
},
"dialog": {
@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "使用静音以及 16 倍速播放跳过广告片段",
"name": "广告加速跳过"
},
"adblocker": {
"description": "屏蔽所有广告与跟踪器",
"menu": {
@ -275,6 +279,49 @@
},
"name": "沉浸模式"
},
"api-server": {
"description": "添加一个 API 服务器来控制播放器",
"dialog": {
"request": {
"buttons": {
"allow": "允许",
"deny": "拒绝"
},
"message": "允许 {{ID}} {{origin}} 访问该 API 吗?",
"title": "API 授权请求"
}
},
"menu": {
"auth-strategy": {
"label": "授权策略",
"submenu": {
"auth-at-first": {
"label": "首次请求时授权"
},
"none": {
"label": "无需授权"
}
}
},
"hostname": {
"label": "主机名"
},
"port": {
"label": "端口号"
}
},
"name": "API 服务器 [测试]",
"prompt": {
"hostname": {
"label": "请输入 API 服务器的主机名(如 0.0.0.0",
"title": "主机名"
},
"port": {
"label": "请输入 API 服务器的端口号:",
"title": "端口号"
}
}
},
"audio-compressor": {
"description": "对音频应用压缩(压低响亮部分,提升柔和部分)",
"name": "音频压缩器"
@ -437,6 +484,18 @@
"button": "下载"
}
},
"equalizer": {
"description": "为播放器添加均衡器",
"menu": {
"presets": {
"label": "预设",
"list": {
"bass-booster": "低音增强器"
}
}
},
"name": "均衡器"
},
"exponential-volume": {
"description": "让音量滑块指数化以便选择更低的音量。",
"name": "指数化音量"
@ -455,11 +514,11 @@
"lyrics-genius": {
"description": "为大多数歌曲添加歌词支持",
"menu": {
"romanized-lyrics": "罗马化字幕"
"romanized-lyrics": "罗马化歌词"
},
"name": "Genius 歌词",
"renderer": {
"fetched-lyrics": "已从 Genius 获取字幕"
"fetched-lyrics": "已从 Genius 获取歌词"
}
},
"music-together": {
@ -474,12 +533,12 @@
},
"menu": {
"click-to-copy-id": "复制发起者 ID",
"close": "关闭 Music Together",
"close": "关闭一起听",
"connected-users": "已连接用户",
"disconnect": "断开 Music Together 连接",
"disconnect": "断开一起听连接",
"empty-user": "没有已连接的用户",
"host": "Music Together 发起者",
"join": "加入 Music Together",
"host": "一起听发起者",
"join": "加入一起听",
"permission": {
"all": "允许来宾控制播放列表与播放器",
"host-only": "仅发起人可以控制播放列表与播放器",
@ -492,20 +551,20 @@
"host": "已作为发起人连接"
}
},
"name": "Music Together [测试]",
"name": "一起听 [测试]",
"toast": {
"add-song-failed": "添加歌曲失败",
"closed": "Music Together 已关闭",
"disconnected": "Music Together 已断开连接",
"host-failed": "发起 Music Together 失败",
"closed": "一起听已关闭",
"disconnected": "一起听已断开连接",
"host-failed": "发起一起听失败",
"id-copied": "已将发起者 ID 复制到剪切板",
"id-copy-failed": "复制发起者 ID 到剪贴板时失败",
"join-failed": "加入 Music Together 失败",
"joined": "已加入 Music Together",
"permission-changed": "Music Together 权限已改为 \"{{permission}}\"",
"join-failed": "加入一起听失败",
"joined": "已加入一起听",
"permission-changed": "一起听权限已改为 \"{{permission}}\"",
"remove-song-failed": "移除歌曲失败",
"user-connected": "{{name}} 加入了 Music Together",
"user-disconnected": "{{name}} 离开了 Music Together"
"user-connected": "{{name}} 加入了一起听",
"user-disconnected": "{{name}} 离开了一起听"
}
},
"navigation": {
@ -627,7 +686,7 @@
},
"listenbrainz": {
"token": {
"label": "输入您的v ListenBrainz 用户令牌:",
"label": "输入您的 ListenBrainz 用户令牌:",
"title": "ListenBrainz 令牌"
}
}
@ -664,6 +723,59 @@
"description": "自动跳过非音乐部分,如 MV 的介绍/结语以及歌曲未开始的部分",
"name": "SponsorBlock"
},
"synced-lyrics": {
"description": "透过 LRClib 等服务提供滚动歌词显示。",
"errors": {
"fetch": "⚠️ - 获取歌词时发生错误。请稍后再试。",
"not-found": "⚠️ - 未找到此歌曲的歌词。"
},
"menu": {
"default-text-string": {
"label": "默认的歌词行间字符",
"tooltip": "选择在歌词间隙期间默认显示的字符"
},
"line-effect": {
"label": "歌词行特效",
"submenu": {
"focus": {
"label": "高亮",
"tooltip": "仅将当前歌词行显示为白色"
},
"offset": {
"label": "偏移",
"tooltip": "将当前歌词行向右偏移"
},
"scale": {
"label": "放大",
"tooltip": "放大当前歌词行"
}
},
"tooltip": "选择当前歌词行应用的特效"
},
"precise-timing": {
"label": "让滚动歌词完全同步",
"tooltip": "以毫秒精度估算下句歌词的显示时间(可能对性能有小幅影响)"
},
"show-lyrics-even-if-inexact": {
"label": "即使时值不精确依然显示歌词",
"tooltip": "若首次搜索未找到该歌曲的歌词,插件将尝试用不同的查询方式重新获取。\n重试查询的结果可能不精确。"
},
"show-time-codes": {
"label": "显示时值",
"tooltip": "在歌词旁显示时值"
}
},
"name": "滚动歌词",
"refetch-btn": {
"fetching": "正在获取…",
"normal": "重新获取歌词"
},
"warnings": {
"duration-mismatch": "⚠️ - 由于持续时间不对应,滚动歌词可能不同步。",
"inexact": "⚠️ - 此曲目的歌词可能不准确",
"instrumental": "⚠️ - 此曲目为纯音乐"
}
},
"taskbar-mediacontrol": {
"description": "从 Windows 任务栏控制音乐回放",
"name": "任务栏媒体控件"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "使用 16 倍速播放及靜音來跳過廣告片段",
"name": "加速略過"
},
"adblocker": {
"description": "阻擋所有廣告",
"menu": {
@ -275,6 +279,56 @@
},
"name": "微光效果"
},
"amuse": {
"description": "加入支援 6K Labs 的 Amuse OBS 外掛以取得 Youtube Music 現正播放資訊",
"name": "Amuse",
"response": {
"query": "Amuse API 伺服器正在運行中,使用 /query 以取得歌曲資訊。"
}
},
"api-server": {
"description": "新增伺服器以使用 API 控制播放器",
"dialog": {
"request": {
"buttons": {
"allow": "允許",
"deny": "拒絕"
},
"message": "允許 {{ID}} ({{origin}}) 訪問 API 嗎?",
"title": "API 驗證請求"
}
},
"menu": {
"auth-strategy": {
"label": "驗證策略",
"submenu": {
"auth-at-first": {
"label": "首次請求時驗證"
},
"none": {
"label": "不要驗證"
}
}
},
"hostname": {
"label": "主機名稱"
},
"port": {
"label": "接口"
}
},
"name": "API 伺服器 [Beta]",
"prompt": {
"hostname": {
"label": "輸入 API 伺服器的主機名稱 例 (0.0.0.0)",
"title": "主機名稱"
},
"port": {
"label": "輸入 API 伺服器接口:",
"title": "接口"
}
}
},
"audio-compressor": {
"description": "使用音效壓縮 (大聲部份的音量降低, 柔和部份的音量提高)",
"name": "音效壓縮器"
@ -296,7 +350,7 @@
"name": "標題選擇器",
"prompt": {
"selector": {
"label": "目前標題語言: {{language}}",
"label": "目前標題語言{{language}}",
"none": "無",
"title": "選擇標題語言"
}
@ -341,10 +395,10 @@
"discord": {
"backend": {
"already-connected": "已嘗試可用連接",
"connected": "已連接至Discord",
"disconnected": "與Discord斷開連接"
"connected": "已連接至 Discord",
"disconnected": "與 Discord 斷開連接"
},
"description": "使用Discord狀態與你的好友分享你正在收聽的音樂",
"description": "使用 Discord 狀態與你的好友分享你正在收聽的音樂",
"menu": {
"auto-reconnect": "自動重新連接",
"clear-activity": "清除狀態",
@ -352,14 +406,14 @@
"connected": "已連接",
"disconnected": "已斷開連接",
"hide-duration-left": "隱藏音樂剩餘時間狀態",
"hide-github-button": "隱藏Github頁面按鈕",
"play-on-youtube-music": "顯示Play on YouTube Music按鈕",
"hide-github-button": "隱藏 Github 頁面按鈕",
"play-on-youtube-music": "顯示 Play on YouTube Music 按鈕",
"set-inactivity-timeout": "設定閒置狀態時長"
},
"name": "Discord狀態",
"name": "Discord 狀態",
"prompt": {
"set-inactivity-timeout": {
"label": "設定多少秒後清除狀態:",
"label": "設定多少秒後清除狀態",
"title": "設定閒置狀態時長"
}
}
@ -384,11 +438,11 @@
}
},
"feedback": {
"conversion-progress": "轉檔進度: {{percent}}%",
"conversion-progress": "轉檔進度{{percent}}%",
"converting": "轉檔中…",
"done": "完成下載: {{filePath}}",
"done": "完成下載{{filePath}}",
"download-info": "正在下載 {{artist}} - {{title}} [{{videoId}}",
"download-progress": "下載進度: {{percent}}%",
"download-progress": "下載進度{{percent}}%",
"downloading": "下載中…",
"downloading-counter": "正在下載第 {{current}}/{{total}}…",
"downloading-playlist": "正在下載播放清單 \"{{playlistTitle}}\" - 共 {{playlistSize}} 首歌 ({{playlistId}})",
@ -399,10 +453,10 @@
"playlist-has-only-one-song": "播放清單內只有一首歌曲, 將直接下載",
"playlist-id-not-found": "沒有找到播放清單 ID",
"playlist-is-empty": "播放清單是空的",
"playlist-is-mix-or-private": "獲取播放清單資訊時發生錯誤: 請確認非私人播放清單或是\"為你推薦的合輯\"\n\n{{error}}",
"playlist-is-mix-or-private": "獲取播放清單資訊時發生錯誤請確認非私人播放清單或是\"為你推薦的合輯\"\n\n{{error}}",
"preparing-file": "正在準備檔案…",
"saving": "儲存中…",
"trying-to-get-playlist-id": "正在嘗試獲取播放清單 ID: {{playlistId}}",
"trying-to-get-playlist-id": "正在嘗試獲取播放清單 ID{{playlistId}}",
"video-id-not-found": "未能找到該影片",
"writing-id3": "正在寫入 ID3 標籤…"
}
@ -437,6 +491,18 @@
"button": "下載"
}
},
"equalizer": {
"description": "為播放器加入等化器",
"menu": {
"presets": {
"label": "預設格式",
"list": {
"bass-booster": "低音增強器"
}
}
},
"name": "等化器"
},
"exponential-volume": {
"description": "使音量滑桿指數化,以便更容易選擇較低的音量。",
"name": "指數化音量調整"
@ -459,7 +525,7 @@
},
"name": "第三方字幕",
"renderer": {
"fetched-lyrics": "為Genius獲取字幕"
"fetched-lyrics": "為 Genius 獲取字幕"
}
},
"music-together": {
@ -513,8 +579,8 @@
"name": "導覽列"
},
"no-google-login": {
"description": "移除Google登入按鈕及連結",
"name": "停用Google登入"
"description": "移除 Google 登入按鈕及連結",
"name": "停用 Google 登入"
},
"notifications": {
"description": "在歌曲播放時發送一個系統通知 (可互動通知僅限Windows)",
@ -578,7 +644,7 @@
"decrease": "降低音量",
"increase": "增加音量"
},
"label": "選擇全域音量控制快捷鍵:",
"label": "選擇全域音量控制快捷鍵",
"title": "全域音量控制快捷鍵"
},
"volume-steps": {
@ -591,8 +657,8 @@
"backend": {
"dialog": {
"quality-changer": {
"detail": "目前畫質: {{quality}}",
"message": "選擇影片畫質:",
"detail": "目前畫質{{quality}}",
"message": "選擇影片畫質",
"title": "選擇影片畫質"
}
}
@ -647,7 +713,7 @@
"play-pause": "播放/暫停",
"previous": "上一首"
},
"label": "選擇全域音樂控制快捷鍵:",
"label": "選擇全域音樂控制快捷鍵",
"title": "全域快捷鍵"
}
}
@ -664,6 +730,63 @@
"description": "自動跳過贊助片段",
"name": "贊助阻擋"
},
"synced-lyrics": {
"description": "使用 LRClib 等管道提供歌詞同步顯示。",
"errors": {
"fetch": "⚠️\t擷取歌詞時發生錯誤\n請稍後再試。",
"not-found": "⚠️未找到該首歌曲的歌詞。"
},
"menu": {
"default-text-string": {
"label": "預設歌詞中間隔的符號",
"tooltip": "選擇歌詞中間隔要使用的符號"
},
"line-effect": {
"label": "歌詞顯示效果",
"submenu": {
"fancy": {
"label": "絢麗",
"tooltip": "使用較為接近原生樣式並且放大當前該行歌詞"
},
"focus": {
"label": "高亮",
"tooltip": "高亮當前的歌詞"
},
"offset": {
"label": "凸行",
"tooltip": "凸行當前的歌詞"
},
"scale": {
"label": "放大",
"tooltip": "放大當前的歌詞"
}
},
"tooltip": "選擇要使用的歌詞顯示效果"
},
"precise-timing": {
"label": "使歌詞完美同步",
"tooltip": "更精確的計算下一行歌詞的顯示(將會降低些許效能)"
},
"show-lyrics-even-if-inexact": {
"label": "即使不精確依然強制顯示歌詞",
"tooltip": "當找不到符合該歌曲的歌詞時,該功能會嘗試不同的搜尋方式。\n使用不同的搜尋方式會導致不精確的結果。"
},
"show-time-codes": {
"label": "顯示時間線",
"tooltip": "在歌詞旁顯示時間線"
}
},
"name": "歌詞同步",
"refetch-btn": {
"fetching": "擷取中...",
"normal": "重新擷取歌詞"
},
"warnings": {
"duration-mismatch": "⚠️歌詞可能會出現不同步的情況。",
"inexact": "⚠️該歌曲的歌詞可能並不精確",
"instrumental": "⚠️該首歌曲為純音樂"
}
},
"taskbar-mediacontrol": {
"description": "允許工作列應用程式預覽介面顯示媒體控制相關按鈕",
"name": "工作列媒體控制"

View File

@ -11,6 +11,8 @@ import {
shell,
dialog,
ipcMain,
protocol,
type BrowserWindowConstructorOptions,
} from 'electron';
import enhanceWebRequest, {
BetterSession,
@ -82,6 +84,34 @@ if (!gotTheLock) {
app.exit();
}
protocol.registerSchemesAsPrivileged([
{
scheme: 'http',
privileges: {
standard: true,
bypassCSP: true,
allowServiceWorkers: true,
supportFetchAPI: true,
corsEnabled: true,
stream: true,
codeCache: true,
},
},
{
scheme: 'https',
privileges: {
standard: true,
bypassCSP: true,
allowServiceWorkers: true,
supportFetchAPI: true,
corsEnabled: true,
stream: true,
codeCache: true,
},
},
{ scheme: 'mailto', privileges: { standard: true } },
]);
// Ozone platform hint: Required for Wayland support
app.commandLine.appendSwitch('ozone-platform-hint', 'auto');
// SharedArrayBuffer: Required for downloader (@ffmpeg/core-mt)
@ -101,17 +131,21 @@ if (config.get('options.disableHardwareAcceleration')) {
}
if (is.linux()) {
const disabledFeatures = [
// Overrides WM_CLASS for X11 to correspond to icon filename
app.setName('com.github.th_ch.youtube_music');
// Workaround for issue #2248
'UseMultiPlaneFormatForSoftwareVideo',
];
if (
process.env.XDG_SESSION_TYPE === 'wayland' ||
process.env.WAYLAND_DISPLAY
) {
app.commandLine.appendSwitch('disable-gpu-memory-buffer-video-frames');
}
// Stops chromium from launching its own MPRIS service
if (config.plugins.isEnabled('shortcuts')) {
disabledFeatures.push('MediaSessionService');
app.commandLine.appendSwitch('disable-features', 'MediaSessionService');
}
app.commandLine.appendSwitch('disable-features', disabledFeatures.join());
}
if (config.get('options.proxy')) {
@ -286,6 +320,23 @@ async function createMainWindow() {
height: 32,
};
const decorations: Partial<BrowserWindowConstructorOptions> = {
frame: !is.macOS() && !useInlineMenu,
titleBarOverlay: defaultTitleBarOverlayOptions,
titleBarStyle: useInlineMenu
? 'hidden'
: is.macOS()
? 'hiddenInset'
: 'default',
autoHideMenuBar: config.get('options.hideMenu'),
};
// Note: on linux, for some weird reason, having these extra properties with 'frame: false' does not work
if (is.linux() && useInlineMenu) {
delete decorations.titleBarOverlay;
delete decorations.titleBarStyle;
}
const win = new BrowserWindow({
icon,
width: windowSize.width,
@ -303,14 +354,7 @@ async function createMainWindow() {
sandbox: false,
}),
},
frame: !is.macOS() && !useInlineMenu,
titleBarOverlay: defaultTitleBarOverlayOptions,
titleBarStyle: useInlineMenu
? 'hidden'
: is.macOS()
? 'hiddenInset'
: 'default',
autoHideMenuBar: config.get('options.hideMenu'),
...decorations,
});
initHook(win);
initTheme(win);
@ -321,27 +365,31 @@ async function createMainWindow() {
const { x: windowX, y: windowY } = windowPosition;
const winSize = win.getSize();
const display = screen.getDisplayNearestPoint(windowPosition);
const primaryDisplay = screen.getPrimaryDisplay();
const scaledWidth = windowSize.width;
const scaledHeight = windowSize.height;
const scaleFactor = is.windows()
? primaryDisplay.scaleFactor / display.scaleFactor
: 1;
const scaledWidth = Math.floor(windowSize.width * scaleFactor);
const scaledHeight = Math.floor(windowSize.height * scaleFactor);
const scaledX = windowX;
const scaledY = windowY;
if (
scaledX + scaledWidth < display.bounds.x - 8 ||
scaledX - scaledWidth > display.bounds.x + display.bounds.width ||
scaledY < display.bounds.y - 8 ||
scaledY > display.bounds.y + display.bounds.height
scaledX + scaledWidth / 2 < display.bounds.x - 8 || // Left
scaledX + scaledWidth / 2 > display.bounds.x + display.bounds.width || // Right
scaledY < display.bounds.y - 8 || // Top
scaledY + scaledHeight / 2 > display.bounds.y + display.bounds.height // Bottom
) {
// Window is offscreen
if (is.dev()) {
console.warn(
LoggerPrefix,
t('main.console.window.tried-to-render-offscreen', {
winSize: String(winSize),
displaySize: String(display.bounds),
windowPosition: String(windowPosition),
windowSize: String(winSize),
displaySize: JSON.stringify(display.bounds),
position: JSON.stringify(windowPosition),
}),
);
}
@ -442,7 +490,7 @@ async function createMainWindow() {
event.preventDefault();
win.webContents.loadURL(
'https://accounts.google.com/ServiceLogin?ltmpl=music&service=youtube&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26next%3Dhttps%253A%252F%252Fmusic.youtube.com%252F'
'https://accounts.google.com/ServiceLogin?ltmpl=music&service=youtube&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26next%3Dhttps%253A%252F%252Fmusic.youtube.com%252F',
);
}
});
@ -457,10 +505,11 @@ app.once('browser-window-created', (_event, win) => {
// User agents are from https://developers.whatismybrowser.com/useragents/explore/
const originalUserAgent = win.webContents.userAgent;
const userAgents = {
mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 12.1; rv:95.0) Gecko/20100101 Firefox/95.0',
mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.152 Safari/537.36',
windows:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0',
linux: 'Mozilla/5.0 (Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.152 Safari/537.36',
linux:
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.152 Safari/537.36',
};
const updatedUserAgent = is.macOS()
@ -516,7 +565,11 @@ app.once('browser-window-created', (_event, win) => {
console.log(log);
}
if (errorCode !== -3) {
if (
errorCode !== -3 &&
// Workaround for #2435
!new URL(validatedURL).hostname.includes('doubleclick.net')
) {
// -3 is a false positive
win.webContents.send('log', log);
win.webContents.loadFile(ErrorHtmlAsset);
@ -605,6 +658,7 @@ app.whenReady().then(async () => {
shortcutDetails.target !== appLocation ||
shortcutDetails.appUserModelId !== appID
) {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw 'needUpdate';
}
} catch (error) {
@ -628,7 +682,9 @@ app.whenReady().then(async () => {
// In dev mode, get string from process.env.VITE_DEV_SERVER_URL, else use fs.readFileSync
if (is.dev() && process.env.ELECTRON_RENDERER_URL) {
// HACK: to make vite work with electron renderer (supports hot reload)
event.returnValue = [null, `
event.returnValue = [
null,
`
console.log('${LoggerPrefix}', 'Loading vite from dev server');
(async () => {
await new Promise((resolve) => {
@ -649,7 +705,8 @@ app.whenReady().then(async () => {
document.body.appendChild(rendererScript);
})();
0
`];
`,
];
} else {
const rendererPath = path.join(__dirname, '..', 'renderer');
const indexHTML = parse(
@ -661,7 +718,10 @@ app.whenReady().then(async () => {
scriptSrc.getAttribute('src')!,
);
const scriptString = fs.readFileSync(scriptPath, 'utf-8');
event.returnValue = [url.pathToFileURL(scriptPath).toString(), scriptString + ';0'];
event.returnValue = [
url.pathToFileURL(scriptPath).toString(),
scriptString + ';0',
];
}
});
@ -845,9 +905,21 @@ function removeContentSecurityPolicy(
betterSession.webRequest.onHeadersReceived((details, callback) => {
details.responseHeaders ??= {};
// prettier-ignore
if (new URL(details.url).protocol === 'https:') {
// Remove the content security policy
delete details.responseHeaders['content-security-policy-report-only'];
delete details.responseHeaders['Content-Security-Policy-Report-Only'];
delete details.responseHeaders['content-security-policy'];
delete details.responseHeaders['Content-Security-Policy'];
if (
!details.responseHeaders['access-control-allow-origin'] &&
!details.responseHeaders['Access-Control-Allow-Origin']
) {
details.responseHeaders['access-control-allow-origin'] = ['https://music.youtube.com'];
}
}
callback({ cancel: false, responseHeaders: details.responseHeaders });
});

View File

@ -34,11 +34,12 @@ const createContext = (
win.webContents.send(event, ...args);
},
handle: (event: string, listener: CallableFunction) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call
ipcMain.handle(event, (_, ...args: unknown[]) => listener(...args));
},
on: (event: string, listener: CallableFunction) => {
ipcMain.on(event, (_, ...args: unknown[]) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
listener(...args);
});
},
@ -75,11 +76,11 @@ export const forceUnloadMainPlugin = async (
);
return;
} else {
console.log(
LoggerPrefix,
t('common.console.plugins.unload-failed', { pluginName: id }),
);
return Promise.reject();
const message = t('common.console.plugins.unload-failed', {
pluginName: id,
});
console.log(LoggerPrefix, message);
return Promise.reject(new Error(message));
}
} catch (err) {
console.error(
@ -87,7 +88,7 @@ export const forceUnloadMainPlugin = async (
t('common.console.plugins.unload-failed', { pluginName: id }),
);
console.trace(err);
return Promise.reject(err);
return Promise.reject(err as Error);
}
};
@ -111,11 +112,11 @@ export const forceLoadMainPlugin = async (
) {
loadedPluginMap[id] = plugin;
} else {
console.log(
LoggerPrefix,
t('common.console.plugins.load-failed', { pluginName: id }),
);
return Promise.reject();
const message = t('common.console.plugins.load-failed', {
pluginName: id,
});
console.log(LoggerPrefix, message);
return Promise.reject(new Error(message));
}
} catch (err) {
console.error(
@ -123,7 +124,7 @@ export const forceLoadMainPlugin = async (
t('common.console.plugins.initialize-failed', { pluginName: id }),
);
console.trace(err);
return Promise.reject(err);
return Promise.reject(err as Error);
}
};

View File

@ -18,7 +18,8 @@ const loadedPluginMap: Record<
export const createContext = <Config extends PluginConfig>(
id: string,
): RendererContext<Config> => ({
getConfig: async () => window.ipcRenderer.invoke('ytmd:get-config', id),
getConfig: async () =>
window.ipcRenderer.invoke('ytmd:get-config', id) as Promise<Config>,
setConfig: async (newConfig) => {
await window.ipcRenderer.invoke('ytmd:set-config', id, newConfig);
},
@ -30,6 +31,7 @@ export const createContext = <Config extends PluginConfig>(
window.ipcRenderer.invoke(event, ...args),
on: (event: string, listener: CallableFunction) => {
window.ipcRenderer.on(event, (_, ...args: unknown[]) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
listener(...args);
});
},

View File

@ -1,5 +1,13 @@
import is from 'electron-is';
import { app, BrowserWindow, clipboard, dialog, Menu, MenuItem, shell, } from 'electron';
import {
app,
BrowserWindow,
clipboard,
dialog,
Menu,
MenuItem,
shell,
} from 'electron';
import prompt from 'custom-electron-prompt';
import { satisfies } from 'semver';
@ -68,12 +76,21 @@ export const mainMenuTemplate = async (
const plugin = allPlugins[id];
const pluginLabel = plugin?.name?.() ?? id;
const pluginDescription = plugin?.description?.() ?? undefined;
const isNew = plugin?.addedVersion ? satisfies(packageJson.version, plugin.addedVersion) : false;
const isNew = plugin?.addedVersion
? satisfies(packageJson.version, plugin.addedVersion)
: false;
if (!config.plugins.isEnabled(id)) {
return [
id,
pluginEnabledMenu(id, pluginLabel, pluginDescription, isNew, true, innerRefreshMenu),
pluginEnabledMenu(
id,
pluginLabel,
pluginDescription,
isNew,
true,
innerRefreshMenu,
),
] as const;
}
@ -115,9 +132,18 @@ export const mainMenuTemplate = async (
const plugin = allPlugins[id];
const pluginLabel = plugin?.name?.() ?? id;
const pluginDescription = plugin?.description?.() ?? undefined;
const isNew = plugin?.addedVersion ? satisfies(packageJson.version, plugin.addedVersion) : false;
const isNew = plugin?.addedVersion
? satisfies(packageJson.version, plugin.addedVersion)
: false;
return pluginEnabledMenu(id, pluginLabel, pluginDescription, isNew, true, innerRefreshMenu);
return pluginEnabledMenu(
id,
pluginLabel,
pluginDescription,
isNew,
true,
innerRefreshMenu,
);
});
const availableLanguages = Object.keys(languageResources);
@ -233,7 +259,7 @@ export const mainMenuTemplate = async (
label: t(
'main.menu.options.submenu.visual-tweaks.submenu.theme.submenu.no-theme',
),
}
},
]
: []),
...(config.get('options.themes')?.map((theme: string) => ({
@ -251,16 +277,25 @@ export const mainMenuTemplate = async (
{ theme },
),
buttons: [
t('main.menu.options.submenu.visual-tweaks.submenu.theme.dialog.button.cancel'),
t('main.menu.options.submenu.visual-tweaks.submenu.theme.dialog.button.remove'),
t(
'main.menu.options.submenu.visual-tweaks.submenu.theme.dialog.button.cancel',
),
t(
'main.menu.options.submenu.visual-tweaks.submenu.theme.dialog.button.remove',
),
],
});
if (response === 1) {
config.set('options.themes', config.get('options.themes')?.filter((t) => t !== theme) ?? []);
config.set(
'options.themes',
config
.get('options.themes')
?.filter((t) => t !== theme) ?? [],
);
innerRefreshMenu();
}
}
},
})) ?? []),
{ type: 'separator' },
{

View File

@ -1,5 +1,7 @@
function skipAd(target: Element) {
const skipButton = target.querySelector<HTMLButtonElement>('button.ytp-ad-skip-button-modern');
const skipButton = target.querySelector<HTMLButtonElement>(
'button.ytp-ad-skip-button-modern',
);
if (skipButton) {
skipButton.click();
}
@ -17,7 +19,7 @@ function speedUpAndMute(player: Element, isAdShowing: boolean) {
}
}
export const loadAdSpeedup = async () => {
export const loadAdSpeedup = () => {
const player = document.querySelector<HTMLVideoElement>('#movie_player');
if (!player) return;
@ -53,4 +55,4 @@ export const loadAdSpeedup = async () => {
player.classList.contains('ad-interrupting');
speedUpAndMute(player, isAdShowing);
skipAd(player);
}
};

View File

@ -2,7 +2,7 @@
import path from 'node:path';
import fs, { promises } from 'node:fs';
import { ElectronBlocker } from '@cliqz/adblocker-electron';
import { ElectronBlocker } from '@ghostery/adblocker-electron';
import { app, net } from 'electron';
const SOURCES = [
@ -55,6 +55,7 @@ export const loadAdBlockerEngine = async (
(url: string) => net.fetch(url),
lists,
{
enableCompression: true,
// When generating the engine for caching, do not load network filters
// So that enhancing the session works as expected
// Allowing to define multiple webRequest listeners
@ -66,7 +67,7 @@ export const loadAdBlockerEngine = async (
blocker.enableBlockingInSession(session);
}
} catch (error) {
console.log('Error loading adBlocker engine', error);
console.error('Error loading adBlocker engine', error);
}
};

View File

@ -8,13 +8,12 @@ import {
unloadAdBlockerEngine,
} from './blocker';
import injectCliqzPreload from './injectors/inject-cliqz-preload';
import { inject, isInjected } from './injectors/inject';
import { loadAdSpeedup } from './adSpeedup';
import { t } from '@/i18n';
import type { BrowserWindow } from 'electron';
import { loadAdSpeedup } from './adSpeedup';
interface AdblockerConfig {
/**
@ -74,12 +73,12 @@ export default createPlugin({
];
},
renderer: {
async onPlayerApiReady(_, {getConfig}) {
async onPlayerApiReady(_, { getConfig }) {
const config = await getConfig();
if (config.blocker === blockers.AdSpeedup) {
await loadAdSpeedup();
}
}
},
},
backend: {
mainWindow: null as BrowserWindow | null,
@ -118,22 +117,29 @@ export default createPlugin({
},
},
preload: {
script: 'window.JSON.parse = window._proxyJsonParse; window._proxyJsonParse = undefined; window.Response.prototype.json = window._proxyResponseJson; window._proxyResponseJson = undefined; 0',
// see #1478
script: `const _prunerFn = window._pruner;
window._pruner = undefined;
JSON.parse = new Proxy(JSON.parse, {
apply() {
return _prunerFn(Reflect.apply(...arguments));
},
});
Response.prototype.json = new Proxy(Response.prototype.json, {
apply() {
return Reflect.apply(...arguments).then((o) => _prunerFn(o));
},
}); 0`,
async start({ getConfig }) {
const config = await getConfig();
if (config.blocker === blockers.WithBlocklists) {
// Preload adblocker to inject scripts/styles
await injectCliqzPreload();
} else if (config.blocker === blockers.InPlayer && !isInjected()) {
if (config.blocker === blockers.InPlayer && !isInjected()) {
inject(contextBridge);
await webFrame.executeJavaScript(this.script);
}
},
async onConfigChange(newConfig) {
if (newConfig.blocker === blockers.WithBlocklists) {
await injectCliqzPreload();
} else if (newConfig.blocker === blockers.InPlayer && !isInjected()) {
if (newConfig.blocker === blockers.InPlayer && !isInjected()) {
inject(contextBridge);
await webFrame.executeJavaScript(this.script);
}

View File

@ -1,3 +1,3 @@
export default async () => {
await import('@cliqz/adblocker-electron-preload');
await import('@ghostery/adblocker-electron-preload');
};

View File

@ -37,19 +37,9 @@ export const inject = (contextBridge) => {
//
return o;
};
}
contextBridge.exposeInMainWorld('_proxyJsonParse', new Proxy(JSON.parse, {
apply() {
return pruner(Reflect.apply(...arguments));
},
}));
contextBridge.exposeInMainWorld('_proxyResponseJson', new Proxy(Response.prototype.json, {
apply() {
return Reflect.apply(...arguments).then((o) => pruner(o));
},
}));
contextBridge.exposeInMainWorld('_pruner', pruner);
}
const chains = [

View File

@ -1,6 +1,7 @@
import { t } from '@/i18n';
import { createPlugin } from '@/utils';
import { ElementFromHtml } from '@/plugins/utils/renderer';
import { waitForElement } from '@/utils/wait-for-element';
import undislikeHTML from './templates/undislike.html?raw';
import dislikeHTML from './templates/dislike.html?raw';
@ -16,7 +17,6 @@ export default createPlugin<
changeObserver?: MutationObserver;
waiting: boolean;
onPageChange(): void;
waitForElem(selector: string): Promise<HTMLElement>;
loadFullList: (event: MouseEvent) => void;
applyToList(id: string, loader: HTMLElement): void;
start(): void;
@ -50,7 +50,7 @@ export default createPlugin<
} else {
this.waiting = true;
}
const continuations = await this.waitForElem('#continuations');
const continuations = await waitForElement<HTMLElement>('#continuations');
this.waiting = false;
//Gets the for buttons
const buttons: Array<HTMLElement> = [
@ -104,21 +104,28 @@ export default createPlugin<
buttons.splice(i, 1);
i--;
} else {
(buttons[i].children[0].children[0] as HTMLElement).style.setProperty(
(
buttons[i].children[0].children[0] as HTMLElement
).style.setProperty(
'-webkit-mask-size',
`100% ${100 - ((count / listsLength) * 100)}%`,
`100% ${100 - (count / listsLength) * 100}%`,
);
}
i++;
}
}
const menuParent = document.querySelector('#action-buttons')?.parentElement;
const menuParent =
document.querySelector('#action-buttons')?.parentElement;
if (menuParent && !document.querySelector('.like-menu')) {
const menu = document.createElement('div');
menu.id = 'ytmd-album-action-buttons';
menu.className = 'action-buttons style-scope ytmusic-responsive-header-renderer';
menu.className =
'action-buttons style-scope ytmusic-responsive-header-renderer';
menuParent.insertBefore(menu, menuParent.children[menuParent.children.length - 1]);
menuParent.insertBefore(
menu,
menuParent.children[menuParent.children.length - 1],
);
for (const button of buttons) {
menu.appendChild(button);
button.addEventListener('click', this.loadFullList);
@ -126,9 +133,11 @@ export default createPlugin<
}
},
loadFullList(event: MouseEvent) {
if (event.currentTarget instanceof Element) {
if (event.target instanceof Element) {
event.stopPropagation();
const id = event.currentTarget.id;
const button = event.target.closest('button') as HTMLElement;
if (!button?.id) return;
const id = button.id;
const loader = document.getElementById('continuations')!;
this.loadObserver = new MutationObserver(() => {
this.applyToList(id, loader);
@ -183,16 +192,5 @@ export default createPlugin<
button.remove();
}
},
waitForElem(selector: string) {
return new Promise((resolve) => {
const interval = setInterval(() => {
const elem = document.querySelector<HTMLElement>(selector);
if (!elem) return;
clearInterval(interval);
resolve(elem);
});
});
},
},
});

View File

@ -25,7 +25,12 @@ export default createPlugin<
sidebarSmall: HTMLElement | null;
ytmusicAppLayout: HTMLElement | null;
getMixedColor(color: string, key: string, alpha?: number, ratioMultiply?: number): string;
getMixedColor(
color: string,
key: string,
alpha?: number,
ratioMultiply?: number,
): string;
updateColor(): void;
},
{
@ -91,7 +96,10 @@ export default createPlugin<
this.ytmusicAppLayout = document.querySelector<HTMLElement>('#layout');
const config = await getConfig();
document.documentElement.style.setProperty(RATIO_KEY, `${~~(config.ratio * 100)}%`);
document.documentElement.style.setProperty(
RATIO_KEY,
`${~~(config.ratio * 100)}%`,
);
},
onPlayerApiReady(playerApi) {
const fastAverageColor = new FastAverageColor();
@ -100,10 +108,12 @@ export default createPlugin<
if (event.detail.name !== 'dataloaded') return;
const playerResponse = playerApi.getPlayerResponse();
const thumbnail = playerResponse?.videoDetails?.thumbnail?.thumbnails?.at(0);
const thumbnail =
playerResponse?.videoDetails?.thumbnail?.thumbnails?.at(0);
if (!thumbnail) return;
const albumColor = await fastAverageColor.getColorAsync(thumbnail.url)
const albumColor = await fastAverageColor
.getColorAsync(thumbnail.url)
.catch((err) => {
console.error(err);
return null;
@ -120,8 +130,14 @@ export default createPlugin<
this.darkColor = this.darkColor?.darken(0.05);
}
document.documentElement.style.setProperty(COLOR_KEY, `${~~this.color.red()}, ${~~this.color.green()}, ${~~this.color.blue()}`);
document.documentElement.style.setProperty(DARK_COLOR_KEY, `${~~this.darkColor.red()}, ${~~this.darkColor.green()}, ${~~this.darkColor.blue()}`);
document.documentElement.style.setProperty(
COLOR_KEY,
`${~~this.color.red()}, ${~~this.color.green()}, ${~~this.color.blue()}`,
);
document.documentElement.style.setProperty(
DARK_COLOR_KEY,
`${~~this.darkColor.red()}, ${~~this.darkColor.green()}, ${~~this.darkColor.blue()}`,
);
} else {
document.documentElement.style.setProperty(COLOR_KEY, '0, 0, 0');
document.documentElement.style.setProperty(DARK_COLOR_KEY, '0, 0, 0');
@ -131,7 +147,10 @@ export default createPlugin<
});
},
onConfigChange(config) {
document.documentElement.style.setProperty(RATIO_KEY, `${~~(config.ratio * 100)}%`);
document.documentElement.style.setProperty(
RATIO_KEY,
`${~~(config.ratio * 100)}%`,
);
},
getMixedColor(color: string, key: string, alpha = 1, ratioMultiply) {
const keyColor = `rgba(var(${key}), ${alpha})`;
@ -181,11 +200,23 @@ export default createPlugin<
'--yt-spec-black-1-alpha-95': 'rgba(40,40,40,0.95)',
};
Object.entries(variableMap).map(([variable, color]) => {
document.documentElement.style.setProperty(variable, this.getMixedColor(color, COLOR_KEY), 'important');
document.documentElement.style.setProperty(
variable,
this.getMixedColor(color, COLOR_KEY),
'important',
);
});
document.body.style.setProperty('background', this.getMixedColor('#030303', COLOR_KEY), 'important');
document.documentElement.style.setProperty('--ytmusic-background', this.getMixedColor('#030303', DARK_COLOR_KEY), 'important');
document.body.style.setProperty(
'background',
this.getMixedColor('#030303', COLOR_KEY),
'important',
);
document.documentElement.style.setProperty(
'--ytmusic-background',
this.getMixedColor('#030303', DARK_COLOR_KEY),
'important',
);
},
},
});

View File

@ -4,6 +4,7 @@ import { t } from '@/i18n';
import { createPlugin } from '@/utils';
import { menu } from './menu';
import { AmbientModePluginConfig } from './types';
import { waitForElement } from '@/utils/wait-for-element';
const defaultConfig: AmbientModePluginConfig = {
enabled: false,
@ -36,7 +37,7 @@ export default createPlugin({
unregister: null as (() => void) | null,
update: null as (() => void) | null,
interval: null as NodeJS.Timeout | null,
lastMediaType: null as "video" | "image" | null,
lastMediaType: null as 'video' | 'image' | null,
lastVideoSource: null as string | null,
lastImageSource: null as string | null,
@ -52,9 +53,16 @@ export default createPlugin({
const songImage = document.querySelector<HTMLImageElement>('#song-image');
const songVideo = document.querySelector<HTMLDivElement>('#song-video');
const image = songImage?.querySelector<HTMLImageElement>('yt-img-shadow > img');
const video = songVideo?.querySelector<HTMLVideoElement>('.html5-video-container > video');
const videoWrapper = document.querySelector('#song-video > .player-wrapper');
const image = songImage?.querySelector<HTMLImageElement>(
'yt-img-shadow > img',
);
const video = await waitForElement<HTMLVideoElement>(
'.html5-video-container > video',
);
const videoWrapper = document.querySelector(
'#song-video > .player-wrapper',
);
const injectBlurImage = () => {
if (!songImage || !image) return null;
@ -93,7 +101,9 @@ export default createPlugin({
const blurCanvas = document.createElement('canvas');
blurCanvas.classList.add('html5-blur-canvas');
const context = blurCanvas.getContext('2d', { willReadFrequently: true });
const context = blurCanvas.getContext('2d', {
willReadFrequently: true,
});
/* effect */
let lastEffectWorkId: number | null = null;
@ -107,14 +117,18 @@ export default createPlugin({
if (!context) return;
const width = this.qualityRatio;
let height = Math.max(Math.floor((blurCanvas.height / blurCanvas.width) * width), 1,);
let height = Math.max(
Math.floor((blurCanvas.height / blurCanvas.width) * width),
1,
);
if (!Number.isFinite(height)) height = width;
if (!height) return;
context.globalAlpha = 1;
if (lastImageData) {
const frameOffset = (1 / this.buffer) * (1000 / this.interpolationTime);
context.globalAlpha = 1 - (frameOffset * 2); // because of alpha value must be < 1
const frameOffset =
(1 / this.buffer) * (1000 / this.interpolationTime);
context.globalAlpha = 1 - frameOffset * 2; // because of alpha value must be < 1
context.putImageData(lastImageData, 0, 0);
context.globalAlpha = frameOffset;
}
@ -135,7 +149,9 @@ export default createPlugin({
if (newWidth === 0 || newHeight === 0) return;
blurCanvas.width = this.qualityRatio;
blurCanvas.height = Math.floor((newHeight / newWidth) * this.qualityRatio);
blurCanvas.height = Math.floor(
(newHeight / newWidth) * this.qualityRatio,
);
if (this.isFullscreen) blurCanvas.classList.add('fullscreen');
else blurCanvas.classList.remove('fullscreen');
@ -149,7 +165,10 @@ export default createPlugin({
/* hooking */
let canvasInterval: NodeJS.Timeout | null = null;
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / this.buffer)));
canvasInterval = setInterval(
onSync,
Math.max(1, Math.ceil(1000 / this.buffer)),
);
const onPause = () => {
if (canvasInterval) clearInterval(canvasInterval);
@ -157,7 +176,10 @@ export default createPlugin({
};
const onPlay = () => {
if (canvasInterval) clearInterval(canvasInterval);
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / this.buffer)));
canvasInterval = setInterval(
onSync,
Math.max(1, Math.ceil(1000 / this.buffer)),
);
};
songVideo.addEventListener('pause', onPause);
songVideo.addEventListener('play', onPlay);
@ -179,12 +201,12 @@ export default createPlugin({
const isVideoMode = () => {
const songVideo = document.querySelector<HTMLDivElement>('#song-video');
if (!songVideo) {
this.lastMediaType = "image";
this.lastMediaType = 'image';
return false;
}
const isVideo = getComputedStyle(songVideo).display !== 'none';
this.lastMediaType = isVideo ? "video" : "image";
this.lastMediaType = isVideo ? 'video' : 'image';
return isVideo;
};
@ -196,16 +218,25 @@ export default createPlugin({
if (isPageOpen) {
const isVideo = isVideoMode();
if (!force) {
if (this.lastMediaType === "video" && this.lastVideoSource === video?.src) return false;
if (this.lastMediaType === "image" && this.lastImageSource === image?.src) return false;
if (
this.lastMediaType === 'video' &&
this.lastVideoSource === video?.src
)
return false;
if (
this.lastMediaType === 'image' &&
this.lastImageSource === image?.src
)
return false;
}
this.unregister?.();
this.unregister = (isVideo ? injectBlurVideo() : injectBlurImage()) ?? null;
this.unregister =
(isVideo ? injectBlurVideo() : injectBlurImage()) ?? null;
} else {
this.unregister?.();
this.unregister = null;
}
}
};
/* needed for switching between different views (e.g. miniplayer) */
const observer = new MutationObserver((mutationsList) => {

View File

@ -1,14 +1,24 @@
import { t } from "@/i18n";
import { MenuContext } from "@/types/contexts";
import { MenuItemConstructorOptions } from "electron";
import { AmbientModePluginConfig } from "./types";
import { MenuItemConstructorOptions } from 'electron';
import { t } from '@/i18n';
import { MenuContext } from '@/types/contexts';
import { AmbientModePluginConfig } from './types';
export interface menuParameters {
getConfig: () => AmbientModePluginConfig | Promise<AmbientModePluginConfig>;
setConfig: (conf: Partial<Omit<AmbientModePluginConfig, "enabled">>) => void | Promise<void>;
setConfig: (
conf: Partial<Omit<AmbientModePluginConfig, 'enabled'>>,
) => void | Promise<void>;
}
export const menu: (ctx: MenuContext<AmbientModePluginConfig>) => MenuItemConstructorOptions[] | Promise<MenuItemConstructorOptions[]> = async ({ getConfig, setConfig }: menuParameters) => {
export const menu: (
ctx: MenuContext<AmbientModePluginConfig>,
) =>
| MenuItemConstructorOptions[]
| Promise<MenuItemConstructorOptions[]> = async ({
getConfig,
setConfig,
}: menuParameters) => {
const interpolationTimeList = [0, 500, 1000, 1500, 2000, 3000, 4000, 5000];
const qualityList = [10, 25, 50, 100, 200, 500, 1000];
const sizeList = [100, 110, 125, 150, 175, 200, 300];
@ -107,4 +117,4 @@ export const menu: (ctx: MenuContext<AmbientModePluginConfig>) => MenuItemConstr
},
},
];
}
};

View File

@ -34,3 +34,12 @@
margin: 0 auto !important;
overflow: visible;
}
/* Fix ambient mode overlapping other elements #2520 */
.song-button.ytmusic-av-toggle, .video-button.ytmusic-av-toggle {
z-index: 1;
background-color: transparent;
}
#side-panel.side-panel.ytmusic-player-page {
z-index: 0;
}

View File

@ -0,0 +1,71 @@
import { t } from 'i18next';
import { type Context, Hono } from 'hono';
import { cors } from 'hono/cors';
import { serve } from '@hono/node-server';
import registerCallback, { type SongInfo } from '@/providers/song-info';
import { createBackend } from '@/utils';
import type { AmuseSongInfo } from './types';
const amusePort = 9863;
const formatSongInfo = (info: SongInfo) => {
const formattedSongInfo: AmuseSongInfo = {
player: {
hasSong: !!(info.artist && info.title),
isPaused: info.isPaused ?? false,
seekbarCurrentPosition: info.elapsedSeconds ?? 0,
},
track: {
duration: info.songDuration,
title: info.title,
author: info.artist,
cover: info.imageSrc ?? '',
url: info.url ?? '',
id: info.videoId,
isAdvertisement: false,
},
};
return formattedSongInfo;
};
export default createBackend({
currentSongInfo: {} as SongInfo,
app: null as Hono | null,
server: null as ReturnType<typeof serve> | null,
start() {
registerCallback((songInfo) => {
this.currentSongInfo = songInfo;
});
this.app = new Hono();
this.app.use('*', cors());
this.app.get('/', (ctx) =>
ctx.body(t('plugins.amuse.response.query'), 200),
);
const queryAndApiHandler = (ctx: Context) => {
return ctx.json(formatSongInfo(this.currentSongInfo), 200);
};
this.app.get('/query', queryAndApiHandler);
this.app.get('/api', queryAndApiHandler);
try {
this.server = serve({
fetch: this.app.fetch.bind(this.app),
port: amusePort,
});
} catch (err) {
console.error(err);
}
},
stop() {
if (this.server) {
this.server?.close();
}
},
});

View File

@ -0,0 +1,20 @@
import { createPlugin } from '@/utils';
import backend from './backend';
import { t } from '@/i18n';
export interface MusicWidgetConfig {
enabled: boolean;
}
export const defaultConfig: MusicWidgetConfig = {
enabled: false,
};
export default createPlugin({
name: () => t('plugins.amuse.name'),
description: () => t('plugins.amuse.description'),
addedVersion: '3.7.X',
restartNeeded: true,
config: defaultConfig,
backend,
});

View File

@ -0,0 +1,20 @@
export interface PlayerInfo {
hasSong: boolean;
isPaused: boolean;
seekbarCurrentPosition: number;
}
export interface TrackInfo {
author: string;
title: string;
cover: string;
duration: number;
url: string;
id: string;
isAdvertisement: boolean;
}
export interface AmuseSongInfo {
player: PlayerInfo;
track: TrackInfo;
}

View File

@ -0,0 +1 @@
export * from './main';

View File

@ -0,0 +1,143 @@
import { jwt } from 'hono/jwt';
import { OpenAPIHono as Hono } from '@hono/zod-openapi';
import { cors } from 'hono/cors';
import { swaggerUI } from '@hono/swagger-ui';
import { serve } from '@hono/node-server';
import registerCallback from '@/providers/song-info';
import { createBackend } from '@/utils';
import { JWTPayloadSchema } from './scheme';
import { registerAuth, registerControl } from './routes';
import { type APIServerConfig, AuthStrategy } from '../config';
import type { BackendType } from './types';
import type { RepeatMode } from '@/types/datahost-get-state';
export const backend = createBackend<BackendType, APIServerConfig>({
async start(ctx) {
const config = await ctx.getConfig();
await this.init(ctx);
registerCallback((songInfo) => {
this.songInfo = songInfo;
});
ctx.ipc.on('ytmd:player-api-loaded', () => {
ctx.ipc.send('ytmd:setup-time-changed-listener');
ctx.ipc.send('ytmd:setup-repeat-changed-listener');
});
ctx.ipc.on(
'ytmd:repeat-changed',
(mode: RepeatMode) => (this.currentRepeatMode = mode),
);
this.run(config.hostname, config.port);
},
stop() {
this.end();
},
onConfigChange(config) {
if (
this.oldConfig?.hostname === config.hostname &&
this.oldConfig?.port === config.port
) {
this.oldConfig = config;
return;
}
this.end();
this.run(config.hostname, config.port);
this.oldConfig = config;
},
// Custom
async init(ctx) {
const config = await ctx.getConfig();
this.app = new Hono();
this.app.use('*', cors());
// for web remote control
this.app.use('*', async (ctx, next) => {
ctx.header('Access-Control-Request-Private-Network', 'true');
await next();
});
// middlewares
this.app.use('/api/*', async (ctx, next) => {
if (config.authStrategy !== AuthStrategy.NONE) {
return await jwt({
secret: config.secret,
})(ctx, next);
}
await next();
});
this.app.use('/api/*', async (ctx, next) => {
const result = await JWTPayloadSchema.spa(await ctx.get('jwtPayload'));
const isAuthorized =
config.authStrategy === AuthStrategy.NONE ||
(result.success && config.authorizedClients.includes(result.data.id));
if (!isAuthorized) {
ctx.status(401);
return ctx.body('Unauthorized');
}
return await next();
});
// routes
registerControl(
this.app,
ctx,
() => this.songInfo,
() => this.currentRepeatMode,
);
registerAuth(this.app, ctx);
// swagger
this.app.openAPIRegistry.registerComponent(
'securitySchemes',
'bearerAuth',
{
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
);
this.app.doc('/doc', {
openapi: '3.1.0',
info: {
version: '1.0.0',
title: 'Youtube Music API Server',
},
security: [
{
bearerAuth: [],
},
],
});
this.app.get('/swagger', swaggerUI({ url: '/doc' }));
},
run(hostname, port) {
if (!this.app) return;
try {
this.server = serve({
fetch: this.app.fetch.bind(this.app),
port,
hostname,
});
} catch (err) {
console.error(err);
}
},
end() {
this.server?.close();
this.server = undefined;
},
});

View File

@ -0,0 +1,95 @@
import { createRoute, z } from '@hono/zod-openapi';
import { dialog } from 'electron';
import { sign } from 'hono/jwt';
import { getConnInfo } from '@hono/node-server/conninfo';
import { t } from '@/i18n';
import { type APIServerConfig, AuthStrategy } from '../../config';
import type { JWTPayload } from '../scheme';
import type { HonoApp } from '../types';
import type { BackendContext } from '@/types/contexts';
const routes = {
request: createRoute({
method: 'post',
path: '/auth/{id}',
summary: '',
description: '',
security: [],
request: {
params: z.object({
id: z.string(),
}),
},
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({
accessToken: z.string(),
}),
},
},
},
403: {
description: 'Forbidden',
},
},
}),
};
export const register = (
app: HonoApp,
{ getConfig, setConfig }: BackendContext<APIServerConfig>,
) => {
app.openapi(routes.request, async (ctx) => {
const config = await getConfig();
const { id } = ctx.req.param();
if (config.authorizedClients.includes(id)) {
// SKIP CHECK
} else if (config.authStrategy === AuthStrategy.AUTH_AT_FIRST) {
const result = await dialog.showMessageBox({
title: t('plugins.api-server.dialog.request.title'),
message: t('plugins.api-server.dialog.request.message', {
origin: getConnInfo(ctx).remote.address,
ID: id,
}),
buttons: [
t('plugins.api-server.dialog.request.buttons.allow'),
t('plugins.api-server.dialog.request.buttons.deny'),
],
defaultId: 1,
cancelId: 1,
});
if (result.response === 1) {
ctx.status(403);
return ctx.body(null);
}
} else if (config.authStrategy === AuthStrategy.NONE) {
// SKIP CHECK
}
setConfig({
authorizedClients: [...config.authorizedClients, id],
});
const token = await sign(
{
id,
iat: ~~(Date.now() / 1000),
} satisfies JWTPayload,
config.secret,
);
ctx.status(200);
return ctx.json({
accessToken: token,
});
});
};

View File

@ -0,0 +1,704 @@
import { createRoute, z } from '@hono/zod-openapi';
import { ipcMain } from 'electron';
import getSongControls from '@/providers/song-controls';
import {
AddSongToQueueSchema,
GoBackSchema,
GoForwardScheme,
MoveSongInQueueSchema,
QueueParamsSchema,
SearchSchema,
SeekSchema,
SetFullscreenSchema,
SetQueueIndexSchema,
SetVolumeSchema,
SongInfoSchema,
SwitchRepeatSchema,
type ResponseSongInfo,
} from '../scheme';
import type { RepeatMode } from '@/types/datahost-get-state';
import type { SongInfo } from '@/providers/song-info';
import type { BackendContext } from '@/types/contexts';
import type { APIServerConfig } from '../../config';
import type { HonoApp } from '../types';
import type { QueueResponse } from '@/types/youtube-music-desktop-internal';
import type { Context } from 'hono';
const API_VERSION = 'v1';
const routes = {
previous: createRoute({
method: 'post',
path: `/api/${API_VERSION}/previous`,
summary: 'play previous song',
description: 'Plays the previous song in the queue',
responses: {
204: {
description: 'Success',
},
},
}),
next: createRoute({
method: 'post',
path: `/api/${API_VERSION}/next`,
summary: 'play next song',
description: 'Plays the next song in the queue',
responses: {
204: {
description: 'Success',
},
},
}),
play: createRoute({
method: 'post',
path: `/api/${API_VERSION}/play`,
summary: 'Play',
description: 'Change the state of the player to play',
responses: {
204: {
description: 'Success',
},
},
}),
pause: createRoute({
method: 'post',
path: `/api/${API_VERSION}/pause`,
summary: 'Pause',
description: 'Change the state of the player to pause',
responses: {
204: {
description: 'Success',
},
},
}),
togglePlay: createRoute({
method: 'post',
path: `/api/${API_VERSION}/toggle-play`,
summary: 'Toggle play/pause',
description:
'Change the state of the player to play if paused, or pause if playing',
responses: {
204: {
description: 'Success',
},
},
}),
like: createRoute({
method: 'post',
path: `/api/${API_VERSION}/like`,
summary: 'like song',
description: 'Set the current song as liked',
responses: {
204: {
description: 'Success',
},
},
}),
dislike: createRoute({
method: 'post',
path: `/api/${API_VERSION}/dislike`,
summary: 'dislike song',
description: 'Set the current song as disliked',
responses: {
204: {
description: 'Success',
},
},
}),
seekTo: createRoute({
method: 'post',
path: `/api/${API_VERSION}/seek-to`,
summary: 'seek',
description: 'Seek to a specific time in the current song',
request: {
body: {
description: 'seconds to seek to',
content: {
'application/json': {
schema: SeekSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
goBack: createRoute({
method: 'post',
path: `/api/${API_VERSION}/go-back`,
summary: 'go back',
description: 'Move the current song back by a number of seconds',
request: {
body: {
description: 'seconds to go back',
content: {
'application/json': {
schema: GoBackSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
goForward: createRoute({
method: 'post',
path: `/api/${API_VERSION}/go-forward`,
summary: 'go forward',
description: 'Move the current song forward by a number of seconds',
request: {
body: {
description: 'seconds to go forward',
content: {
'application/json': {
schema: GoForwardScheme,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
shuffle: createRoute({
method: 'post',
path: `/api/${API_VERSION}/shuffle`,
summary: 'shuffle',
description: 'Shuffle the queue',
responses: {
204: {
description: 'Success',
},
},
}),
repeatMode: createRoute({
method: 'get',
path: `/api/${API_VERSION}/repeat-mode`,
summary: 'get current repeat mode',
description: 'Get the current repeat mode (NONE, ALL, ONE)',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({
mode: z.enum(['ONE', 'NONE', 'ALL']).nullable(),
}),
},
},
},
},
}),
switchRepeat: createRoute({
method: 'post',
path: `/api/${API_VERSION}/switch-repeat`,
summary: 'switch repeat',
description: 'Switch the repeat mode',
request: {
body: {
description: 'number of times to click the repeat button',
content: {
'application/json': {
schema: SwitchRepeatSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
setVolume: createRoute({
method: 'post',
path: `/api/${API_VERSION}/volume`,
summary: 'set volume',
description: 'Set the volume of the player',
request: {
body: {
description: 'volume to set',
content: {
'application/json': {
schema: SetVolumeSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
setFullscreen: createRoute({
method: 'post',
path: `/api/${API_VERSION}/fullscreen`,
summary: 'set fullscreen',
description: 'Set the fullscreen state of the player',
request: {
body: {
description: 'fullscreen state',
content: {
'application/json': {
schema: SetFullscreenSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
toggleMute: createRoute({
method: 'post',
path: `/api/${API_VERSION}/toggle-mute`,
summary: 'toggle mute',
description: 'Toggle the mute state of the player',
responses: {
204: {
description: 'Success',
},
},
}),
getFullscreenState: createRoute({
method: 'get',
path: `/api/${API_VERSION}/fullscreen`,
summary: 'get fullscreen state',
description: 'Get the current fullscreen state',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({
state: z.boolean(),
}),
},
},
},
},
}),
oldQueueInfo: createRoute({
deprecated: true,
method: 'get',
path: `/api/${API_VERSION}/queue-info`,
summary: 'get current queue info',
description: 'Get the current queue info',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({}),
},
},
},
204: {
description: 'No queue info',
},
},
}),
oldSongInfo: createRoute({
deprecated: true,
method: 'get',
path: `/api/${API_VERSION}/song-info`,
summary: 'get current song info',
description: 'Get the current song info',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: SongInfoSchema,
},
},
},
204: {
description: 'No song info',
},
},
}),
songInfo: createRoute({
method: 'get',
path: `/api/${API_VERSION}/song`,
summary: 'get current song info',
description: 'Get the current song info',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: SongInfoSchema,
},
},
},
204: {
description: 'No song info',
},
},
}),
queueInfo: createRoute({
method: 'get',
path: `/api/${API_VERSION}/queue`,
summary: 'get current queue info',
description: 'Get the current queue info',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({}),
},
},
},
204: {
description: 'No queue info',
},
},
}),
addSongToQueue: createRoute({
method: 'post',
path: `/api/${API_VERSION}/queue`,
summary: 'add song to queue',
description: 'Add a song to the queue',
request: {
body: {
description: 'video id of the song to add',
content: {
'application/json': {
schema: AddSongToQueueSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
moveSongInQueue: createRoute({
method: 'patch',
path: `/api/${API_VERSION}/queue/{index}`,
summary: 'move song in queue',
description: 'Move a song in the queue',
request: {
params: QueueParamsSchema,
body: {
description: 'index to move the song to',
content: {
'application/json': {
schema: MoveSongInQueueSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
removeSongFromQueue: createRoute({
method: 'delete',
path: `/api/${API_VERSION}/queue/{index}`,
summary: 'remove song from queue',
description: 'Remove a song from the queue',
request: {
params: QueueParamsSchema,
},
responses: {
204: {
description: 'Success',
},
},
}),
setQueueIndex: createRoute({
method: 'patch',
path: `/api/${API_VERSION}/queue`,
summary: 'set queue index',
description: 'Set the current index of the queue',
request: {
body: {
description: 'index to move the song to',
content: {
'application/json': {
schema: SetQueueIndexSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
clearQueue: createRoute({
method: 'delete',
path: `/api/${API_VERSION}/queue`,
summary: 'clear queue',
description: 'Clear the queue',
responses: {
204: {
description: 'Success',
},
},
}),
search: createRoute({
method: 'post',
path: `/api/${API_VERSION}/search`,
summary: 'search for a song',
description: 'search for a song',
request: {
body: {
description: 'search query',
content: {
'application/json': {
schema: SearchSchema,
},
},
},
},
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({}),
},
},
},
},
}),
};
export const register = (
app: HonoApp,
{ window }: BackendContext<APIServerConfig>,
songInfoGetter: () => SongInfo | undefined,
repeatModeGetter: () => RepeatMode | undefined,
) => {
const controller = getSongControls(window);
app.openapi(routes.previous, (ctx) => {
controller.previous();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.next, (ctx) => {
controller.next();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.play, (ctx) => {
controller.play();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.pause, (ctx) => {
controller.pause();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.togglePlay, (ctx) => {
controller.playPause();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.like, (ctx) => {
controller.like();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.dislike, (ctx) => {
controller.dislike();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.seekTo, (ctx) => {
const { seconds } = ctx.req.valid('json');
controller.seekTo(seconds);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.goBack, (ctx) => {
const { seconds } = ctx.req.valid('json');
controller.goBack(seconds);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.goForward, (ctx) => {
const { seconds } = ctx.req.valid('json');
controller.goForward(seconds);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.shuffle, (ctx) => {
controller.shuffle();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.repeatMode, (ctx) => {
ctx.status(200);
return ctx.json({ mode: repeatModeGetter() ?? null });
});
app.openapi(routes.switchRepeat, (ctx) => {
const { iteration } = ctx.req.valid('json');
controller.switchRepeat(iteration);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.setVolume, (ctx) => {
const { volume } = ctx.req.valid('json');
controller.setVolume(volume);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.setFullscreen, (ctx) => {
const { state } = ctx.req.valid('json');
controller.setFullscreen(state);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.toggleMute, (ctx) => {
controller.muteUnmute();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.getFullscreenState, async (ctx) => {
const stateResponsePromise = new Promise<boolean>((resolve) => {
ipcMain.once(
'ytmd:set-fullscreen',
(_, isFullscreen: boolean | undefined) => {
return resolve(!!isFullscreen);
},
);
controller.requestFullscreenInformation();
});
const fullscreen = await stateResponsePromise;
ctx.status(200);
return ctx.json({ state: fullscreen });
});
const songInfo = (ctx: Context) => {
const info = songInfoGetter();
if (!info) {
ctx.status(204);
return ctx.body(null);
}
const body = { ...info };
delete body.image;
ctx.status(200);
return ctx.json(body satisfies ResponseSongInfo);
};
app.openapi(routes.oldSongInfo, songInfo);
app.openapi(routes.songInfo, songInfo);
// Queue
const queueInfo = async (ctx: Context) => {
const queueResponsePromise = new Promise<QueueResponse>((resolve) => {
ipcMain.once('ytmd:get-queue-response', (_, queue: QueueResponse) => {
return resolve(queue);
});
controller.requestQueueInformation();
});
const info = await queueResponsePromise;
if (!info) {
ctx.status(204);
return ctx.body(null);
}
ctx.status(200);
return ctx.json(info);
};
app.openapi(routes.oldQueueInfo, queueInfo);
app.openapi(routes.queueInfo, queueInfo);
app.openapi(routes.addSongToQueue, (ctx) => {
const { videoId } = ctx.req.valid('json');
controller.addSongToQueue(videoId);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.moveSongInQueue, (ctx) => {
const index = Number(ctx.req.param('index'));
const { toIndex } = ctx.req.valid('json');
controller.moveSongInQueue(index, toIndex);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.removeSongFromQueue, (ctx) => {
const index = Number(ctx.req.param('index'));
controller.removeSongFromQueue(index);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.setQueueIndex, (ctx) => {
const { index } = ctx.req.valid('json');
controller.setQueueIndex(index);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.clearQueue, (ctx) => {
controller.clearQueue();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.search, async (ctx) => {
const { query } = ctx.req.valid('json');
const response = await controller.search(query);
ctx.status(200);
return ctx.json(response as object);
});
};

View File

@ -0,0 +1,2 @@
export { register as registerControl } from './control';
export { register as registerAuth } from './auth';

View File

@ -0,0 +1,7 @@
import { z } from '@hono/zod-openapi';
export type JWTPayload = z.infer<typeof JWTPayloadSchema>;
export const JWTPayloadSchema = z.object({
id: z.string(),
iat: z.number(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const GoBackSchema = z.object({
seconds: z.number(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const GoForwardScheme = z.object({
seconds: z.number(),
});

View File

@ -0,0 +1,10 @@
export * from './auth';
export * from './song-info';
export * from './seek';
export * from './go-back';
export * from './go-forward';
export * from './switch-repeat';
export * from './set-volume';
export * from './set-fullscreen';
export * from './queue';
export * from './search';

View File

@ -0,0 +1,15 @@
import { z } from '@hono/zod-openapi';
export const QueueParamsSchema = z.object({
index: z.coerce.number().int().nonnegative(),
});
export const AddSongToQueueSchema = z.object({
videoId: z.string(),
});
export const MoveSongInQueueSchema = z.object({
toIndex: z.number(),
});
export const SetQueueIndexSchema = z.object({
index: z.number().int().nonnegative(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const SearchSchema = z.object({
query: z.string(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const SeekSchema = z.object({
seconds: z.number(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const SetFullscreenSchema = z.object({
state: z.boolean(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const SetVolumeSchema = z.object({
volume: z.number(),
});

View File

@ -0,0 +1,26 @@
import { z } from '@hono/zod-openapi';
import { MediaType } from '@/providers/song-info';
export type ResponseSongInfo = z.infer<typeof SongInfoSchema>;
export const SongInfoSchema = z.object({
title: z.string(),
artist: z.string(),
views: z.number(),
uploadDate: z.string().optional(),
imageSrc: z.string().nullable().optional(),
isPaused: z.boolean().optional(),
songDuration: z.number(),
elapsedSeconds: z.number().optional(),
url: z.string().optional(),
album: z.string().nullable().optional(),
videoId: z.string(),
playlistId: z.string().optional(),
mediaType: z.enum([
MediaType.Audio,
MediaType.OriginalMusicVideo,
MediaType.UserGeneratedContent,
MediaType.PodcastEpisode,
MediaType.OtherVideo,
]),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const SwitchRepeatSchema = z.object({
iteration: z.number(),
});

View File

@ -0,0 +1,20 @@
import { OpenAPIHono as Hono } from '@hono/zod-openapi';
import { serve } from '@hono/node-server';
import type { BackendContext } from '@/types/contexts';
import type { SongInfo } from '@/providers/song-info';
import type { RepeatMode } from '@/types/datahost-get-state';
import type { APIServerConfig } from '../config';
export type HonoApp = Hono;
export type BackendType = {
app?: HonoApp;
server?: ReturnType<typeof serve>;
oldConfig?: APIServerConfig;
songInfo?: SongInfo;
currentRepeatMode?: RepeatMode;
init: (ctx: BackendContext<APIServerConfig>) => Promise<void>;
run: (hostname: string, port: number) => void;
end: () => void;
};

View File

@ -0,0 +1,24 @@
export enum AuthStrategy {
AUTH_AT_FIRST = 'AUTH_AT_FIRST',
NONE = 'NONE',
}
export interface APIServerConfig {
enabled: boolean;
hostname: string;
port: number;
authStrategy: AuthStrategy;
secret: string;
authorizedClients: string[];
}
export const defaultAPIServerConfig: APIServerConfig = {
enabled: true,
hostname: '0.0.0.0',
port: 26538,
authStrategy: AuthStrategy.AUTH_AT_FIRST,
secret: Date.now().toString(36),
authorizedClients: [],
};

View File

@ -0,0 +1,17 @@
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import { defaultAPIServerConfig } from './config';
import { onMenu } from './menu';
import { backend } from './backend';
export default createPlugin({
name: () => t('plugins.api-server.name'),
description: () => t('plugins.api-server.description'),
restartNeeded: false,
config: defaultAPIServerConfig,
addedVersion: '3.6.X',
menu: onMenu,
backend,
});

View File

@ -0,0 +1,97 @@
import prompt from 'custom-electron-prompt';
import { t } from '@/i18n';
import promptOptions from '@/providers/prompt-options';
import {
type APIServerConfig,
AuthStrategy,
defaultAPIServerConfig,
} from './config';
import type { MenuContext } from '@/types/contexts';
import type { MenuTemplate } from '@/menu';
export const onMenu = async ({
getConfig,
setConfig,
window,
}: MenuContext<APIServerConfig>): Promise<MenuTemplate> => {
const config = await getConfig();
return [
{
label: t('plugins.api-server.menu.hostname.label'),
type: 'normal',
async click() {
const config = await getConfig();
const newHostname =
(await prompt(
{
title: t('plugins.api-server.prompt.hostname.title'),
label: t('plugins.api-server.prompt.hostname.label'),
value: config.hostname,
type: 'input',
width: 380,
...promptOptions(),
},
window,
)) ??
config.hostname ??
defaultAPIServerConfig.hostname;
setConfig({ ...config, hostname: newHostname });
},
},
{
label: t('plugins.api-server.menu.port.label'),
type: 'normal',
async click() {
const config = await getConfig();
const newPort =
(await prompt(
{
title: t('plugins.api-server.prompt.port.title'),
label: t('plugins.api-server.prompt.port.label'),
value: config.port,
type: 'counter',
counterOptions: { minimum: 0, maximum: 65565 },
width: 380,
...promptOptions(),
},
window,
)) ??
config.port ??
defaultAPIServerConfig.port;
setConfig({ ...config, port: newPort });
},
},
{
label: t('plugins.api-server.menu.auth-strategy.label'),
type: 'submenu',
submenu: [
{
label: t(
'plugins.api-server.menu.auth-strategy.submenu.auth-at-first.label',
),
type: 'radio',
checked: config.authStrategy === AuthStrategy.AUTH_AT_FIRST,
click() {
setConfig({ ...config, authStrategy: AuthStrategy.AUTH_AT_FIRST });
},
},
{
label: t('plugins.api-server.menu.auth-strategy.submenu.none.label'),
type: 'radio',
checked: config.authStrategy === AuthStrategy.NONE,
click() {
setConfig({ ...config, authStrategy: AuthStrategy.NONE });
},
},
],
},
];
};

View File

@ -15,7 +15,10 @@ export default createPlugin({
this.styleSheet = new CSSStyleSheet();
await this.styleSheet.replace(style);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, this.styleSheet];
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
this.styleSheet,
];
},
async stop() {
await this.styleSheet?.replace('');

View File

@ -5,7 +5,6 @@
}
ytmusic-tabs {
top: calc(var(--ytmusic-nav-bar-height) + var(--menu-bar-height, 36px));
backdrop-filter: blur(8px) !important;
}

View File

@ -34,7 +34,7 @@ export default createPlugin<
{
label: t('plugins.captions-selector.menu.autoload'),
type: 'checkbox',
checked: config.autoload as boolean,
checked: config.autoload,
click(item) {
setConfig({ autoload: item.checked });
},
@ -42,7 +42,7 @@ export default createPlugin<
{
label: t('plugins.captions-selector.menu.disable-captions'),
type: 'checkbox',
checked: config.disableCaptions as boolean,
checked: config.disableCaptions,
click(item) {
setConfig({ disableCaptions: item.checked });
},

View File

@ -64,7 +64,7 @@ interface VolumeFade {
// Main class
export class VolumeFader {
private readonly media: HTMLMediaElement;
private readonly logger: VolumeLogger | false;
private readonly logger: VolumeLogger | null;
private scale: {
internalToVolume: (level: number) => number;
volumeToInternal: (level: number) => number;
@ -100,7 +100,7 @@ export class VolumeFader {
this.logger = options.logger;
} else {
// Set log function explicitly to false
this.logger = false;
this.logger = null;
}
// Linear volume fading?
@ -112,7 +112,7 @@ export class VolumeFader {
};
// Log setting
this.logger && this.logger('Using linear fading.');
this.logger?.('Using linear fading.');
}
// No linear, but logarithmic fading…
else {
@ -152,9 +152,8 @@ export class VolumeFader {
};
// Log setting if not default
options.fadeScaling &&
this.logger &&
this.logger(
if (options.fadeScaling)
this.logger?.(
'Using logarithmic fading with ' +
String(10 * dynamicRange) +
' dB dynamic range.',
@ -170,8 +169,7 @@ export class VolumeFader {
this.media.volume = options.initialVolume;
// Log setting
this.logger &&
this.logger('Set initial volume to ' + String(this.media.volume) + '.');
this.logger?.('Set initial volume to ' + String(this.media.volume) + '.');
}
// Fade duration given?
@ -187,7 +185,7 @@ export class VolumeFader {
this.active = false;
// Initialization done
this.logger && this.logger('Initialized for', this.media);
this.logger?.('Initialized for', this.media);
}
/**
@ -236,8 +234,7 @@ export class VolumeFader {
this.fadeDuration = fadeDuration;
// Log setting
this.logger &&
this.logger('Set fade duration to ' + String(fadeDuration) + ' ms.');
this.logger?.('Set fade duration to ' + String(fadeDuration) + ' ms.');
} else {
// Abort and throw an exception
throw new TypeError('Positive number expected as fade duration!');
@ -279,7 +276,7 @@ export class VolumeFader {
this.start();
// Log new fade
this.logger && this.logger('New fade started:', this.fade);
this.logger?.('New fade started:', this.fade);
// Return instance for chaining
return this;
@ -313,7 +310,7 @@ export class VolumeFader {
// Compute current level on internal scale
const level =
(progress * (this.fade.volume.end - this.fade.volume.start)) +
progress * (this.fade.volume.end - this.fade.volume.start) +
this.fade.volume.start;
// Map fade level to volume level and apply it to media element
@ -323,8 +320,7 @@ export class VolumeFader {
window.requestAnimationFrame(this.updateVolume.bind(this));
} else {
// Log end of fade
this.logger &&
this.logger('Fade to ' + String(this.fade.volume.end) + ' complete.');
this.logger?.('Fade to ' + String(this.fade.volume.end) + ' complete.');
// Time is up, jump to target volume
this.media.volume = this.scale.internalToVolume(this.fade.volume.end);
@ -333,7 +329,7 @@ export class VolumeFader {
this.active = false;
// Done, call back (if callable)
typeof this.fade.callback === 'function' && this.fade.callback();
if (typeof this.fade.callback === 'function') this.fade.callback();
// Clear fade
this.fade = undefined;
@ -382,7 +378,7 @@ export class VolumeFader {
input = Math.log10(input);
// Scale minus something × 10 dB to 0…1 (clipping at 0)
return Math.max(1 + (input / dynamicRange), 0);
return Math.max(1 + input / dynamicRange, 0);
}
}

View File

@ -191,7 +191,7 @@ export default createPlugin<
let waitForTransition: Promise<unknown>;
const getStreamURL = async (videoID: string): Promise<string> =>
this.ipc?.invoke('audio-url', videoID);
this.ipc?.invoke('audio-url', videoID) as Promise<string>;
const getVideoIDFromURL = (url: string) =>
new URLSearchParams(url.split('?')?.at(-1)).get('v');

View File

@ -1,10 +1,13 @@
import { app, dialog, ipcMain } from 'electron';
import { app, dialog } from 'electron';
import { Client as DiscordClient } from '@xhayper/discord-rpc';
import { dev } from 'electron-is';
import { ActivityType, GatewayActivityButton } from 'discord-api-types/v10';
import registerCallback, { type SongInfo } from '@/providers/song-info';
import registerCallback, {
type SongInfo,
SongInfoEvent,
} from '@/providers/song-info';
import { createBackend, LoggerPrefix } from '@/utils';
import { t } from '@/i18n';
@ -107,7 +110,7 @@ export const clear = () => {
};
export const registerRefresh = (cb: () => void) => refreshCallbacks.push(cb);
export const isConnected = () => info.rpc !== null;
export const isConnected = () => info.rpc?.isConnected;
export const backend = createBackend<
{
@ -202,15 +205,15 @@ export const backend = createBackend<
}
} else if (!config.hideDurationLeft) {
// Add the start and end time of the song
const songStartTime = Date.now() - ((songInfo.elapsedSeconds ?? 0) * 1000);
const songStartTime = Date.now() - (songInfo.elapsedSeconds ?? 0) * 1000;
activityInfo.startTimestamp = songStartTime;
activityInfo.endTimestamp = songStartTime + (songInfo.songDuration * 1000);
activityInfo.endTimestamp = songStartTime + songInfo.songDuration * 1000;
}
info.rpc.user?.setActivity(activityInfo).catch(console.error);
},
async start({ window: win, getConfig }) {
this.config = await getConfig();
async start(ctx) {
this.config = await ctx.getConfig();
info.rpc.on('connected', () => {
if (dev()) {
@ -239,29 +242,32 @@ export const backend = createBackend<
info.autoReconnect = this.config.autoReconnect;
window = win;
window = ctx.window;
// If the page is ready, register the callback
win.once('ready-to-show', () => {
let lastSongInfo: SongInfo;
registerCallback((songInfo) => {
lastSongInfo = songInfo;
if (this.config) this.updateActivity(songInfo, this.config);
});
connect();
ctx.window.once('ready-to-show', () => {
let lastSent = Date.now();
ipcMain.on('ytmd:time-changed', (_, t: number) => {
registerCallback((songInfo, event) => {
if (event !== SongInfoEvent.TimeChanged) {
info.lastSongInfo = songInfo;
if (this.config) this.updateActivity(songInfo, this.config);
} else {
const currentTime = Date.now();
// if lastSent is more than 5 seconds ago, send the new time
if (currentTime - lastSent > 5000) {
lastSent = currentTime;
if (lastSongInfo) {
lastSongInfo.elapsedSeconds = t;
if (this.config) this.updateActivity(lastSongInfo, this.config);
if (songInfo) {
info.lastSongInfo = songInfo;
if (this.config) this.updateActivity(songInfo, this.config);
}
}
}
});
connect();
});
ctx.ipc.on('ytmd:player-api-loaded', () =>
ctx.ipc.send('ytmd:setup-time-changed-listener'),
);
app.on('window-all-closed', clear);
},
stop() {

View File

@ -30,12 +30,13 @@ import registerCallback, {
getImage,
MediaType,
type SongInfo,
SongInfoEvent,
} from '@/providers/song-info';
import { getNetFetchAsFetch } from '@/plugins/utils/main';
import { t } from '@/i18n';
import { YoutubeFormatList, type Preset, DefaultPresetList } from '../types';
import { DefaultPresetList, type Preset, YoutubeFormatList } from '../types';
import type { DownloaderPluginConfig } from '../index';
@ -62,13 +63,23 @@ let yt: Innertube;
let win: BrowserWindow;
let playingUrl: string;
const isYouTubePremium = () =>
win.webContents.executeJavaScript(
'!document.querySelector(\'#endpoint[href="/music_premium"]\')',
) as Promise<boolean>;
const sendError = (error: Error, source?: string) => {
win.setProgressBar(-1); // Close progress bar
setBadge(0); // Close badge
sendFeedback_(win); // Reset feedback
const songNameMessage = source ? `\nin ${source}` : '';
const cause = error.cause ? `\n\n${String(error.cause)}` : '';
const cause = error.cause
? `\n\n${
// eslint-disable-next-line @typescript-eslint/no-base-to-string,@typescript-eslint/restrict-template-expressions
error.cause instanceof Error ? error.cause.toString() : error.cause
}`
: '';
const message = `${error.toString()}${songNameMessage}${cause}`;
console.error(message);
@ -172,7 +183,14 @@ function downloadSongOnFinishSetup({
let duration: number | undefined;
let time = 0;
registerCallback((songInfo: SongInfo) => {
const defaultDownloadFolder = app.getPath('downloads');
registerCallback((songInfo: SongInfo, event) => {
if (event === SongInfoEvent.TimeChanged) {
const elapsedSeconds = songInfo.elapsedSeconds ?? 0;
if (elapsedSeconds > time) time = elapsedSeconds;
return;
}
if (
!songInfo.isPaused &&
songInfo.url !== currentUrl &&
@ -183,12 +201,22 @@ function downloadSongOnFinishSetup({
config.downloadOnFinish.mode === 'seconds' &&
duration - time <= config.downloadOnFinish.seconds
) {
downloadSong(currentUrl, config.downloadOnFinish.folder ?? config.downloadFolder);
downloadSong(
currentUrl,
config.downloadOnFinish.folder ??
config.downloadFolder ??
defaultDownloadFolder,
);
} else if (
config.downloadOnFinish.mode === 'percent' &&
time >= duration * (config.downloadOnFinish.percent / 100)
) {
downloadSong(currentUrl, config.downloadOnFinish.folder ?? config.downloadFolder);
downloadSong(
currentUrl,
config.downloadOnFinish.folder ??
config.downloadFolder ??
defaultDownloadFolder,
);
}
}
@ -201,10 +229,6 @@ function downloadSongOnFinishSetup({
ipcMain.on('ytmd:player-api-loaded', () => {
ipc.send('ytmd:setup-time-changed-listener');
});
ipcMain.on('ytmd:time-changed', (_, t: number) => {
if (t > time) time = t;
});
}
async function downloadSongUnsafe(
@ -261,12 +285,12 @@ async function downloadSongUnsafe(
let playabilityStatus = info.playability_status;
let bypassedResult = null;
if (playabilityStatus.status === 'LOGIN_REQUIRED') {
if (playabilityStatus?.status === 'LOGIN_REQUIRED') {
// Try to bypass the age restriction
bypassedResult = await getAndroidTvInfo(id);
playabilityStatus = bypassedResult.playability_status;
if (playabilityStatus.status === 'LOGIN_REQUIRED') {
if (playabilityStatus?.status === 'LOGIN_REQUIRED') {
throw new Error(
`[${playabilityStatus.status}] ${playabilityStatus.reason}`,
);
@ -275,7 +299,7 @@ async function downloadSongUnsafe(
info = bypassedResult;
}
if (playabilityStatus.status === 'UNPLAYABLE') {
if (playabilityStatus?.status === 'UNPLAYABLE') {
const errorScreen =
playabilityStatus.error_screen as PlayerErrorMessage | null;
throw new Error(
@ -294,7 +318,7 @@ async function downloadSongUnsafe(
}
const downloadOptions: FormatOptions = {
type: 'audio', // Audio, video or video+audio
type: (await isYouTubePremium()) ? 'audio' : 'video+audio', // Audio, video or video+audio
quality: 'best', // Best, bestefficiency, 144p, 240p, 480p, 720p and so on.
format: 'any', // Media container format
};
@ -438,7 +462,7 @@ async function iterableStreamToProcessedUint8Array(
}),
ratio,
);
increasePlaylistProgress(0.15 + (ratio * 0.85));
increasePlaylistProgress(0.15 + ratio * 0.85);
});
const safeVideoNameWithExtension = `${safeVideoName}.${extension}`;
@ -566,14 +590,17 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
return;
}
if (!playlist || !playlist.items || playlist.items.length === 0 || !playlist.header || !('title' in playlist.header)) {
if (!playlist || !playlist.items || playlist.items.length === 0) {
sendError(
new Error(t('plugins.downloader.backend.feedback.playlist-is-empty')),
);
return;
}
const normalPlaylistTitle = playlist.header?.title?.text;
const normalPlaylistTitle =
playlist.header && 'title' in playlist.header
? playlist.header?.title?.text
: undefined;
const playlistTitle =
normalPlaylistTitle ??
playlist.page.contents_memo
@ -660,7 +687,7 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
const increaseProgress = (itemPercentage: number) => {
const currentProgress = (counter - 1) / (items.length ?? 1);
const newProgress = currentProgress + (progressStep * itemPercentage);
const newProgress = currentProgress + progressStep * itemPercentage;
win.setProgressBar(newProgress);
};

View File

@ -35,7 +35,10 @@ export const onMenu = async ({
click(item) {
setConfig({
downloadOnFinish: {
...deepmerge(defaultConfig.downloadOnFinish, config.downloadOnFinish)!,
...deepmerge(
defaultConfig.downloadOnFinish,
config.downloadOnFinish,
)!,
enabled: item.checked,
},
});
@ -49,14 +52,19 @@ export const onMenu = async ({
click() {
const result = dialog.showOpenDialogSync({
properties: ['openDirectory', 'createDirectory'],
defaultPath: getFolder(config.downloadOnFinish?.folder ?? config.downloadFolder),
defaultPath: getFolder(
config.downloadOnFinish?.folder ?? config.downloadFolder,
),
});
if (result) {
setConfig({
downloadOnFinish: {
...deepmerge(defaultConfig.downloadOnFinish, config.downloadOnFinish)!,
...deepmerge(
defaultConfig.downloadOnFinish,
config.downloadOnFinish,
)!,
folder: result[0],
}
},
});
}
},
@ -76,7 +84,10 @@ export const onMenu = async ({
click() {
setConfig({
downloadOnFinish: {
...deepmerge(defaultConfig.downloadOnFinish, config.downloadOnFinish)!,
...deepmerge(
defaultConfig.downloadOnFinish,
config.downloadOnFinish,
)!,
mode: 'seconds',
},
});
@ -91,7 +102,10 @@ export const onMenu = async ({
click() {
setConfig({
downloadOnFinish: {
...deepmerge(defaultConfig.downloadOnFinish, config.downloadOnFinish)!,
...deepmerge(
defaultConfig.downloadOnFinish,
config.downloadOnFinish,
)!,
mode: 'percent',
},
});
@ -120,7 +134,9 @@ export const onMenu = async ({
min: '0',
step: '1',
},
value: config.downloadOnFinish?.seconds ?? defaultConfig.downloadOnFinish!.seconds,
value:
config.downloadOnFinish?.seconds ??
defaultConfig.downloadOnFinish!.seconds,
},
{
label: t(
@ -133,7 +149,9 @@ export const onMenu = async ({
max: '100',
step: '1',
},
value: config.downloadOnFinish?.percent ?? defaultConfig.downloadOnFinish!.percent,
value:
config.downloadOnFinish?.percent ??
defaultConfig.downloadOnFinish!.percent,
},
],
...promptOptions(),
@ -147,7 +165,10 @@ export const onMenu = async ({
setConfig({
downloadOnFinish: {
...deepmerge(defaultConfig.downloadOnFinish, config.downloadOnFinish)!,
...deepmerge(
defaultConfig.downloadOnFinish,
config.downloadOnFinish,
)!,
seconds: Number(res[0]),
percent: Number(res[1]),
},

View File

@ -8,6 +8,8 @@ import { LoggerPrefix } from '@/utils';
import { t } from '@/i18n';
import { defaultTrustedTypePolicy } from '@/utils/trusted-types';
import { ElementFromHtml } from '../utils/renderer';
import type { RendererContext } from '@/types/contexts';
@ -39,7 +41,9 @@ const menuObserver = new MutationObserver(() => {
if (!menuUrl?.includes('watch?')) {
menuUrl = undefined;
// check for podcast
for (const it of document.querySelectorAll('tp-yt-paper-listbox [tabindex="-1"] #navigation-endpoint')) {
for (const it of document.querySelectorAll(
'tp-yt-paper-listbox [tabindex="-1"] #navigation-endpoint',
)) {
if (it.getAttribute('href')?.includes('podcast/')) {
menuUrl = it.getAttribute('href')!;
break;
@ -72,7 +76,9 @@ export const onRendererLoad = ({
?.getAttribute('href');
if (!videoUrl && songMenu) {
for (const it of songMenu.querySelectorAll('ytmusic-menu-navigation-item-renderer[tabindex="-1"] #navigation-endpoint')) {
for (const it of songMenu.querySelectorAll(
'ytmusic-menu-navigation-item-renderer[tabindex="-1"] #navigation-endpoint',
)) {
if (it.getAttribute('href')?.includes('podcast/')) {
videoUrl = it.getAttribute('href');
break;
@ -86,7 +92,8 @@ export const onRendererLoad = ({
}
if (videoUrl.startsWith('podcast/')) {
videoUrl = defaultConfig.url + '/watch?' + videoUrl.replace('podcast/', 'v=');
videoUrl =
defaultConfig.url + '/watch?' + videoUrl.replace('podcast/', 'v=');
}
if (videoUrl.includes('?playlist=')) {
@ -102,7 +109,10 @@ export const onRendererLoad = ({
ipc.on('downloader-feedback', (feedback: string) => {
if (progress) {
progress.innerHTML = feedback || t('plugins.downloader.templates.button');
const targetHtml = feedback || t('plugins.downloader.templates.button');
(progress.innerHTML as string | TrustedHTML) = defaultTrustedTypePolicy
? defaultTrustedTypePolicy.createHTML(targetHtml)
: targetHtml;
} else {
console.warn(
LoggerPrefix,

Some files were not shown because too many files have changed in this diff Show More