Compare commits

...

284 Commits

Author SHA1 Message Date
fdd55e10bc fix: package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-HONO-12668833
2025-09-15 14:02:26 +00:00
c9ae7cb277 chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2025-09-15 14:01:59 +00:00
e455932754 chore(i18n): Translated using Weblate (Catalan)
Currently translated at 98.2% (448 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ca/
2025-09-14 12:02:01 +02:00
a1e3bf23be chore(i18n): Translated using Weblate (Catalan)
Currently translated at 98.2% (448 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ca/
2025-09-14 12:02:00 +02:00
8ccd510700 chore(i18n): Translated using Weblate (Italian)
Currently translated at 98.9% (451 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2025-09-14 12:01:59 +02:00
Bai
c0a495640f chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2025-09-13 07:52:22 +02:00
6060e138ee chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2025-09-13 07:52:22 +02:00
98b2e182fb chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2025-09-13 07:52:22 +02:00
715ddb8923 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-09-12 12:01:59 +02:00
3104111f6b chore(i18n): Translated using Weblate (Thai)
Currently translated at 99.7% (455 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/th/
2025-09-11 09:02:10 +00:00
e064c37859 chore(i18n): Translated using Weblate (Russian)
Currently translated at 99.7% (455 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-09-11 09:02:08 +00:00
1de223b4ca chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-09-11 09:02:06 +00:00
50a1365a6f chore(i18n): Translated using Weblate (Czech)
Currently translated at 91.4% (417 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/cs/
2025-09-11 09:02:04 +00:00
cc83804491 chore(i18n): Translated using Weblate (Filipino)
Currently translated at 83.9% (383 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fil/
2025-09-09 19:02:05 +00:00
92cf306439 chore(i18n): Translated using Weblate (Swedish)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sv/
2025-09-09 19:02:04 +00:00
a8be510a07 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-09-09 19:02:03 +00:00
58524fb3c1 chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 96.7% (441 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2025-09-09 19:02:02 +00:00
aeb6997117 chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2025-09-09 19:02:01 +00:00
0116188623 fix: maybe fix #3613 2025-09-09 23:43:42 +09:00
af63edb058 fix: update pnpm-lock.yml 2025-09-09 22:42:42 +09:00
bd0ac52832 Revert "fix(deps): update dependency color to v5.0.1 (#3846)" (#3855) 2025-09-09 22:35:32 +09:00
5b537d2a9e fix(deps): update dependency virtua to v0.42.3 (#3847)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-09 22:08:10 +09:00
d9a7c352d3 chore(deps): update dependency typescript-eslint to v8.43.0 (#3848)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-09 22:07:58 +09:00
84add37441 fix(deps): update dependency color to v5.0.1 (#3846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-09 08:34:11 +09:00
9a88f11f16 chore(deps): update dependency vite to v7.1.8 (#3844)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-09 08:33:47 +09:00
51b4441e5c chore(deps): update dependency ts-morph to v27 (#3841)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-09 08:31:35 +09:00
29784e6a39 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-09-08 18:19:17 +02:00
e2981c22fa chore(i18n): Translated using Weblate (Malayalam)
Currently translated at 11.6% (53 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ml/
2025-09-08 14:02:08 +00:00
d7513dcc20 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-09-08 14:02:07 +00:00
5c0face2c9 chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2025-09-08 14:02:04 +00:00
a1805f7662 chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2025-09-08 14:02:03 +00:00
46889098e8 chore(i18n): Translated using Weblate (Dutch)
Currently translated at 95.1% (434 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/nl/
2025-09-08 14:02:02 +00:00
607938c170 chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 96.2% (439 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2025-09-08 14:02:00 +00:00
58a03db898 chore(i18n): Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hans/
2025-09-08 14:01:59 +00:00
67ef3408dc chore(i18n): Translated using Weblate (Italian)
Currently translated at 98.0% (447 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2025-09-08 14:01:57 +00:00
27f16e26b3 chore(i18n): Translated using Weblate (French)
Currently translated at 99.7% (455 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fr/
2025-09-08 14:01:56 +00:00
e38200bc1f chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-09-08 14:01:54 +00:00
736e63d259 Update changelog for v3.11.0 2025-09-07 09:01:30 +00:00
721271d902 fix: Update changelog script in package.json 2025-09-07 15:38:35 +09:00
a2151930ec Bump version to 3.11.0 2025-09-07 15:18:33 +09:00
bdc9f42681 fix: change deprecated option rollupOptions to rolldownOptions 2025-09-07 15:18:02 +09:00
0b3c6f9e1f chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (456 of 456 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2025-09-07 08:16:14 +02:00
ebe373bdc6 chore(package.json): add NODE_ENV 2025-09-07 13:45:40 +09:00
ab91e6d735 Fixed missing videochange dataupdated event when using shuffle (#3659)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: rewhex <gitea@cluser.local>
2025-09-07 13:43:48 +09:00
be3ae4d789 feat(synced-lyrics): preferred provider (global/per-song) (#3741)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-07 13:35:29 +09:00
336b7fe5e9 fix(api-server): use ipc instead of ipcMain 2025-09-07 12:47:08 +09:00
5ecd39f324 feat(api-server): send shuffle state over websocket (#3837) 2025-09-07 04:29:38 +09:00
eb50596961 feat(synced-lyrics): add new "spacer" (#3742)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-07 04:26:03 +09:00
aede0cd643 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (452 of 452 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-09-06 17:20:17 +02:00
25f51784c3 chore(i18n): Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (452 of 452 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hans/
2025-09-06 17:20:17 +02:00
7acac6d11c chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (452 of 452 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2025-09-06 17:20:16 +02:00
1972ef70b5 chore(i18n): Translated using Weblate (Russian)
Currently translated at 99.7% (451 of 452 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-09-06 17:20:16 +02:00
c4455ed3d2 chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (452 of 452 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2025-09-06 17:20:16 +02:00
c1a06ab955 feat: remove unnecessary export default for better tree-shaking 2025-09-06 22:31:02 +09:00
26fa1f85b2 fix(discord-rpc, scrobbler): Align artist and title with the last.fm's de facto standard
- Display only the main artist.
- Display the title in its original language without romanization.

- fix #3358
- fix #3641
2025-09-06 10:25:54 +09:00
555817e2f5 feat(downloader): Add context menu button for playlists and albums (#3768)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-06 09:12:24 +09:00
f8654dfdb9 fix(i18n): fix missing i18n 2025-09-06 09:08:17 +09:00
96c0fc412c chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (442 of 442 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2025-09-06 00:00:58 +00:00
a70a4106df chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (442 of 442 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-09-06 00:00:57 +00:00
895210cbb6 feat(transparent-player): new plugin for Acrylic, Mica or Tabbed effects (#3529)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-06 09:00:39 +09:00
789a30312b fix(reviewdog): checkout PR HEAD 2025-09-06 06:38:36 +09:00
623d97b1e2 fix(reviewdog): run eslint for changed files 2025-09-06 06:28:52 +09:00
4ed97f0145 fix: action should catch errors 2025-09-06 06:22:19 +09:00
77a2bbf02a fix(action): fix permission 2025-09-06 06:09:03 +09:00
7a9a1531d4 fix(action): fix auth 2025-09-06 05:35:59 +09:00
16b59698d6 fix(action): fix node version 2025-09-06 05:30:58 +09:00
a85a2e0c58 fix(action): fix install deps 2025-09-06 05:27:38 +09:00
97f1a20a4f fix(actions): fix mistake 2025-09-06 05:19:21 +09:00
8dbe151ddd fix(audio-compressor): real-time behavior and duplicated audio bug (#3786)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-06 05:15:47 +09:00
87144e03c2 fix(actions): fix node / pnpm version 2025-09-06 05:13:51 +09:00
2046b253e3 fix: Added Min height and width to the window which doesnt breaks the UI responsiveness (#3602) 2025-09-06 05:04:16 +09:00
c068e11fc5 feat(actions): add reviewdog 2025-09-06 04:54:53 +09:00
10384b6c4c chore(eslint): added new eslint rule (for jsx) 2025-09-06 04:51:31 +09:00
4d83bd587d chore(deps): update dependency discord-api-types to v0.38.23 (#3833)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-06 02:55:56 +09:00
aae523989b feat(plugin): Custom output device plugin (#3789)
Co-authored-by: Angelos Bouklis <me@arjix.dev>
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-06 02:54:07 +09:00
afacec973b chore(deps): update dependency @babel/runtime to v7.28.4 (#3831)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-06 01:20:54 +09:00
75fb51e290 chore(deps): update eslint monorepo to v9.35.0 (#3829)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-06 01:18:02 +09:00
cb85048af4 feat(api-server): Add websocket as /api/v1/ws route (#3707)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-06 01:17:32 +09:00
8b10872e83 feat(api-server): Improved api-server volume and like/dislike state (#3592)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: rewhex <gitea@cluser.local>
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-05 23:59:39 +09:00
96ea114335 fix: pnpm-lock.yaml 2025-09-05 23:02:15 +09:00
7c1c3ef28d Merge remote-tracking branch 'origin/master' 2025-09-05 22:45:43 +09:00
7a7ad4261c fix(deps): update dependency i18next to v25.5.2 (#3826)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 22:45:33 +09:00
c0dbc204a0 fix(deps): update dependency virtua to v0.42.2 (#3827)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 22:45:19 +09:00
68e63f809c fix: apply fix from eslint 2025-09-05 22:43:34 +09:00
4b188ec205 chore(i18n): Translated using Weblate (Thai)
Currently translated at 100.0% (437 of 437 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/th/
2025-09-05 15:07:03 +02:00
23013cddb9 fix(exponential-volume): volume desync bug (#3787)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-05 20:53:07 +09:00
588b84ecd0 feat(synced-lyrics): thai romanization (#3618)
Co-authored-by: Angelos Bouklis <me@arjix.dev>
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-05 16:30:39 +09:00
fd68c204f6 chore(i18n): Translated using Weblate (Swedish)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sv/
2025-09-05 06:58:38 +00:00
313bb6e43f chore(i18n): Translated using Weblate (Swedish)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sv/
2025-09-05 06:58:37 +00:00
0a6f244035 chore(i18n): Translated using Weblate (Swedish)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sv/
2025-09-05 06:58:36 +00:00
8e4e2c42f6 feat(discord): add option to display artist/title in status (#3692)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-05 15:58:26 +09:00
f31053cf3c chore(deps): update playwright monorepo to v1.55.0 (#3819)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:43:02 +09:00
d5758790c0 fix(deps): update dependency i18next to v25.5.1 (#3820)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:42:52 +09:00
bbd243a534 fix(deps): update dependency virtua to v0.42.0 (#3821)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:42:41 +09:00
2fc0d6f3b0 fix(deps): update dependency zod to v4.1.5 (#3822)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:42:31 +09:00
6b15018a9b chore(deps): update eslint monorepo to v9.34.0 (#3818)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:42:24 +09:00
acc977db7c chore(deps): update actions/setup-node action to v5 (#3823)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:42:03 +09:00
270100a14c chore(deps): update dependency electron to v38 (#3824)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:41:43 +09:00
094e6fa2d6 chore(deps): update dependency @stylistic/eslint-plugin to v5.3.1 (#3817)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:40:46 +09:00
9f81f7001c fix(deps): update dependency serve to v14.2.5 (#3816)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:40:21 +09:00
lew
e6c78dd5e0 feat(discord): add song & artist URLs to rich presence (#3737)
Co-authored-by: JellyBrick <shlee1503@naver.com>
2025-09-05 15:32:31 +09:00
b64e1394ae fix: fix #3621 (#3774) 2025-09-05 15:32:15 +09:00
dcc611c7d0 feat(refactor): PluginDefinition::platform (#3665) 2025-09-05 15:28:17 +09:00
d329076b52 chore(docs): update copyright footer year (#3792) 2025-09-05 15:10:28 +09:00
1435559a56 chore(deps): update dependency vite-plugin-inspect to v11.3.3 (#3814)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:08:36 +09:00
1feeeedf10 fix(deps): update dependency @floating-ui/dom to v1.7.4 (#3815)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:07:50 +09:00
443d716e45 fix(deps): update dependency @ghostery/adblocker-electron to v2.11.6 (#3770)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:01:46 +09:00
3d65a96e38 chore(deps): update dependency discord-api-types to v0.38.22 (#3813)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:01:37 +09:00
e20f3fe24c chore(deps): update dependency @types/semver to v7.7.1 (#3812)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 15:01:30 +09:00
5d3afb52d8 fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.11.6 (#3771)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:59:44 +09:00
5e0341c8d5 fix(deps): update dependency @hono/node-server to v1.19.1 (#3759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:58:08 +09:00
b84a8c512a chore(deps): update dependency typescript-eslint to v8.42.0 (#3761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:57:52 +09:00
cd0f4bbc1d chore(deps): update dependency node-gyp to v11.4.2 (#3772)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:57:38 +09:00
e37367c5e5 chore(deps): update actions/checkout action to v5 (#3757)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:55:52 +09:00
8a765be912 chore(deps): update dependency vite to v7.1.5 (#3760)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:54:47 +09:00
a213dae14d fix(deps): update dependency hono to v4.9.6 [security] (#3807)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:50:33 +09:00
40c429f3c1 chore(deps): update dependency electron to v37.3.1 [security] (#3806)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-05 14:50:13 +09:00
3125520e68 chore(deps): bump hono from 4.9.2 to 4.9.6 (#3805)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-05 14:49:48 +09:00
1c57fec016 chore(i18n): Translated using Weblate (Swedish)
Currently translated at 37.6% (163 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sv/
2025-09-04 20:01:57 +02:00
2708b4fffc chore(i18n): Translated using Weblate (Greek)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/el/
2025-09-02 19:22:57 +02:00
f1d264a6c7 chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-09-01 21:13:45 +02:00
c478e74771 chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2025-09-01 21:13:45 +02:00
6cf9f813a0 chore(i18n): Translated using Weblate (Bosnian)
Currently translated at 22.1% (96 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/bs/
2025-08-30 23:01:51 +02:00
dddfa581ed chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2025-08-29 17:41:00 +02:00
94b789aa78 chore(i18n): Translated using Weblate (Albanian)
Currently translated at 0.4% (2 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sq/
2025-08-25 16:02:12 +00:00
d6d731260b chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2025-08-25 16:02:11 +00:00
440864e605 chore(i18n): Added translation using Weblate (Albanian) 2025-08-24 17:34:48 +02:00
4506ae4079 chore(i18n): Translated using Weblate (Galician)
Currently translated at 5.5% (24 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/gl/
2025-08-24 17:34:47 +02:00
c2538e280a chore(i18n): Translated using Weblate (Finnish)
Currently translated at 84.5% (366 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fi/
2025-08-24 17:34:47 +02:00
ef7da94201 chore(i18n): Translated using Weblate (Catalan)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ca/
2025-08-21 17:02:09 +00:00
68a754f438 chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2025-08-19 22:02:19 +02:00
2a81a4e887 chore: remove unused deps 2025-08-17 23:46:06 +09:00
40d64fb04f fix: fix bundling error 2025-08-17 23:16:37 +09:00
c6bc65b3d3 chore(deps): update playwright monorepo to v1.54.2 (#3713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:52:01 +09:00
db02e009cd chore(deps): update dependency vite to v7.1.2 (#3710)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:50:12 +09:00
b0b6ebe036 chore(deps): update dependency @stylistic/eslint-plugin to v5.2.3 (#3754)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:48:25 +09:00
be698cc0fb chore(deps): update dependency @babel/runtime to v7.28.3 (#3753)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:48:13 +09:00
06b35acf65 chore(deps): update dependency discord-api-types to v0.38.20 (#3706)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:48:02 +09:00
557932f7bb fix(deps): update dependency @floating-ui/dom to v1.7.3 (#3714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:46:55 +09:00
d48f328881 chore(deps): update dependency vite-plugin-solid to v2.11.8 (#3711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:46:10 +09:00
4e7f40c86a chore(deps): update dependency rollup to v4.46.2 (#3709)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:45:52 +09:00
614c774e71 chore(deps): update dependency @electron/universal to v3.0.1 (#3705)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:45:31 +09:00
3fa4ab54b6 chore(deps): update dependency electron to v37.3.0 (#3708)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-17 22:44:23 +09:00
de8136dbe4 chore(docs): Grammar mistakes (#3722) 2025-08-17 22:39:45 +09:00
4051aec6e3 chore(i18n): Translated using Weblate (Romanian)
Currently translated at 99.7% (432 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ro/
2025-08-17 13:02:10 +00:00
aa0496c548 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 88.9% (385 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2025-08-15 14:02:11 +00:00
a953b5995c chore(i18n): Translated using Weblate (Czech)
Currently translated at 96.0% (416 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/cs/
2025-08-14 15:02:03 +02:00
ff2d889329 chore(i18n): Translated using Weblate (Czech)
Currently translated at 96.0% (416 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/cs/
2025-08-14 15:02:01 +02:00
f3b1adbd32 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 88.4% (383 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2025-08-13 05:02:13 +02:00
247443630a chore(i18n): Translated using Weblate (Dutch)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/nl/
2025-08-13 05:02:11 +02:00
6eb54afda4 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-08-09 03:01:54 +00:00
83ecc499e3 chore(i18n): Translated using Weblate (Japanese)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ja/
2025-08-09 03:01:53 +00:00
418a6ce8e4 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-08-09 03:01:52 +00:00
4f19f73d4d chore(i18n): Translated using Weblate (Bengali)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/bn/
2025-08-07 15:02:01 +00:00
31d109e00f chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-08-07 15:01:58 +00:00
fd3f79e976 chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-08-06 13:01:57 +00:00
c748e606b1 chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2025-08-04 19:02:01 +00:00
40299b38c5 chore(i18n): Translated using Weblate (Tamil)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ta/
2025-08-03 09:02:30 +00:00
62b40d4df5 fix: typed networkManager.fetch 2025-08-02 16:49:15 +09:00
5e4a1253d4 chore(i18n): Translated using Weblate (French)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fr/
2025-08-01 00:02:22 +02:00
702792b659 chore(i18n): Translated using Weblate (Azerbaijani)
Currently translated at 13.6% (59 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/az/
2025-07-30 20:06:32 +02:00
e83f83fa9b chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-30 20:06:32 +02:00
3de54340f3 chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2025-07-30 20:06:32 +02:00
ffbc3bd1c2 chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2025-07-30 20:06:31 +02:00
c513959461 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-29 17:15:56 +02:00
66e414dd64 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 86.6% (375 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2025-07-29 17:15:55 +02:00
454d2a1d4e chore(i18n): Translated using Weblate (Lithuanian)
Currently translated at 76.4% (331 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/lt/
2025-07-29 17:15:54 +02:00
ca3372d7f5 chore(i18n): Translated using Weblate (Thai)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/th/
2025-07-29 17:15:53 +02:00
5bcbab1fac chore(i18n): Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hans/
2025-07-29 17:15:52 +02:00
47656c08fd chore(i18n): Translated using Weblate (Polish)
Currently translated at 100.0% (433 of 433 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2025-07-29 17:15:51 +02:00
6374ff4a41 fix: fix #3661 2025-07-28 23:55:55 +09:00
86e7c84e43 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-28 16:32:22 +02:00
d554fa34b2 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-07-28 16:32:21 +02:00
1bec276c8b fix: fix #3613, fix #3651 2025-07-28 23:29:46 +09:00
17153eacf0 Fixes the error 500 for /auth/ endpoint (#3627)
Co-authored-by: rewhex <gitea@cluser.local>
2025-07-28 23:19:22 +09:00
20d25ca953 feat: add custom window title option (#3656) 2025-07-28 23:16:47 +09:00
b3b3d45b96 fix(downloader): fix for getBasicInfo 2025-07-28 23:09:25 +09:00
5ba65ea122 fix: bump dependencies 2025-07-28 23:02:17 +09:00
0108e3f603 fix: rollback electron version to v37 2025-07-28 22:53:15 +09:00
8d23b13f70 fix(deps): update dependency zod to v4.0.10 (#3686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 22:40:12 +09:00
a8f9505255 chore(deps): update dependency @babel/runtime to v7.28.2 (#3687)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 22:39:56 +09:00
cd0509eb06 chore(deps): update dependency rollup to v4.46.1 (#3632)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 22:39:42 +09:00
23504408ec chore(deps): update dependency electron to v38.0.0-alpha.10 (#3681)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 22:37:39 +09:00
AZE
ba8282881d chore(i18n): Translated using Weblate (Azerbaijani)
Currently translated at 10.0% (43 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/az/
2025-07-28 07:03:06 +02:00
ad1ac79fdb chore(i18n): Translated using Weblate (Bengali)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/bn/
2025-07-28 07:03:04 +02:00
54736256a4 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-28 07:02:56 +02:00
0d77ac096d chore(i18n): Translated using Weblate (English)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/en/
2025-07-28 07:02:44 +02:00
6a2b27bfcb chore(i18n): Translated using Weblate (Greek)
Currently translated at 98.3% (423 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/el/
2025-07-26 21:08:10 +00:00
2a0aeac89b chore(deps): update dependency eslint-config-prettier to v10.1.8 (#3676)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:35:26 +09:00
5dc11e2bdc chore(deps): update dependency eslint-plugin-prettier to v5.5.3 (#3678)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:15:44 +09:00
fba48dcd55 fix(deps): update dependency @ghostery/adblocker-electron to v2.11.3 (#3679)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:12:57 +09:00
832c3103c7 chore(deps): update dependency discord-api-types to v0.38.17 (#3620)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:04:24 +09:00
49d9bf9859 chore(deps): update dependency esbuild to v0.25.8 (#3675)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:04:13 +09:00
ef5d0c1222 chore(deps): update dependency @stylistic/eslint-plugin to v5.2.2 (#3636)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:03:41 +09:00
1cb666d7dd fix(deps): update dependency @hono/node-server to v1.17.1 (#3625)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 23:02:29 +09:00
45ca896bef chore(i18n): Translated using Weblate (Portuguese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt/
2025-07-25 14:48:21 +02:00
624d5102a5 fix(deps): update dependency hono to v4.8.7 (#3567)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 18:03:03 +09:00
2e9e5cc51f chore(deps): update dependency typescript-eslint to v8.38.0 (#3628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 18:00:31 +09:00
c5f755bfcf chore(deps): update dependency electron to v38.0.0-alpha.9 (#3626)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 18:00:24 +09:00
0d1cadd650 fix(Skip Disliked Song): updated querySelector (#3667)
Co-authored-by: Joel Carlos <joel.carlos@merkle.com>
2025-07-25 18:00:13 +09:00
4cc7ffe74d chore(deps): update dependency vite to v7.0.11 (#3624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 17:59:39 +09:00
7f59ca18b0 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-25 08:03:56 +02:00
f87030ff55 chore(i18n): Translated using Weblate (Latvian)
Currently translated at 54.8% (236 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/lv/
2025-07-23 14:02:56 +02:00
2406baa5a5 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-23 14:02:55 +02:00
d7bf973547 chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2025-07-21 23:03:00 +02:00
0d199b82ec chore(i18n): Translated using Weblate (Polish)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2025-07-21 23:02:59 +02:00
7d7562d147 chore(i18n): Translated using Weblate (Czech)
Currently translated at 87.9% (378 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/cs/
2025-07-21 23:02:58 +02:00
9d43fb2bb3 chore(i18n): Translated using Weblate (Nepali)
Currently translated at 99.7% (429 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ne/
2025-07-20 09:02:39 +02:00
010da7536d chore(i18n): Translated using Weblate (Romanian)
Currently translated at 99.7% (429 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ro/
2025-07-20 09:02:38 +02:00
3473f05823 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 86.9% (374 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2025-07-18 13:03:13 +02:00
f72664957d chore(i18n): Translated using Weblate (Hindi)
Currently translated at 86.9% (374 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2025-07-18 13:03:12 +02:00
a127c2e5e2 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-18 13:03:10 +02:00
952da4ddf6 chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2025-07-18 13:03:09 +02:00
bf84477609 chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2025-07-18 13:03:07 +02:00
e274a1b4c4 chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2025-07-18 13:03:06 +02:00
e6150a5b53 chore(i18n): Translated using Weblate (Italian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2025-07-18 13:03:04 +02:00
dfd881186a chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:30 +00:00
762b66dbcd chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:29 +00:00
f1acfbf48f chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:29 +00:00
046faecf11 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:28 +00:00
c3612d2ca7 chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:27 +00:00
3da344fcad chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:26 +00:00
2b5380e67e chore(i18n): Translated using Weblate (Vietnamese)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/vi/
2025-07-17 10:02:26 +00:00
e3c7e4f524 chore(i18n): Translated using Weblate (Lithuanian)
Currently translated at 75.8% (326 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/lt/
2025-07-17 10:02:25 +00:00
3604e46661 chore(i18n): Translated using Weblate (Thai)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/th/
2025-07-15 19:01:50 +02:00
8cea079f26 chore(i18n): Translated using Weblate (Japanese)
Currently translated at 99.5% (428 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ja/
2025-07-15 19:01:49 +02:00
83b68001cb chore(i18n): Translated using Weblate (Bosnian)
Currently translated at 20.2% (87 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/bs/
2025-07-14 13:47:47 +02:00
7a11a47f91 chore(i18n): Translated using Weblate (Bosnian)
Currently translated at 20.2% (87 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/bs/
2025-07-14 13:47:47 +02:00
2a9a00bd86 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-14 13:47:47 +02:00
cfcbf37f98 chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
7f5c854c00 chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
7ec89580e7 chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
56a5102377 chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
b6e9b5ac2b chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
eecdbbd2c4 chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
efeb871490 chore(i18n): Translated using Weblate (Croatian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hr/
2025-07-14 13:47:46 +02:00
f326a55247 chore(i18n): Translated using Weblate (Dutch)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/nl/
2025-07-14 13:47:46 +02:00
e788585bd4 chore(i18n): Translated using Weblate (Dutch)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/nl/
2025-07-14 13:47:46 +02:00
1396761b18 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-07-14 13:47:45 +02:00
5872e0f736 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-07-14 13:47:45 +02:00
1872c8193d chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-07-14 13:47:45 +02:00
187a0c54cb chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-07-14 13:47:45 +02:00
9533497388 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-07-14 13:47:45 +02:00
f323b7bb1f chore(i18n): Translated using Weblate (Japanese)
Currently translated at 98.8% (425 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ja/
2025-07-14 13:47:45 +02:00
68810b4762 chore(i18n): Translated using Weblate (French)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/fr/
2025-07-14 13:47:45 +02:00
d3e01d0732 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-07-14 13:47:44 +02:00
970cf7ee91 chore(i18n): Translated using Weblate (Spanish)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2025-07-14 13:47:44 +02:00
4bf038e24d chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2025-07-14 13:47:44 +02:00
5925b765b8 fix(deps): update dependency @hono/zod-validator to v0.7.1 (#3616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 22:43:21 +09:00
78cd3a786c Update changelog for v3.10.0 2025-07-13 08:26:54 +00:00
adb88991d9 Bump version to 3.10.0 2025-07-13 17:10:18 +09:00
4dad68d255 fix(downloader): code splitting (happy-dom) 2025-07-13 17:04:38 +09:00
33a09cc8e1 fix(api-server): fix #3572 2025-07-13 16:43:29 +09:00
e2c849f6c4 fix(store): fix synced lyrics config 2025-07-13 16:38:38 +09:00
7b41775b26 fix(store): fix migrator 2025-07-13 16:36:51 +09:00
6284b87fc7 fix(deps): update dependency butterchurn to v3.0.0-beta.5 (#3610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 16:32:03 +09:00
f3f63d4fcd fix: bump @hono/zod-openapi version 2025-07-13 16:24:38 +09:00
cf80dd396c fix: remove the weird scrollbar
- Bump electron version to v38
- Remove `FluentScrollbar`
2025-07-13 16:06:46 +09:00
c79fc799b2 chore(i18n): Translated using Weblate (Basque)
Currently translated at 0.6% (3 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/eu/
2025-07-13 08:16:01 +02:00
7789d5d444 chore(i18n): Added translation using Weblate (Basque) 2025-07-13 08:14:58 +02:00
e0dbd4b88f chore(i18n): Translated using Weblate (Azerbaijani)
Currently translated at 0.6% (3 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/az/
2025-07-13 08:14:08 +02:00
1c74bbd954 chore(i18n): Translated using Weblate (Korean)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ko/
2025-07-13 08:10:35 +02:00
d949e3550f chore(deps): update eslint monorepo to v9.31.0 (#3600)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 14:19:01 +09:00
d76115ab5d chore(i18n): Translated using Weblate (Arabic)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ar/
2025-07-13 07:01:56 +02:00
5be467a869 chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2025-07-13 07:01:54 +02:00
b2dfbe1ed3 chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2025-07-13 07:01:52 +02:00
a9e9e0bdc2 chore(i18n): Translated using Weblate (Turkish)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/tr/
2025-07-13 07:01:50 +02:00
93ce9cc359 chore(i18n): Translated using Weblate (Russian)
Currently translated at 99.7% (429 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2025-07-13 07:01:47 +02:00
2a626a5ff1 chore(deps): update dependency rollup to v4.45.0 (#3568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 13:53:37 +09:00
1ccabb8e25 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:42 +02:00
2dae8688c2 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:42 +02:00
65459726a4 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:42 +02:00
0c21accb10 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
125d2d5163 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
6c1855b5a5 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
82c5222610 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
0d0e2a11e1 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
daf724f9dc chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
be2cdb4cb5 chore(i18n): Translated using Weblate (Serbian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/sr/
2025-07-12 00:03:41 +02:00
ff2fdab77d chore(i18n): Translated using Weblate (Tamil)
Currently translated at 98.6% (424 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ta/
2025-07-12 00:03:41 +02:00
9047169a39 chore(i18n): Translated using Weblate (Sinhala)
Currently translated at 23.2% (100 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/si/
2025-07-12 00:03:41 +02:00
9525df343f chore(i18n): Translated using Weblate (Sinhala)
Currently translated at 23.2% (100 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/si/
2025-07-12 00:03:40 +02:00
be2abee85d chore(i18n): Translated using Weblate (Bulgarian)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/bg/
2025-07-12 00:03:40 +02:00
7d5f7a9527 chore(i18n): Translated using Weblate (German)
Currently translated at 100.0% (430 of 430 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/de/
2025-07-12 00:03:40 +02:00
175 changed files with 7784 additions and 2957 deletions

View File

@ -18,7 +18,7 @@ jobs:
os: [ macos-latest, ubuntu-latest, windows-latest ]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Install pnpm
uses: pnpm/action-setup@v4
@ -28,14 +28,14 @@ jobs:
- name: Setup NodeJS
if: startsWith(matrix.os, 'macOS') != true
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Setup NodeJS for macOS
if: startsWith(matrix.os, 'macOS')
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: ${{ env.NODE_VERSION }}
@ -91,7 +91,7 @@ jobs:
if: github.repository == 'th-ch/youtube-music' && github.ref == 'refs/heads/master'
needs: build
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
@ -103,14 +103,14 @@ jobs:
- name: Setup NodeJS
if: startsWith(matrix.os, 'macOS') != true
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Setup NodeJS for macOS
if: startsWith(matrix.os, 'macOS')
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: ${{ env.NODE_VERSION }}

View File

@ -15,6 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: "Checkout Repository"
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: "Dependency Review"
uses: actions/dependency-review-action@v4

41
.github/workflows/reviewdog.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: reviewdog
on: [pull_request_target]
env:
NODE_VERSION: "22.x"
jobs:
eslint:
name: runner / eslint
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
run_install: false
- name: Setup NodeJS
uses: actions/setup-node@v5
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: reviewdog/action-eslint@v1.34.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review # Change reporter.
eslint_flags: './src'
fail_level: error

View File

@ -2,8 +2,269 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v3.11.0](https://github.com/th-ch/youtube-music/compare/v3.10.0...v3.11.0)
- Fixed missing videochange dataupdated event when using shuffle [`#3659`](https://github.com/th-ch/youtube-music/pull/3659)
- feat(synced-lyrics): preferred provider (global/per-song) [`#3741`](https://github.com/th-ch/youtube-music/pull/3741)
- feat(api-server): send shuffle state over websocket [`#3837`](https://github.com/th-ch/youtube-music/pull/3837)
- feat(synced-lyrics): add new "spacer" [`#3742`](https://github.com/th-ch/youtube-music/pull/3742)
- feat(downloader): Add context menu button for playlists and albums [`#3768`](https://github.com/th-ch/youtube-music/pull/3768)
- feat(transparent-player): new plugin for Acrylic, Mica or Tabbed effects [`#3529`](https://github.com/th-ch/youtube-music/pull/3529)
- fix(audio-compressor): real-time behavior and duplicated audio bug [`#3786`](https://github.com/th-ch/youtube-music/pull/3786)
- fix: Added Min height and width to the window which doesnt breaks the UI responsiveness [`#3602`](https://github.com/th-ch/youtube-music/pull/3602)
- chore(deps): update dependency discord-api-types to v0.38.23 [`#3833`](https://github.com/th-ch/youtube-music/pull/3833)
- feat(plugin): Custom output device plugin [`#3789`](https://github.com/th-ch/youtube-music/pull/3789)
- chore(deps): update dependency @babel/runtime to v7.28.4 [`#3831`](https://github.com/th-ch/youtube-music/pull/3831)
- chore(deps): update eslint monorepo to v9.35.0 [`#3829`](https://github.com/th-ch/youtube-music/pull/3829)
- feat(api-server): Add websocket as `/api/v1/ws` route [`#3707`](https://github.com/th-ch/youtube-music/pull/3707)
- feat(api-server): Improved api-server volume and like/dislike state [`#3592`](https://github.com/th-ch/youtube-music/pull/3592)
- fix(deps): update dependency i18next to v25.5.2 [`#3826`](https://github.com/th-ch/youtube-music/pull/3826)
- fix(deps): update dependency virtua to v0.42.2 [`#3827`](https://github.com/th-ch/youtube-music/pull/3827)
- fix(exponential-volume): volume desync bug [`#3787`](https://github.com/th-ch/youtube-music/pull/3787)
- feat(synced-lyrics): thai romanization [`#3618`](https://github.com/th-ch/youtube-music/pull/3618)
- feat(discord): add option to display artist/title in status [`#3692`](https://github.com/th-ch/youtube-music/pull/3692)
- chore(deps): update playwright monorepo to v1.55.0 [`#3819`](https://github.com/th-ch/youtube-music/pull/3819)
- fix(deps): update dependency i18next to v25.5.1 [`#3820`](https://github.com/th-ch/youtube-music/pull/3820)
- fix(deps): update dependency virtua to v0.42.0 [`#3821`](https://github.com/th-ch/youtube-music/pull/3821)
- fix(deps): update dependency zod to v4.1.5 [`#3822`](https://github.com/th-ch/youtube-music/pull/3822)
- chore(deps): update eslint monorepo to v9.34.0 [`#3818`](https://github.com/th-ch/youtube-music/pull/3818)
- chore(deps): update actions/setup-node action to v5 [`#3823`](https://github.com/th-ch/youtube-music/pull/3823)
- chore(deps): update dependency electron to v38 [`#3824`](https://github.com/th-ch/youtube-music/pull/3824)
- chore(deps): update dependency @stylistic/eslint-plugin to v5.3.1 [`#3817`](https://github.com/th-ch/youtube-music/pull/3817)
- fix(deps): update dependency serve to v14.2.5 [`#3816`](https://github.com/th-ch/youtube-music/pull/3816)
- feat(discord): add song & artist URLs to rich presence [`#3737`](https://github.com/th-ch/youtube-music/pull/3737)
- fix: fix #3621 [`#3774`](https://github.com/th-ch/youtube-music/pull/3774)
- feat(refactor): PluginDefinition::platform [`#3665`](https://github.com/th-ch/youtube-music/pull/3665)
- chore(docs): update copyright footer year [`#3792`](https://github.com/th-ch/youtube-music/pull/3792)
- chore(deps): update dependency vite-plugin-inspect to v11.3.3 [`#3814`](https://github.com/th-ch/youtube-music/pull/3814)
- fix(deps): update dependency @floating-ui/dom to v1.7.4 [`#3815`](https://github.com/th-ch/youtube-music/pull/3815)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.11.6 [`#3770`](https://github.com/th-ch/youtube-music/pull/3770)
- chore(deps): update dependency discord-api-types to v0.38.22 [`#3813`](https://github.com/th-ch/youtube-music/pull/3813)
- chore(deps): update dependency @types/semver to v7.7.1 [`#3812`](https://github.com/th-ch/youtube-music/pull/3812)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.11.6 [`#3771`](https://github.com/th-ch/youtube-music/pull/3771)
- fix(deps): update dependency @hono/node-server to v1.19.1 [`#3759`](https://github.com/th-ch/youtube-music/pull/3759)
- chore(deps): update dependency typescript-eslint to v8.42.0 [`#3761`](https://github.com/th-ch/youtube-music/pull/3761)
- chore(deps): update dependency node-gyp to v11.4.2 [`#3772`](https://github.com/th-ch/youtube-music/pull/3772)
- chore(deps): update actions/checkout action to v5 [`#3757`](https://github.com/th-ch/youtube-music/pull/3757)
- chore(deps): update dependency vite to v7.1.5 [`#3760`](https://github.com/th-ch/youtube-music/pull/3760)
- fix(deps): update dependency hono to v4.9.6 [security] [`#3807`](https://github.com/th-ch/youtube-music/pull/3807)
- chore(deps): update dependency electron to v37.3.1 [security] [`#3806`](https://github.com/th-ch/youtube-music/pull/3806)
- chore(deps): bump hono from 4.9.2 to 4.9.6 [`#3805`](https://github.com/th-ch/youtube-music/pull/3805)
- chore(deps): update playwright monorepo to v1.54.2 [`#3713`](https://github.com/th-ch/youtube-music/pull/3713)
- chore(deps): update dependency vite to v7.1.2 [`#3710`](https://github.com/th-ch/youtube-music/pull/3710)
- chore(deps): update dependency @stylistic/eslint-plugin to v5.2.3 [`#3754`](https://github.com/th-ch/youtube-music/pull/3754)
- chore(deps): update dependency @babel/runtime to v7.28.3 [`#3753`](https://github.com/th-ch/youtube-music/pull/3753)
- chore(deps): update dependency discord-api-types to v0.38.20 [`#3706`](https://github.com/th-ch/youtube-music/pull/3706)
- fix(deps): update dependency @floating-ui/dom to v1.7.3 [`#3714`](https://github.com/th-ch/youtube-music/pull/3714)
- chore(deps): update dependency vite-plugin-solid to v2.11.8 [`#3711`](https://github.com/th-ch/youtube-music/pull/3711)
- chore(deps): update dependency rollup to v4.46.2 [`#3709`](https://github.com/th-ch/youtube-music/pull/3709)
- chore(deps): update dependency @electron/universal to v3.0.1 [`#3705`](https://github.com/th-ch/youtube-music/pull/3705)
- chore(deps): update dependency electron to v37.3.0 [`#3708`](https://github.com/th-ch/youtube-music/pull/3708)
- chore(docs): Grammar mistakes [`#3722`](https://github.com/th-ch/youtube-music/pull/3722)
- Fixes the error 500 for /auth/ endpoint [`#3627`](https://github.com/th-ch/youtube-music/pull/3627)
- feat: add custom window title option [`#3656`](https://github.com/th-ch/youtube-music/pull/3656)
- fix(deps): update dependency zod to v4.0.10 [`#3686`](https://github.com/th-ch/youtube-music/pull/3686)
- chore(deps): update dependency @babel/runtime to v7.28.2 [`#3687`](https://github.com/th-ch/youtube-music/pull/3687)
- chore(deps): update dependency rollup to v4.46.1 [`#3632`](https://github.com/th-ch/youtube-music/pull/3632)
- chore(deps): update dependency electron to v38.0.0-alpha.10 [`#3681`](https://github.com/th-ch/youtube-music/pull/3681)
- chore(deps): update dependency eslint-config-prettier to v10.1.8 [`#3676`](https://github.com/th-ch/youtube-music/pull/3676)
- chore(deps): update dependency eslint-plugin-prettier to v5.5.3 [`#3678`](https://github.com/th-ch/youtube-music/pull/3678)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.11.3 [`#3679`](https://github.com/th-ch/youtube-music/pull/3679)
- chore(deps): update dependency discord-api-types to v0.38.17 [`#3620`](https://github.com/th-ch/youtube-music/pull/3620)
- chore(deps): update dependency esbuild to v0.25.8 [`#3675`](https://github.com/th-ch/youtube-music/pull/3675)
- chore(deps): update dependency @stylistic/eslint-plugin to v5.2.2 [`#3636`](https://github.com/th-ch/youtube-music/pull/3636)
- fix(deps): update dependency @hono/node-server to v1.17.1 [`#3625`](https://github.com/th-ch/youtube-music/pull/3625)
- fix(deps): update dependency hono to v4.8.7 [`#3567`](https://github.com/th-ch/youtube-music/pull/3567)
- chore(deps): update dependency typescript-eslint to v8.38.0 [`#3628`](https://github.com/th-ch/youtube-music/pull/3628)
- chore(deps): update dependency electron to v38.0.0-alpha.9 [`#3626`](https://github.com/th-ch/youtube-music/pull/3626)
- fix(Skip Disliked Song): updated querySelector [`#3667`](https://github.com/th-ch/youtube-music/pull/3667)
- chore(deps): update dependency vite to v7.0.11 [`#3624`](https://github.com/th-ch/youtube-music/pull/3624)
- fix(deps): update dependency @hono/zod-validator to v0.7.1 [`#3616`](https://github.com/th-ch/youtube-music/pull/3616)
- fix(discord-rpc, scrobbler): Align artist and title with the last.fm's de facto standard [`#3358`](https://github.com/th-ch/youtube-music/issues/3358) [`#3641`](https://github.com/th-ch/youtube-music/issues/3641)
- fix: fix #3621 (#3774) [`#3621`](https://github.com/th-ch/youtube-music/issues/3621)
- fix: fix #3661 [`#3661`](https://github.com/th-ch/youtube-music/issues/3661)
- fix: fix #3613, fix #3651 [`#3613`](https://github.com/th-ch/youtube-music/issues/3613) [`#3651`](https://github.com/th-ch/youtube-music/issues/3651)
- chore: remove unused deps [`2a81a4e`](https://github.com/th-ch/youtube-music/commit/2a81a4e887cb5cc3c91a672302db6da3c15544e8)
- chore(i18n): Translated using Weblate (Swedish) [`0a6f244`](https://github.com/th-ch/youtube-music/commit/0a6f244035f17724ab1934f3cb2e011adf838e09)
- fix: bump dependencies [`5ba65ea`](https://github.com/th-ch/youtube-music/commit/5ba65ea1221236478efa8cb61bca3ffb1bb2d061)
#### [v3.10.0](https://github.com/th-ch/youtube-music/compare/v3.9.0...v3.10.0)
> 13 July 2025
- fix(deps): update dependency butterchurn to v3.0.0-beta.5 [`#3610`](https://github.com/th-ch/youtube-music/pull/3610)
- chore(deps): update eslint monorepo to v9.31.0 [`#3600`](https://github.com/th-ch/youtube-music/pull/3600)
- chore(deps): update dependency rollup to v4.45.0 [`#3568`](https://github.com/th-ch/youtube-music/pull/3568)
- feat: code splitting [`#3593`](https://github.com/th-ch/youtube-music/pull/3593)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.11.1 [`#3571`](https://github.com/th-ch/youtube-music/pull/3571)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.11.1 [`#3570`](https://github.com/th-ch/youtube-music/pull/3570)
- chore(deps): update playwright monorepo to v1.54.1 [`#3599`](https://github.com/th-ch/youtube-music/pull/3599)
- chore(deps): update playwright monorepo to v1.54.0 [`#3591`](https://github.com/th-ch/youtube-music/pull/3591)
- chore(deps): update dependency electron to v37.2.1 [`#3559`](https://github.com/th-ch/youtube-music/pull/3559)
- fix(deps): update dependency socks to v2.8.6 [`#3598`](https://github.com/th-ch/youtube-music/pull/3598)
- fix(deps): update dependency zod to v4.0.5 [`#3594`](https://github.com/th-ch/youtube-music/pull/3594)
- chore(deps): update dependency vite to v7.0.8 [`#3597`](https://github.com/th-ch/youtube-music/pull/3597)
- chore(deps): update dependency vite to v7.0.7 [`#3590`](https://github.com/th-ch/youtube-music/pull/3590)
- chore(deps): update dependency @electron/universal to v3 [`#3565`](https://github.com/th-ch/youtube-music/pull/3565)
- fix(deps): update dependency electron-unhandled to v5 [`#2088`](https://github.com/th-ch/youtube-music/pull/2088)
- feat: enable the ESM for main [`#3588`](https://github.com/th-ch/youtube-music/pull/3588)
- fix(deps): update dependency zod to v4 [`#3587`](https://github.com/th-ch/youtube-music/pull/3587)
- feat: migrate from raw HTML to JSX (TSX / SolidJS) [`#3583`](https://github.com/th-ch/youtube-music/pull/3583)
- docs: add Unobtrusive Player in available plugins [`#3582`](https://github.com/th-ch/youtube-music/pull/3582)
- fix(deps): update dependency @hono/node-server to v1.15.0 [`#3557`](https://github.com/th-ch/youtube-music/pull/3557)
- chore(deps): update dependency vitefu to v1.1.1 [`#3564`](https://github.com/th-ch/youtube-music/pull/3564)
- chore(deps): update dependency discord-api-types to v0.38.15 [`#3562`](https://github.com/th-ch/youtube-music/pull/3562)
- fix(deps): update dependency es-hangul to v2.3.5 [`#3563`](https://github.com/th-ch/youtube-music/pull/3563)
- fix(deps): update dependency zod to v3.25.71 [`#3558`](https://github.com/th-ch/youtube-music/pull/3558)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.9.2 [`#3560`](https://github.com/th-ch/youtube-music/pull/3560)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.9.2 [`#3561`](https://github.com/th-ch/youtube-music/pull/3561)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.9.0 [`#3555`](https://github.com/th-ch/youtube-music/pull/3555)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.9.0 [`#3556`](https://github.com/th-ch/youtube-music/pull/3556)
- chore(deps): update eslint monorepo to v9.30.1 [`#3552`](https://github.com/th-ch/youtube-music/pull/3552)
- Fixed play/pause discord rich presence by fixing lastsonginfo tracking [`#3551`](https://github.com/th-ch/youtube-music/pull/3551)
- feat: enable rolldown native plugin [`#3502`](https://github.com/th-ch/youtube-music/pull/3502)
- fix(deps): update dependency virtua to v0.41.5 [`#3549`](https://github.com/th-ch/youtube-music/pull/3549)
- chore(deps): update dependency typescript-eslint to v8.35.1 [`#3545`](https://github.com/th-ch/youtube-music/pull/3545)
- chore(deps): update dependency discord-api-types to v0.38.14 [`#3546`](https://github.com/th-ch/youtube-music/pull/3546)
- chore(deps): update playwright monorepo to v1.53.2 [`#3547`](https://github.com/th-ch/youtube-music/pull/3547)
- fix(deps): update dependency i18next to v25.3.0 [`#3548`](https://github.com/th-ch/youtube-music/pull/3548)
- perf(synced-lyrics): virtual scrolling [`#3162`](https://github.com/th-ch/youtube-music/pull/3162)
- chore(deps): update dependency vite to v7 [`#3524`](https://github.com/th-ch/youtube-music/pull/3524)
- feat(synced-lyrics): Musixmatch [`#3261`](https://github.com/th-ch/youtube-music/pull/3261)
- feat(api-server): add optional params for search [`#3440`](https://github.com/th-ch/youtube-music/pull/3440)
- chore(deps): update dependency vite-plugin-inspect to v11.3.0 [`#3543`](https://github.com/th-ch/youtube-music/pull/3543)
- chore(deps): update eslint monorepo to v9.30.0 [`#3544`](https://github.com/th-ch/youtube-music/pull/3544)
- chore(deps): update dependency rollup to v4.44.1 [`#3537`](https://github.com/th-ch/youtube-music/pull/3537)
- chore(deps): update dependency ws to v8.18.3 [`#3538`](https://github.com/th-ch/youtube-music/pull/3538)
- fix(deps): update dependency @hono/zod-openapi to v0.19.9 [`#3540`](https://github.com/th-ch/youtube-music/pull/3540)
- fix(deps): update dependency @floating-ui/dom to v1.7.2 [`#3539`](https://github.com/th-ch/youtube-music/pull/3539)
- fix(deps): update dependency es-hangul to v2.3.4 [`#3541`](https://github.com/th-ch/youtube-music/pull/3541)
- fix(deps): update dependency hono to v4.8.3 [`#3542`](https://github.com/th-ch/youtube-music/pull/3542)
- fix(style): fix duplicated scrollbar [`#3483`](https://github.com/th-ch/youtube-music/pull/3483)
- chore(deps): update dependency typescript-eslint to v8.35.0 [`#3518`](https://github.com/th-ch/youtube-music/pull/3518)
- chore(deps): update dependency vite-plugin-solid to v2.11.7 [`#3520`](https://github.com/th-ch/youtube-music/pull/3520)
- chore(deps): update dependency discord-api-types to v0.38.13 [`#3517`](https://github.com/th-ch/youtube-music/pull/3517)
- chore(deps): update dependency eslint-import-resolver-typescript to v4.4.4 [`#3534`](https://github.com/th-ch/youtube-music/pull/3534)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.8.0 [`#3521`](https://github.com/th-ch/youtube-music/pull/3521)
- chore(deps): update dependency eslint-plugin-prettier to v5.5.1 [`#3535`](https://github.com/th-ch/youtube-music/pull/3535)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.8.0 [`#3522`](https://github.com/th-ch/youtube-music/pull/3522)
- chore(deps): update dependency electron to v37 [`#3527`](https://github.com/th-ch/youtube-music/pull/3527)
- feat: Add instructional note to Swagger documentation [`#3532`](https://github.com/th-ch/youtube-music/pull/3532)
- chore(deps): update playwright monorepo to v1.53.1 [`#3504`](https://github.com/th-ch/youtube-music/pull/3504)
- chore(deps): update dependency rollup to v4.44.0 [`#3508`](https://github.com/th-ch/youtube-music/pull/3508)
- chore(deps): update dependency eslint-plugin-import to v2.32.0 [`#3513`](https://github.com/th-ch/youtube-music/pull/3513)
- fix(deps): update dependency hono to v4.8.2 [`#3509`](https://github.com/th-ch/youtube-music/pull/3509)
- chore(deps): update dependency electron to v36.5.0 [`#3503`](https://github.com/th-ch/youtube-music/pull/3503)
- chore(deps): update stefanzweifel/git-auto-commit-action action to v6 [`#3500`](https://github.com/th-ch/youtube-music/pull/3500)
- chore(deps): update dependency vite to v6.3.21 [`#3492`](https://github.com/th-ch/youtube-music/pull/3492)
- fix(deps): update dependency hono to v4.8.0 [`#3499`](https://github.com/th-ch/youtube-music/pull/3499)
- chore(deps): update playwright monorepo to v1.53.0 [`#3497`](https://github.com/th-ch/youtube-music/pull/3497)
- chore(deps): update eslint monorepo to v9.29.0 [`#3496`](https://github.com/th-ch/youtube-music/pull/3496)
- chore(deps): update dependency vite-plugin-inspect to v11.2.0 [`#3495`](https://github.com/th-ch/youtube-music/pull/3495)
- fix(deps): update dependency happy-dom to v18 [`#3501`](https://github.com/th-ch/youtube-music/pull/3501)
- fix(deps): update dependency electron-store to v10.1.0 [`#3498`](https://github.com/th-ch/youtube-music/pull/3498)
- chore(deps): update dependency eslint-plugin-prettier to v5.5.0 [`#3493`](https://github.com/th-ch/youtube-music/pull/3493)
- chore(deps): update dependency rollup to v4.43.0 [`#3494`](https://github.com/th-ch/youtube-music/pull/3494)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.7.0 [`#3466`](https://github.com/th-ch/youtube-music/pull/3466)
- fix(deps): update dependency @hono/swagger-ui to v0.5.2 [`#3465`](https://github.com/th-ch/youtube-music/pull/3465)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.7.0 [`#3467`](https://github.com/th-ch/youtube-music/pull/3467)
- fix(deps): update dependency youtubei.js to v14 [`#3468`](https://github.com/th-ch/youtube-music/pull/3468)
- chore(deps): update dependency discord-api-types to v0.38.12 [`#3490`](https://github.com/th-ch/youtube-music/pull/3490)
- chore(deps): update dependency glob to v11.0.3 [`#3491`](https://github.com/th-ch/youtube-music/pull/3491)
- chore(deps): update dependency typescript-eslint to v8.34.1 [`#3469`](https://github.com/th-ch/youtube-music/pull/3469)
- fix(deps): update dependency socks to v2.8.5 [`#3470`](https://github.com/th-ch/youtube-music/pull/3470)
- fix(deps): update dependency zod to v3.25.67 [`#3471`](https://github.com/th-ch/youtube-music/pull/3471)
- chore(deps): update dependency @babel/runtime to v7.27.6 [`#3451`](https://github.com/th-ch/youtube-music/pull/3451)
- chore(deps): update dependency eslint-import-resolver-typescript to v4.4.3 [`#3453`](https://github.com/th-ch/youtube-music/pull/3453)
- fix(deps): update dependency zod to v3.25.56 [`#3454`](https://github.com/th-ch/youtube-music/pull/3454)
- fix(deps): update dependency @hono/node-server to v1.14.4 [`#3456`](https://github.com/th-ch/youtube-music/pull/3456)
- chore(deps): update dependency rollup to v4.42.0 [`#3457`](https://github.com/th-ch/youtube-music/pull/3457)
- fix(deps): update dependency conf to v14 [`#3458`](https://github.com/th-ch/youtube-music/pull/3458)
- fix(deps): update dependency peerjs to v1.5.5 [`#3460`](https://github.com/th-ch/youtube-music/pull/3460)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v4.4.1 [`#3444`](https://github.com/th-ch/youtube-music/pull/3444)
- chore(deps): update dependency discord-api-types to v0.38.11 [`#3445`](https://github.com/th-ch/youtube-music/pull/3445)
- chore(deps): update dependency electron to v36.4.0 [`#3447`](https://github.com/th-ch/youtube-music/pull/3447)
- fix(deps): update dependency zod to v3.25.51 [`#3446`](https://github.com/th-ch/youtube-music/pull/3446)
- fix(deps): update dependency hono to v4.7.11 [`#3435`](https://github.com/th-ch/youtube-music/pull/3435)
- fix(deps): update dependency @floating-ui/dom to v1.7.1 [`#3434`](https://github.com/th-ch/youtube-music/pull/3434)
- chore(deps): update dependency eslint-import-resolver-typescript to v4.4.2 [`#3432`](https://github.com/th-ch/youtube-music/pull/3432)
- chore(deps): update dependency eslint-plugin-prettier to v5.4.1 [`#3433`](https://github.com/th-ch/youtube-music/pull/3433)
- fix(deps): update dependency zod to v3.25.50 [`#3443`](https://github.com/th-ch/youtube-music/pull/3443)
- fix(deps): update dependency happy-dom to v17.6.3 [`#3438`](https://github.com/th-ch/youtube-music/pull/3438)
- fix(deps): update dependency zod to v3.25.49 [`#3436`](https://github.com/th-ch/youtube-music/pull/3436)
- chore(deps): update eslint monorepo to v9.28.0 [`#3437`](https://github.com/th-ch/youtube-music/pull/3437)
- fix(deps): update dependency @hono/zod-openapi to v0.19.8 [`#3411`](https://github.com/th-ch/youtube-music/pull/3411)
- fix: use gtk 3 switch as workaround [`#3366`](https://github.com/th-ch/youtube-music/pull/3366)
- chore(deps): update dependency electron to v36.3.2 [`#3431`](https://github.com/th-ch/youtube-music/pull/3431)
- fix(deps): update dependency @xhayper/discord-rpc to v1.2.2 [`#3413`](https://github.com/th-ch/youtube-music/pull/3413)
- fix(deps): update dependency happy-dom to v17.5.6 [`#3417`](https://github.com/th-ch/youtube-music/pull/3417)
- fix(deps): update dependency @hono/zod-validator to v0.7.0 [`#3414`](https://github.com/th-ch/youtube-music/pull/3414)
- chore(deps): update dependency discord-api-types to v0.38.10 [`#3430`](https://github.com/th-ch/youtube-music/pull/3430)
- chore(deps): update dependency typescript-eslint to v8.33.1 [`#3416`](https://github.com/th-ch/youtube-music/pull/3416)
- chore(docs): Improve README-es.md by adjusting the bad Spanish translation [`#3424`](https://github.com/th-ch/youtube-music/pull/3424)
- chore(docs): Improve README.md by removing the extra flag for Spanish translation [`#3422`](https://github.com/th-ch/youtube-music/pull/3422)
- chore(deps): update dependency @babel/runtime to v7.27.4 [`#3410`](https://github.com/th-ch/youtube-music/pull/3410)
- fix(deps): update dependency ts-morph to v26 [`#3409`](https://github.com/th-ch/youtube-music/pull/3409)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.6.1 [`#3407`](https://github.com/th-ch/youtube-music/pull/3407)
- fix(deps): update dependency zod to v3.25.30 [`#3408`](https://github.com/th-ch/youtube-music/pull/3408)
- fix(precise-volume): replace constructor check for volume slider [`#3362`](https://github.com/th-ch/youtube-music/pull/3362)
- chore(deps): update dependency vite-plugin-inspect to v11.1.0 [`#3393`](https://github.com/th-ch/youtube-music/pull/3393)
- chore(deps): update dependency eslint-import-resolver-typescript to v4.4.1 [`#3406`](https://github.com/th-ch/youtube-music/pull/3406)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v4.4.0 [`#3391`](https://github.com/th-ch/youtube-music/pull/3391)
- fix(deps): update dependency i18next to v25.2.1 [`#3405`](https://github.com/th-ch/youtube-music/pull/3405)
- chore(deps): update dependency esbuild to v0.25.5 [`#3403`](https://github.com/th-ch/youtube-music/pull/3403)
- fix(deps): update dependency @hono/node-server to v1.14.3 [`#3404`](https://github.com/th-ch/youtube-music/pull/3404)
- chore(deps): update dependency rollup to v4.41.1 [`#3392`](https://github.com/th-ch/youtube-music/pull/3392)
- chore(deps): update eslint monorepo to v9.27.0 [`#3394`](https://github.com/th-ch/youtube-music/pull/3394)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.6.1 [`#3395`](https://github.com/th-ch/youtube-music/pull/3395)
- fix(deps): update dependency hono to v4.7.10 [`#3390`](https://github.com/th-ch/youtube-music/pull/3390)
- chore(deps): update dependency eslint-import-resolver-typescript to v4.3.5 [`#3388`](https://github.com/th-ch/youtube-music/pull/3388)
- fix(deps): update dependency @hono/node-server to v1.14.2 [`#3389`](https://github.com/th-ch/youtube-music/pull/3389)
- chore(deps): update dependency electron to v36.3.1 [`#3372`](https://github.com/th-ch/youtube-music/pull/3372)
- chore(deps): update dependency typescript-eslint to v8.32.1 [`#3364`](https://github.com/th-ch/youtube-music/pull/3364)
- fix(deps): update dependency semver to v7.7.2 [`#3365`](https://github.com/th-ch/youtube-music/pull/3365)
- fix(album-actions): update playlist and button selectors [`#3367`](https://github.com/th-ch/youtube-music/pull/3367)
- fix(deps): update dependency i18next to v25.2.0 [`#3370`](https://github.com/th-ch/youtube-music/pull/3370)
- chore(deps): update dependency discord-api-types to v0.38.8 [`#3361`](https://github.com/th-ch/youtube-music/pull/3361)
- fix(deps): update dependency solid-js to v1.9.7 [`#3375`](https://github.com/th-ch/youtube-music/pull/3375)
- chore(deps): update dependency electron to v36 [`#3307`](https://github.com/th-ch/youtube-music/pull/3307)
- fix(deps): update dependency @floating-ui/dom to v1.7.0 [`#3357`](https://github.com/th-ch/youtube-music/pull/3357)
- chore(deps): update eslint monorepo to v9.26.0 [`#3356`](https://github.com/th-ch/youtube-music/pull/3356)
- chore(deps): update dependency eslint-plugin-prettier to v5.4.0 [`#3355`](https://github.com/th-ch/youtube-music/pull/3355)
- fix(deps): update dependency zod to v3.24.4 [`#3354`](https://github.com/th-ch/youtube-music/pull/3354)
- fix(deps): update dependency solid-js to v1.9.6 [`#3353`](https://github.com/th-ch/youtube-music/pull/3353)
- fix(deps): update dependency @ghostery/adblocker-electron-preload to v2.5.2 [`#3350`](https://github.com/th-ch/youtube-music/pull/3350)
- fix(deps): update dependency happy-dom to v17.4.7 [`#3352`](https://github.com/th-ch/youtube-music/pull/3352)
- fix(deps): update dependency @ghostery/adblocker-electron to v2.5.2 [`#3349`](https://github.com/th-ch/youtube-music/pull/3349)
- chore(deps): update dependency vite to v6.3.5 [`#3346`](https://github.com/th-ch/youtube-music/pull/3346)
- chore(deps): update dependency ws to v8.18.2 [`#3347`](https://github.com/th-ch/youtube-music/pull/3347)
- feat(plugin): support authenticated proxy [`#3175`](https://github.com/th-ch/youtube-music/pull/3175)
- chore(deps): update dependency esbuild to v0.25.4 [`#3344`](https://github.com/th-ch/youtube-music/pull/3344)
- chore(deps): update dependency eslint-config-prettier to v10.1.5 [`#3345`](https://github.com/th-ch/youtube-music/pull/3345)
- fix(deps): update dependency hono to v4.7.9 [`#3302`](https://github.com/th-ch/youtube-music/pull/3302)
- chore(deps): update dependency electron to v34.5.5 [`#3343`](https://github.com/th-ch/youtube-music/pull/3343)
- docs: Add Ukrainian translation [`#3338`](https://github.com/th-ch/youtube-music/pull/3338)
- chore(deps): update dependency discord-api-types to v0.38.4 [`#3342`](https://github.com/th-ch/youtube-music/pull/3342)
- chore(deps): update dependency rollup to v4.40.2 [`#3301`](https://github.com/th-ch/youtube-music/pull/3301)
- chore(deps): update dependency @electron/universal to v2.0.3 [`#3341`](https://github.com/th-ch/youtube-music/pull/3341)
- fix(deps): update dependency @hono/zod-validator to v0.5.0 [`#3295`](https://github.com/th-ch/youtube-music/pull/3295)
- chore(deps): update dependency @babel/runtime to v7.27.1 [`#3340`](https://github.com/th-ch/youtube-music/pull/3340)
- fix(deps): update dependency i18next to v25.1.2 [`#3305`](https://github.com/th-ch/youtube-music/pull/3305)
- fix(album-actions): use playlist shelf for playlist detection [`#3306`](https://github.com/th-ch/youtube-music/pull/3306)
- chore(deps): update dependency typescript-eslint to v8.32.0 [`#3304`](https://github.com/th-ch/youtube-music/pull/3304)
- chore(deps): update dependency vite to v6.3.4 [security] [`#3313`](https://github.com/th-ch/youtube-music/pull/3313)
- fix(deps): update dependency @hono/zod-openapi to v0.19.6 [`#3294`](https://github.com/th-ch/youtube-music/pull/3294)
- fix(deps): update dependency es-hangul to v2.3.3 [`#3293`](https://github.com/th-ch/youtube-music/pull/3293)
- fix(api-server): fix #3572 [`#3572`](https://github.com/th-ch/youtube-music/issues/3572)
- fix(youtube-music): fix #3296, and macOS traffic lights [`#3296`](https://github.com/th-ch/youtube-music/issues/3296)
- fix: kuromoji zlib and apply rolldown-vite [`f047dd2`](https://github.com/th-ch/youtube-music/commit/f047dd2d2df189b55b60188392c451aad65b7a1b)
- fix: apply fix from eslint [`1da83ff`](https://github.com/th-ch/youtube-music/commit/1da83ff27c2ccfcdf48c0b0b125033b1a1c194d2)
- feat: refactor [`51b3f53`](https://github.com/th-ch/youtube-music/commit/51b3f535695c0f19cd252049985578d11a853ccb)
#### [v3.9.0](https://github.com/th-ch/youtube-music/compare/v3.8.1...v3.9.0)
> 27 April 2025
- feat(tuna-obs): added alternativeTitle and tags to tuna [`#3288`](https://github.com/th-ch/youtube-music/pull/3288)
- fix: rollback electron version to v34 (for fix #3216) [`#3216`](https://github.com/th-ch/youtube-music/issues/3216)
- fix(synced-lyrics): fix #3157 [`#3157`](https://github.com/th-ch/youtube-music/issues/3157)

View File

@ -478,7 +478,7 @@
</a>
</li>
</ul>
<div class="footer-copyright">© 2024 th-ch</div>
<div class="footer-copyright">© 2025 th-ch</div>
</div>
</div>
</div>

View File

@ -21,7 +21,7 @@
</a>
</div>
Lestu þetta á öðrum tungumálum: [🏴 Ensku](../../README.md), [🇰🇷 Kóreska](./README-ko.md), [🇫🇷 Franska](./README-fr.md), [🇮🇸 Íslenskur](./README-is.md), [🇪🇸 Spænska](./README-es.md), [🇷🇺 Rússneska](./README-ru.md), [🇺🇦 Úkraínska](./README-uk.md), [🇧🇷 Portúgalska](./README-pt.md), [🇯🇵 Japanska](./README-ja.md)
Lestu þetta á öðrum tungumálum: [🏴 Enska](../../README.md), [🇰🇷 Kóreska](./README-ko.md), [🇫🇷 Franska](./README-fr.md), [🇮🇸 Íslenska](./README-is.md), [🇪🇸 Spænska](./README-es.md), [🇷🇺 Rússneska](./README-ru.md), [🇺🇦 Úkraínska](./README-uk.md), [🇧🇷 Portúgalska](./README-pt.md), [🇭🇺 Ungverska](./README-hu.md) [🇯🇵 Japanska](./README-ja.md)
**Electron umbúðir utan um YouTube Tónlist sem inniheldur:**

View File

@ -45,7 +45,7 @@ export default defineConfig({
formats: ['es'],
},
outDir: 'dist/main',
rollupOptions: {
rolldownOptions: {
external: ['electron', 'custom-electron-prompt', ...builtinModules],
input: './src/index.ts',
},
@ -96,7 +96,7 @@ export default defineConfig({
commonjsOptions: {
ignoreDynamicRequires: true,
},
rollupOptions: {
rolldownOptions: {
external: ['electron', 'custom-electron-prompt', ...builtinModules],
input: './src/preload.ts',
},
@ -149,7 +149,7 @@ export default defineConfig({
name: 'renderer',
},
outDir: 'dist/renderer',
rollupOptions: {
rolldownOptions: {
external: ['electron', ...builtinModules],
input: './src/index.html',
},

View File

@ -31,11 +31,19 @@ export default tsEslint.config(
rules: {
'stylistic/arrow-parens': ['error', 'always'],
'stylistic/object-curly-spacing': ['error', 'always'],
'stylistic/jsx-pascal-case': 'error',
'stylistic/jsx-curly-spacing': ['error', { when: 'never', children: true }],
'stylistic/jsx-sort-props': 'error',
'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',
'@typescript-eslint/consistent-type-imports': ['error', {
fixStyle: 'inline-type-imports',
prefer: 'type-imports',
disallowTypeAnnotations: false,
}],
'importPlugin/first': 'error',
'importPlugin/newline-after-import': 'off',
'importPlugin/no-default-export': 'off',

View File

@ -2,7 +2,7 @@
"name": "youtube-music",
"desktopName": "com.github.th_ch.youtube_music",
"productName": "YouTube Music",
"version": "3.9.0",
"version": "3.11.0",
"description": "YouTube Music Desktop App - including custom plugins",
"main": "./dist/main/index.js",
"type": "module",
@ -14,16 +14,16 @@
"url": "https://github.com/th-ch/youtube-music"
},
"scripts": {
"test": "playwright test",
"test:debug": "cross-env DEBUG=pw:*,-pw:test:protocol playwright test",
"build": "electron-vite build",
"test": "pnpm playwright test",
"test:debug": "pnpm cross-env DEBUG=pw:*,-pw:test:protocol playwright test",
"build": "pnpm electron-vite build",
"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": "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",
"start": "pnpm electron-vite preview",
"start:debug": "pnpm cross-env ELECTRON_ENABLE_LOGGING=1 pnpm start",
"dev": "pnpm cross-env NODE_ENV=development NODE_OPTIONS=--enable-source-maps electron-vite dev --watch",
"dev:renderer": "pnpm cross-env NODE_ENV=development NODE_OPTIONS=--enable-source-maps electron-vite dev",
"dev:debug": "pnpm cross-env ELECTRON_ENABLE_LOGGING=1 pnpm dev",
"clean": "pnpm del-cli dist && pnpm del-cli pack && pnpm del-cli .vite-inspect",
"dist": "pnpm clean && pnpm build && pnpm electron-builder --win --mac --linux -p never",
"dist:linux": "pnpm clean && pnpm build && pnpm electron-builder --linux -p never",
"dist:linux:deb-arm64": "pnpm clean && pnpm build && pnpm electron-builder --linux deb:arm64 -p never",
@ -32,12 +32,12 @@
"dist:mac:arm64": "pnpm clean && pnpm build && pnpm electron-builder --mac dmg:arm64 -p never",
"dist:win": "pnpm clean && pnpm build && pnpm electron-builder --win -p never",
"dist:win:x64": "pnpm clean && pnpm build && pnpm electron-builder --win nsis-web:x64 -p never",
"lint": "eslint .",
"changelog": "npx --yes auto-changelog",
"lint": "pnpm eslint ./src",
"changelog": "pnpm dlx auto-changelog",
"release:linux": "pnpm clean && pnpm build && pnpm electron-builder --linux -p always -c.snap.publish=github",
"release:mac": "pnpm clean && pnpm build && pnpm electron-builder --mac -p always",
"release:win": "pnpm clean && pnpm build && pnpm electron-builder --win -p always",
"typecheck": "tsc -p tsconfig.json --noEmit"
"typecheck": "pnpm tsc -p tsconfig.json --noEmit"
},
"engines": {
"node": ">=22",
@ -45,44 +45,46 @@
},
"pnpm": {
"overrides": {
"vite": "npm:rolldown-vite@7.0.8",
"node-gyp": "11.2.0",
"vite": "npm:rolldown-vite@7.1.8",
"node-gyp": "11.4.2",
"xml2js": "0.6.2",
"node-fetch": "3.3.2",
"@electron/universal": "3.0.0",
"@babel/runtime": "7.27.6",
"vitefu": "1.1.1"
"@electron/universal": "3.0.1",
"@babel/runtime": "7.28.4"
},
"patchedDependencies": {
"vudio@2.1.1": "patches/vudio@2.1.1.patch",
"@malept/flatpak-bundler@0.4.0": "patches/@malept__flatpak-bundler@0.4.0.patch",
"kuromoji@0.1.2": "patches/kuromoji@0.1.2.patch",
"file-type@16.5.4": "patches/file-type@16.5.4.patch"
"file-type@16.5.4": "patches/file-type@16.5.4.patch",
"electron-is@3.0.0": "patches/electron-is@3.0.0.patch"
},
"neverBuiltDependencies": []
},
"dependencies": {
"@dehoist/romanize-thai": "1.0.0",
"@electron-toolkit/tsconfig": "1.0.1",
"@electron/remote": "2.1.3",
"@ffmpeg.wasm/core-mt": "0.12.0",
"@ffmpeg.wasm/main": "0.12.0",
"@floating-ui/dom": "1.7.2",
"@floating-ui/dom": "1.7.4",
"@foobar404/wave": "2.0.5",
"@ghostery/adblocker-electron": "2.11.1",
"@ghostery/adblocker-electron-preload": "2.11.1",
"@hono/node-server": "1.15.0",
"@ghostery/adblocker-electron": "2.11.6",
"@ghostery/adblocker-electron-preload": "2.11.6",
"@hono/node-server": "1.19.1",
"@hono/node-ws": "1.2.0",
"@hono/swagger-ui": "0.5.2",
"@hono/zod-openapi": "0.19.9",
"@hono/zod-validator": "0.7.0",
"@hono/zod-openapi": "1.1.0",
"@hono/zod-validator": "0.7.2",
"@jellybrick/dbus-next": "0.10.3",
"@jellybrick/electron-better-web-request": "1.0.4",
"@jellybrick/mpris-service": "2.1.5",
"@jimp/plugin-color": "1.6.0",
"@skyra/jaro-winkler": "1.1.1",
"@xhayper/discord-rpc": "1.2.2",
"@xhayper/discord-rpc": "1.3.0",
"async-mutex": "0.5.0",
"bgutils-js": "3.2.0",
"butterchurn": "3.0.0-beta.4",
"butterchurn": "3.0.0-beta.5",
"butterchurn-presets": "3.0.0-beta.4",
"color": "5.0.0",
"conf": "14.0.0",
@ -100,12 +102,12 @@
"fast-equals": "5.2.2",
"fflate": "0.8.2",
"filenamify": "6.0.0",
"hanja": "1.1.4",
"hanja": "1.1.5",
"happy-dom": "18.0.1",
"hono": "4.8.4",
"hono": "4.9.7",
"howler": "2.2.4",
"html-to-text": "9.0.5",
"i18next": "25.3.2",
"i18next": "25.5.2",
"jimp": "1.6.0",
"keyboardevent-from-electron-accelerator": "2.0.0",
"keyboardevents-areequal": "0.2.2",
@ -116,65 +118,63 @@
"node-html-parser": "7.0.1",
"node-id3": "0.2.9",
"peerjs": "1.5.5",
"segmentit": "2.0.3",
"semver": "7.7.2",
"serve": "14.2.4",
"serve": "14.2.5",
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
"socks": "2.8.6",
"socks": "2.8.7",
"solid-element": "1.9.1",
"solid-floating-ui": "0.3.1",
"solid-js": "1.9.7",
"solid-js": "1.9.9",
"solid-styled-components": "0.28.5",
"solid-transition-group": "0.3.0",
"tiny-pinyin": "1.3.2",
"tinyld": "1.3.4",
"ts-morph": "26.0.0",
"virtua": "0.41.5",
"virtua": "0.42.3",
"vudio": "2.1.1",
"x11": "2.3.0",
"youtubei.js": "14.0.0",
"zod": "4.0.5"
"youtubei.js": "15.0.1",
"zod": "4.1.5"
},
"devDependencies": {
"@eslint/js": "9.30.1",
"@electron-toolkit/tsconfig": "1.0.1",
"@eslint/js": "9.35.0",
"@malept/flatpak-bundler": "0.4.0",
"@playwright/test": "1.54.1",
"@stylistic/eslint-plugin": "5.1.0",
"@playwright/test": "1.55.0",
"@stylistic/eslint-plugin": "5.3.1",
"@total-typescript/ts-reset": "0.6.1",
"@types/electron-localshortcut": "3.1.3",
"@types/howler": "2.2.12",
"@types/html-to-text": "9.0.4",
"@types/semver": "7.7.0",
"@types/semver": "7.7.1",
"@types/trusted-types": "2.0.7",
"bufferutil": "4.0.9",
"builtin-modules": "5.0.0",
"cross-env": "7.0.3",
"cross-env": "10.0.0",
"del-cli": "6.0.0",
"discord-api-types": "0.38.15",
"electron": "37.2.1",
"discord-api-types": "0.38.23",
"electron": "38.0.0",
"electron-builder": "26.0.12",
"electron-builder-squirrel-windows": "26.0.12",
"electron-devtools-installer": "4.0.0",
"electron-vite": "4.0.0",
"esbuild": "0.25.6",
"eslint": "9.30.1",
"eslint-config-prettier": "10.1.5",
"eslint": "9.35.0",
"eslint-config-prettier": "10.1.8",
"eslint-import-resolver-exports": "1.0.0-beta.5",
"eslint-import-resolver-typescript": "4.4.4",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-prettier": "5.5.1",
"eslint-plugin-prettier": "5.5.4",
"eslint-plugin-solid": "0.14.5",
"glob": "11.0.3",
"node-gyp": "11.2.0",
"playwright": "1.54.1",
"rollup": "4.44.2",
"typescript": "5.8.3",
"typescript-eslint": "8.36.0",
"node-gyp": "11.4.2",
"playwright": "1.55.0",
"ts-morph": "27.0.0",
"typescript": "5.9.2",
"typescript-eslint": "8.43.0",
"utf-8-validate": "6.0.5",
"vite": "npm:rolldown-vite@7.0.8",
"vite-plugin-inspect": "11.3.0",
"vite": "npm:rolldown-vite@7.1.8",
"vite-plugin-inspect": "11.3.3",
"vite-plugin-resolve": "2.5.2",
"vite-plugin-solid": "2.11.7",
"vite-plugin-solid": "2.11.8",
"ws": "8.18.3"
},
"auto-changelog": {

View File

@ -0,0 +1,27 @@
diff --git a/is.d.ts b/is.d.ts
index fb861f7b401914f0f89cb4edf25c51df5cb05812..82144733cd34d88e2deb2e4713b104418e673f2e 100644
--- a/is.d.ts
+++ b/is.d.ts
@@ -5,6 +5,7 @@ declare namespace is {
export function macOS(): boolean;
export function windows(): boolean;
export function linux(): boolean;
+ export function freebsd(): boolean;
export function x86(): boolean;
export function x64(): boolean;
export function production(): boolean;
diff --git a/is.js b/is.js
index a76bb1755a2728bde185b35d847031d3b8ea4ab0..f6b03406c17342f5af078de069e5bbbd2246e152 100644
--- a/is.js
+++ b/is.js
@@ -39,6 +39,10 @@ module.exports = {
linux: function () {
return process.platform === 'linux'
},
+ // Checks if we are under FreeBSD OS
+ freebsd: function () {
+ return process.platform === "freebsd"
+ },
// Checks if we are the processor's arch is x86
x86: function () {
return process.arch === 'ia32'

2884
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -31,14 +31,16 @@ export interface DefaultConfig {
likeButtons: string;
proxy: string;
startingPage: string;
backgroundMaterial?: 'none' | 'mica' | 'acrylic' | 'tabbed';
overrideUserAgent: boolean;
usePodcastParticipantAsArtist: boolean;
themes: string[];
customWindowTitle?: string;
};
'plugins': Record<string, unknown>;
}
const defaultConfig: DefaultConfig = {
export const defaultConfig: DefaultConfig = {
'window-size': {
width: 1100,
height: 550,
@ -72,5 +74,3 @@ const defaultConfig: DefaultConfig = {
},
'plugins': {},
};
export default defaultConfig;

View File

@ -1,30 +1,36 @@
import { deepmergeCustom } from 'deepmerge-ts';
import defaultConfig from './defaults';
import store, { IStore } from './store';
import plugins from './plugins';
import { store, type IStore } from './store';
import { restart } from '@/providers/app-controls';
import type { defaultConfig } from './defaults';
const deepmerge = deepmergeCustom({
mergeArrays: false,
});
const set = (key: string, value: unknown) => {
export { defaultConfig } from './defaults';
export * as plugins from './plugins';
export const set = (key: string, value: unknown) => {
store.set(key, value);
};
const setPartial = (key: string, value: object, defaultValue?: object) => {
export const setPartial = (
key: string,
value: object,
defaultValue?: object,
) => {
const newValue = deepmerge(defaultValue ?? {}, store.get(key) ?? {}, value);
store.set(key, newValue);
};
function setMenuOption(key: string, value: unknown) {
export const setMenuOption = (key: string, value: unknown) => {
set(key, value);
if (store.get('options.restartOnConfigChanges')) {
restart();
}
}
};
// MAGIC OF TYPESCRIPT
@ -74,18 +80,11 @@ type PathValue<T, K extends string> =
? PathValue<T[A], B>
: T;
const get = <Key extends Paths<typeof defaultConfig>>(key: Key) =>
export const get = <Key extends Paths<typeof defaultConfig>>(key: Key) =>
store.get(key) as PathValue<typeof defaultConfig, typeof key>;
export default {
defaultConfig,
get,
set,
setPartial,
setMenuOption,
edit: () => store.openInEditor(),
watch(cb: Parameters<IStore['onDidAnyChange']>[0]) {
store.onDidAnyChange(cb);
},
plugins,
export const edit = () => store.openInEditor();
export const watch = (cb: Parameters<IStore['onDidAnyChange']>[0]) => {
store.onDidAnyChange(cb);
};

View File

@ -1,7 +1,7 @@
import { deepmerge } from 'deepmerge-ts';
import { allPlugins } from 'virtual:plugins';
import store from './store';
import { store } from './store';
import { restart } from '@/providers/app-controls';
@ -68,13 +68,3 @@ export function enable(plugin: string) {
export function disable(plugin: string) {
setMenuOptions(plugin, { enabled: false }, []);
}
export default {
isEnabled,
getPlugins,
enable,
disable,
setOptions,
setMenuOptions,
getOptions,
};

View File

@ -1,6 +1,6 @@
import Store from 'electron-store';
import defaults from './defaults';
import { defaultConfig as defaults } from './defaults';
import { DefaultPresetList, type Preset } from '@/plugins/downloader/types';
@ -11,7 +11,7 @@ export type IStore = InstanceType<
>;
const migrations = {
'>=3.4.0'(store: IStore) {
'>=3.10.0'(store: IStore) {
const lyricGeniusConfig = store.get('plugins.lyrics-genius') as
| {
enabled?: boolean;
@ -23,10 +23,16 @@ const migrations = {
const syncedLyricsConfig = store.get('plugins.synced-lyrics') as
| SyncedLyricsPluginConfig
| undefined;
store.set('plugins.synced-lyrics', {
...syncedLyricsConfig,
enabled: lyricGeniusConfig.enabled,
});
if (
!syncedLyricsConfig ||
syncedLyricsConfig?.enabled !== lyricGeniusConfig?.enabled
) {
store.set('plugins.synced-lyrics', {
...syncedLyricsConfig,
enabled: lyricGeniusConfig.enabled,
});
}
store.delete('plugins.lyrics-genius');
}
@ -251,7 +257,7 @@ const migrations = {
},
};
export default new Store({
export const store = new Store({
defaults: {
...defaults,
// README: 'plugin' uses deepmerge to populate the default values, so it is not necessary to include it here

View File

@ -1,5 +1,5 @@
declare module 'custom-electron-prompt' {
import { BrowserWindow } from 'electron';
import { type BrowserWindow } from 'electron';
export type SelectOptions = Record<string, string>;

View File

@ -381,6 +381,11 @@
},
"templates": {
"title": "فتح محدد الترجمة"
},
"toast": {
"caption-changed": "تم تغيير الترجمة الى {{language}}",
"caption-disabled": "الترجمة معطلة",
"no-captions": "الترجمة لهاته الأغنية غير متاحة"
}
},
"compact-sidebar": {
@ -600,7 +605,15 @@
},
"navigation": {
"description": "أسهم التنقل \"التالي/السابق\" مدمجة مباشرة في الواجهة، كما في متصفحك",
"name": "التنقل"
"name": "التنقل",
"templates": {
"back": {
"title": "العودة إلى الصفحة السابقة"
},
"forward": {
"title": "إذهب إلى الصفحة المقبلة"
}
}
},
"no-google-login": {
"description": "إزالة أزرار وروابط تسجيل الدخول بجوجل من الواجهة",
@ -692,7 +705,12 @@
}
},
"description": "يسمح بتغيير جودة الفيديو باستخدام زر على صورة الفيديو",
"name": "مغير جودة الفيديو"
"name": "مغير جودة الفيديو",
"renderer": {
"quality-settings-button": {
"label": "إفتح مغير الجودة"
}
}
},
"scrobbler": {
"description": "إضافة دعم Scrobbling (مثل Last.fm، ListenBrainz)",
@ -859,7 +877,8 @@
},
"name": "تفعيل الفيديو",
"templates": {
"button-song": "أغنية"
"button-song": "أغنية",
"button-video": "فيديو"
}
},
"visualizer": {

View File

@ -1 +1,126 @@
{}
{
"common": {
"console": {
"plugins": {
"execute-failed": "Plagini icra etmək mümkün olmadı {{pluginName}}::{{contextName}}",
"executed-at-ms": "Plagin {{pluginName}}::{{contextName}} {{ms}} millisaniyədə icra edildi",
"initialize-failed": "\"{{pluginName}}\" plaginini başlatmaq mümkün olmadı",
"load-all": "Bütün plaginlər yüklənir",
"load-failed": "\"{{pluginName}}\" plaginini yükləmək mümkün olmadı",
"loaded": "\"{{pluginName}}\" plagini yükləndi",
"unload-failed": "\"{{pluginName}}\" plaqinini yükləmək mümkün olmadı",
"unloaded": "\"{{pluginName}}\" plaqini yükləmədən çıxarıldı"
}
}
},
"language": {
"code": "az",
"local-name": "Azərbaycan dili",
"name": "Azerbaijani"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "Yükləmə tamamlandı. DevTools açıldı"
},
"i18n": {
"loaded": "i18n yükləndi"
},
"second-instance": {
"receive-command": "Protokol üzərindən əmr alındı: \"{{command}}\""
},
"theme": {
"css-file-not-found": "CSS faylı \"{{cssFile}}\" mövcud deyil, nəzərə alınmır"
},
"unresponsive": {
"details": "Cavabsız Səhv!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Proqram keşi təmizlənir"
},
"window": {
"tried-to-render-offscreen": "Pəncərə ekran kənarında göstərilməyə çalışıldı, PəncərəÖlçüsü={{windowSize}}, EkranÖlçüsü={{displaySize}}, Vəziyyət={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "Menu gizlədildi, yenidən göstərmək üçün 'Alt' istifadə edin (Proqramiçi menu üçün 'Esc')",
"message": "Gizlət menusu aktivləşdirildi",
"title": "Gizlət menusu aktivləşdirildi"
},
"need-to-restart": {
"buttons": {
"later": "Sonra",
"restart-now": "Yenidən başlat"
},
"detail": "\"{{pluginName}}\" plaginin işləməsi üçün proqramı yenidən başladın",
"message": "\"{{pluginName}}\" üçün proqram yenidən başlamalıdır",
"title": "Yenidən başlatmaq tələb edilir"
},
"unresponsive": {
"buttons": {
"quit": "Tərk et",
"relaunch": "Yenidən işə sal",
"wait": "Gözləyin"
},
"detail": "Narahatçılıq üçün üzr istəyirik! Nə etməli olduğumuzu seçin:",
"message": "Proqram cavab vermir",
"title": "Pəncərə Cavab vermir"
},
"update-available": {
"buttons": {
"disable": "Yeniləmələri deaktiv et",
"download": "Yüklə",
"ok": "Oldu"
},
"detail": "Yeni versiya mövcuddur və bu linkdən yüklənə bilər {{downloadLink}}",
"message": "Yeni versiya mövcuddur",
"title": "Yeniləmə mövcuddur"
}
},
"menu": {
"about": "Haqqında",
"navigation": {
"label": "İstiqamət",
"submenu": {
"copy-current-url": "Hazırkı linki kopyala",
"go-back": "Geri qayıt",
"go-forward": "İrəli get",
"quit": ıx",
"restart": "Proqramı Yenidən Başlat"
}
},
"options": {
"label": "Seçimlər",
"submenu": {
"advanced-options": {
"label": "Əlavə seçimlər",
"submenu": {
"auto-reset-app-cache": "Proqram başlayanda keşi təmizlə",
"disable-hardware-acceleration": "Aparat təminatı sürətlənməsini deaktiv et",
"edit-config-json": "Config.json dəyiş",
"override-user-agent": "User-Agent dəyişdirildi",
"restart-on-config-changes": "Konfiqurasiya dəyişikliklərində yenidən başladılır",
"set-proxy": {
"label": "Proxy təyin et",
"prompt": {
"label": "Proxy Ünvanını daxil edin: (deaktiv etmək üçün boş buraxın)",
"placeholder": "Nümunə: SOCKS5://127.0.0.1:9999",
"title": "Proxy təyin et"
}
},
"toggle-dev-tools": "DevTools-u açıb bağla"
}
},
"always-on-top": "Həmişə üst tərəfdə",
"auto-update": "Avtomatik Yeniləmə",
"hide-menu": {
"dialog": {
"message": "Menu will be hidden on next launch, use [Alt] to show it (or backtick [`] if using in-app-menu)"
}
}
}
}
}
}
}

View File

@ -333,6 +333,30 @@
"description": "Прилага компресия на аудиото (намалява обема на най-силните части от сигнала и увеличава обема на най-тихите части)",
"name": "Аудио компресор"
},
"auth-proxy-adapter": {
"description": "Поддръжка за използване на услуги за удостоверяване чрез прокси",
"menu": {
"disable": "Деактивирай адаптера за удостоверяване чрез прокси",
"enable": "Активирай адаптера за удостоверяване чрез прокси",
"hostname": {
"label": "Име на хост"
},
"port": {
"label": "Порт"
}
},
"name": "Адаптер за удостоверяване чрез прокси",
"prompt": {
"hostname": {
"label": "Въведи име за локалния прокси сървър (необходимо е рестартиране):",
"title": "Име на прокси хост"
},
"port": {
"label": "Въведи порт за локалния прокси сървър (необходимо е рестартиране):",
"title": "Прокси порт"
}
}
},
"blur-nav-bar": {
"description": "Прави навигационната лента прозрачна и размазана",
"name": "Размазанa навигационна лента"
@ -357,6 +381,11 @@
},
"templates": {
"title": "Отвори избора на надписи"
},
"toast": {
"caption-changed": "Надписите са сменени на {{language}}",
"caption-disabled": "Надписите са деактивирани",
"no-captions": "Няма налични надписи за тази песен"
}
},
"compact-sidebar": {
@ -576,7 +605,15 @@
},
"navigation": {
"description": "Навигационни стрелки Напред/Назад, директно интегрирани в интерфейса, както в любимия ви браузър",
"name": "Навигация"
"name": "Навигация",
"templates": {
"back": {
"title": "Предишна страница"
},
"forward": {
"title": "Следваща страница"
}
}
},
"no-google-login": {
"description": "Премахни бутоните за вход с Google и връзките от интерфейса",
@ -601,7 +638,7 @@
"name": "Известия"
},
"performance-improvement": {
"description": "Подобри произдовителна като пуснеш опасни скриптове",
"description": "Подобри производителността като пуснеш експериментални скриптове",
"name": "Производителни подобрения"
},
"picture-in-picture": {
@ -668,7 +705,12 @@
}
},
"description": "Позволява промяна на качеството на видеото с бутон върху видеото",
"name": "Промяна на качеството на видеото"
"name": "Промяна на качеството на видеото",
"renderer": {
"quality-settings-button": {
"label": "Отвори настройките за качество на плейъра"
}
}
},
"scrobbler": {
"description": "Добавяне на скробблинг поддръжка (last.fm, Listenbrainz и т.н.)",
@ -835,7 +877,8 @@
},
"name": "Превключване на видео",
"templates": {
"button-song": "Песен"
"button-song": "Песен",
"button-video": "Видео"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "দৃষ্টিনন্দন পরিবর্তন",
"submenu": {
"custom-window-title": {
"label": "কাস্টম উইন্ডো টাইটেল",
"prompt": {
"label": "নিজস্ব উইন্ডোর টাইটেল দিন (বন্ধ করতে ফাঁকা রাখুন)",
"placeholder": "উদাহরণস্বরূপ: YouTube Music"
}
},
"like-buttons": {
"default": "ডিফল্ট লাইক বাটন",
"force-show": "সবসময় লাইক বাটন দেখান",
@ -381,6 +388,11 @@
},
"templates": {
"title": "ক্যাপশন নির্বাচক খুলুন"
},
"toast": {
"caption-changed": "ক্যাপশন {{language}} ভাষায় পরিবর্তিত হয়েছে",
"caption-disabled": "ক্যাপশন বন্ধ করা হয়েছে",
"no-captions": "এই গানটির জন্য কোনো ক্যাপশন উপলব্ধ নেই"
}
},
"compact-sidebar": {
@ -600,7 +612,15 @@
},
"navigation": {
"description": "পরবর্তী/পূর্ববর্তী নেভিগেশন তীরগুলি আপনার প্রিয় ব্রাউজারের মতো সরাসরি ইন্টারফেসে অন্তর্ভুক্ত করা হয়েছে",
"name": "নেভিগেশন"
"name": "নেভিগেশন",
"templates": {
"back": {
"title": "আগের পাতায় যান"
},
"forward": {
"title": "পরের পাতায় যান"
}
}
},
"no-google-login": {
"description": "ইন্টারফেস থেকে Google লগইন বাটন এবং লিঙ্কগুলি সরান",
@ -692,7 +712,12 @@
}
},
"description": "ভিডিও ওভারলেতে একটি বাটনের মাধ্যমে ভিডিও কোয়ালিটি পরিবর্তন করতে দেয়",
"name": "ভিডিও কোয়ালিটি পরিবর্তক"
"name": "ভিডিও কোয়ালিটি পরিবর্তক",
"renderer": {
"quality-settings-button": {
"label": "প্লেয়ারের মান পরিবর্তনের অপশন খুলুন"
}
}
},
"scrobbler": {
"description": "স্ক্রবলিং সমর্থন যোগ করুন (যেমন last.fm, Listenbrainz)",
@ -857,7 +882,11 @@
}
}
},
"name": "ভিডিও টগল"
"name": "ভিডিও টগল",
"templates": {
"button-song": "গান",
"button-video": "ভিডিও"
}
},
"visualizer": {
"description": "প্লেয়ারে একটি ভিজ্যুয়ালাইজার যোগ করে",

View File

@ -123,10 +123,79 @@
},
"language": {
"dialog": {
"message": "Jezik će se promijeniti nakon ponovnog pokretanja"
"message": "Jezik će se promijeniti nakon ponovnog pokretanja",
"title": "Jezik je uspješno promjenjen"
},
"label": "Jezik",
"submenu": {
"to-help-translate": "Želite da pomognete s prijevodom? Kliknite ovdje"
}
},
"resume-on-start": "Nastavi posljednju pjesmu pri sljedećem pokretaju",
"single-instance-lock": "Sprječavanje višestrukog pokretanja",
"start-at-login": "Pokreni čim se prijavite",
"starting-page": {
"label": "Početna stranica",
"unset": "Ukinite postavu"
},
"tray": {
"label": "Tacna",
"submenu": {
"disabled": "Onemogućeno",
"enabled-and-hide-app": "Tacna je uključena, i prozor aplikacije skrijte",
"enabled-and-show-app": "Tacna je uključena, i prozor aplikacije prikažite",
"play-pause-on-click": "Pokreni/Zaustavi na klik"
}
},
"visual-tweaks": {
"label": "Vizualne postavke",
"submenu": {
"custom-window-title": {
"label": "Prilagođeni naslov prozora",
"prompt": {
"label": "Unesite vlastiti naslov prozora: (ostavite prazno za isključenje)",
"placeholder": "Primjer: YouTube Music"
}
},
"like-buttons": {
"default": "Zadano",
"force-show": "Prinudno prikaži",
"hide": "Sakrij",
"label": "'Sviđa mi se' dugmadi"
},
"remove-upgrade-button": "Ukloni dugme za nadogradnju",
"theme": {
"dialog": {
"button": {
"cancel": "Otkaži",
"remove": "Ukloni"
},
"remove-theme": "Jeste li sigurni da želite ukloniti prilagođenu temu?",
"remove-theme-message": "Ovo će ukloniti prilagođenu temu"
},
"label": "Tema",
"submenu": {
"import-css-file": "Uvoz prilagođene CSS datoteke",
"no-theme": "Bez teme"
}
}
}
}
}
},
"plugins": {
"enabled": "Omogući",
"label": "Dodaci",
"new": "Novo"
}
}
},
"plugins": {
"ambient-mode": {
"menu": {
"quality": {
"label": "Kvalitet"
}
}
}
}

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Opcions visuals",
"submenu": {
"custom-window-title": {
"label": "Títol personalitzat de la finestra",
"prompt": {
"label": "Introdueix un títol personalitzat per a la finestra (deixa-ho buit per deshabilitar-ho)",
"placeholder": "Exemple: YouTube Music"
}
},
"like-buttons": {
"default": "Per defecte",
"force-show": "Força que es mostri",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Obra el selector de subtítols"
},
"toast": {
"caption-changed": "Subtítols canviats a {{language}}",
"caption-disabled": "Subtítols desactivats",
"no-captions": "Subtítols no disponibles per aquesta cançó"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Configura un dispositiu multimèdia de sortida personalitzat per a cançons",
"menu": {
"device-selector": "Selecciona un dispositiu"
},
"name": "Dispositiu de sortida personalitzat",
"prompt": {
"device-selector": {
"label": "Trieu el dispositiu de sortida que s'utilitzarà",
"title": "Escull el dispositiu de sortida"
}
}
},
"disable-autoplay": {
"description": "Fa que la cançó comenci en mode «pausat»",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "Amaga la durada restant",
"hide-github-button": "Amaga el botó de l'enllaç a GitHub",
"play-on-youtube-music": "Reprodueix a YouTube Music",
"set-inactivity-timeout": "Estableix temps d'espera d'inactivitat"
"set-inactivity-timeout": "Estableix temps d'espera d'inactivitat",
"set-status-display-type": {
"label": "Text d'estat",
"submenu": {
"artist": "Escoltant {artist}",
"title": "Escoltant {song title}",
"youtube-music": "Escoltant YouTube Music"
}
}
},
"name": "Estat d'activitat de Discord",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Fletxes de navegació Següent / Enrere integrades directament a la interfície, com al teu navegador preferit",
"name": "Navegació"
"name": "Navegació",
"templates": {
"back": {
"title": "Pàgina anterior"
},
"forward": {
"title": "Pàgina següent"
}
}
},
"no-google-login": {
"description": "Elimina els botons d'inici de sessió de Google de la interfície",
@ -692,7 +733,12 @@
}
},
"description": "Permet canviar la qualitat del vídeo amb un botó que s'hi mostra a sobre",
"name": "Botó de qualitat del vídeo"
"name": "Botó de qualitat del vídeo",
"renderer": {
"quality-settings-button": {
"label": "Obre les opcions de qualitat del reproductor"
}
}
},
"scrobbler": {
"description": "Afegeix suport per scrobbling (Last.fm, ListenBrainz, etc.)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "Introduir token d'usuari de ListenBrainz"
},
"scrobble-alternative-artist": "Utilitza artistes alternatius",
"scrobble-alternative-title": "Useu títols alternatius",
"scrobble-other-media": "Scrobble amb altres mitjans"
},
@ -796,6 +843,14 @@
"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)"
},
"preferred-provider": {
"label": "Proveïdor preferit",
"none": {
"label": "Cap",
"tooltip": "Cap proveïdor preferit"
},
"tooltip": "Trieu el proveïdor predeterminat que voleu utilitzar"
},
"romanization": {
"label": "Romanitza les lletres",
"tooltip": "Si les lletres són en un idioma diferent, intenta mostrar la versió amb alfabet llatí."
@ -828,6 +883,9 @@
"description": "Afegeix un giny a la Touch Bar per usuaris de macOS",
"name": "TouchBar"
},
"transparent-player": {
"description": "Fa la finestra de l'aplicació transparent"
},
"tuna-obs": {
"description": "Integració amb l'extensió «Tuna» del OBS",
"name": "Tuna OBS"
@ -859,7 +917,8 @@
},
"name": "Botó de vídeo",
"templates": {
"button-song": "Cançó"
"button-song": "Cançó",
"button-video": "Vídeo"
}
},
"visualizer": {

View File

@ -8,7 +8,7 @@
"load-all": "Načítání všech pluginů",
"load-failed": "Selhalo načtení \"{{pluginName}}\" pluginu",
"loaded": "Plugin \"{{pluginName}}\" načten",
"unload-failed": "Selhalo unload \"{{pluginName}}\" pluginu",
"unload-failed": "Selhalo vypnutí \"{{pluginName}}\" pluginu",
"unloaded": "Plugin {{pluginName}} byl odnačten"
}
}
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Vzhledové vylepšení",
"submenu": {
"custom-window-title": {
"label": "Vlastní název okna",
"prompt": {
"label": "Zadejte vlastní název okna: (zanechejte prázdné pro zakázání)",
"placeholder": "Příklad: Hudba YouTube"
}
},
"like-buttons": {
"default": "Výchozí",
"force-show": "Vynutit zobrazení",
@ -202,7 +209,7 @@
"show": "Zobrazit okno",
"tooltip": {
"default": "Youtube Music",
"with-song-info": "Youtube Music {{Umělec}} - {{Titul}}"
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
}
}
},
@ -220,7 +227,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": "Možnosti Albumu"
"name": "Možnosti Alba"
},
"album-color-theme": {
"description": "Používá dynamický motiv a vizuální efekty na základě palety barev alba",
@ -228,7 +235,7 @@
"color-mix-ratio": {
"label": "Poměr míchání barev",
"submenu": {
"percent": "{{poměr}}%"
"percent": "{{ratio}}%"
}
}
},
@ -280,7 +287,10 @@
"name": "Ambientní režim"
},
"amuse": {
"description": "Přídá YouTube Music podporu pro Amuse právě těď hraje widget od 6k Labs"
"description": "Přídá YouTube Music podporu pro Amuse právě hraje widget od 6K Labs",
"response": {
"query": "Server Amuse API běží. Pošli požadavek typu GET na /query, aby ses dozvěděl info o písničce."
}
},
"api-server": {
"description": "Vlož API server abys mohl ovládat přehrávač",
@ -302,7 +312,7 @@
"label": "Ověřit při prvním dotazu"
},
"none": {
"label": "Žádná autorizace"
"label": "Bez ověření"
}
}
},
@ -329,6 +339,29 @@
"description": "Apply compression k audiu (snižuje hlasitost nejhlasitěších částí signálu and zvyšuje hlasitost nejjemnějších částí)",
"name": "Audio kompresor"
},
"auth-proxy-adapter": {
"description": "Podpora pro použití ověřovacích proxy služeb",
"menu": {
"disable": "Vypnout Proxy Adaptér",
"enable": "Zapnout Proxy Adaptér",
"hostname": {
"label": "Hostname"
},
"port": {
"label": "Port"
}
},
"prompt": {
"hostname": {
"label": "Zadejte hostname lokálního proxy serveru (vyžaduje restart):",
"title": "Proxy Hostname"
},
"port": {
"label": "Zadejte port lokálního proxy serveru (vyžaduje restart):",
"title": "Proxy Port"
}
}
},
"blur-nav-bar": {
"description": "Udělá navigační panel průhledný a rozmazaný",
"name": "Rozmazaný navigační panel"
@ -353,6 +386,11 @@
},
"templates": {
"title": "Otevřít titulový selector"
},
"toast": {
"caption-changed": "Titulky změněny na {{language}}",
"caption-disabled": "Titulky vypnuty",
"no-captions": "K této skladbě nejsou titulky dostupné"
}
},
"compact-sidebar": {
@ -469,7 +507,7 @@
},
"submenu": {
"advanced": "Pokoročile",
"enabled": "Zapnuto",
"enabled": "Povoleno",
"mode": "Časový režim",
"percent": "Procent",
"seconds": "Sekundy"
@ -487,6 +525,18 @@
"button": "Stáhnout"
}
},
"equalizer": {
"description": "Přidá do přehrávače ekvalizér",
"menu": {
"presets": {
"label": "Předvolby",
"list": {
"bass-booster": "Zesílení basů"
}
}
},
"name": "Ekvalizér"
},
"exponential-volume": {
"description": "Dělá posuvník hlasitosti exponenciální, takže je snazší vybrat nižší hlasitost.",
"name": "Exponenciální hlasitost"
@ -513,7 +563,7 @@
}
},
"music-together": {
"description": "Sdílejte playlist s ostatními. Když hostitel přehrává písničku, uslyší jí i všichni ostatní.",
"description": "Sdílejte playlist s ostatními. Když hostitel přehrává skladbu, uslyší jí i všichni ostatní",
"dialog": {
"enter-host": "Zadejte Host ID"
},
@ -560,7 +610,15 @@
},
"navigation": {
"description": "Další/Zpátky navigační šipky přímo integrovány do rozhraní, jako ve vašem oblíbeném prohlížeči",
"name": "Navigace"
"name": "Navigace",
"templates": {
"back": {
"title": "Přejít na předchozí stránku"
},
"forward": {
"title": "Přejít na další stránku"
}
}
},
"no-google-login": {
"description": "Odstranit tlačítka Google přihlášení a odkazy z rozhraní",
@ -584,6 +642,9 @@
},
"name": "Oznámení"
},
"performance-improvement": {
"description": "Zlepšit výkon povolením experimentálních skriptů"
},
"picture-in-picture": {
"description": "Povoluje switch aplikaci do režimu obrázek v obrázku",
"menu": {
@ -648,7 +709,12 @@
}
},
"description": "Umožňuje měnit kvalitu videa pomocí tlačítka na video overlay",
"name": "Měnič kvality videa"
"name": "Měnič kvality videa",
"renderer": {
"quality-settings-button": {
"label": "Otevřít volbu kvality přehrávače"
}
}
},
"scrobbler": {
"description": "Přidat scrobbing podporu (např .last.fm , Listenbrainz)",
@ -667,6 +733,7 @@
"listenbrainz": {
"token": "Vložte Listenbrainz user token"
},
"scrobble-alternative-title": "Používat alternativní názvy",
"scrobble-other-media": "Scrobble jiné média"
},
"name": "Scrobbler",
@ -717,8 +784,8 @@
"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."
"fetch": "⚠️ Při hledání textu došlo k chybě.\n \tProsím zkuste to znovu později.",
"not-found": "⚠️ Pro tuto skladbu nebyl nalezen žádný text."
},
"menu": {
"default-text-string": {
@ -726,8 +793,36 @@
"tooltip": "Vyberte výchozí znak pro mezeru mezi texty"
},
"line-effect": {
"label": "Efekt řádku"
"label": "Efekt řádku",
"submenu": {
"offset": {
"label": "Posun"
}
}
},
"precise-timing": {
"tooltip": "Vypočítat zobrazení dalšího řádku na milisekundu (může mít menší dopad na výkon)"
},
"romanization": {
"label": "Romanizovat texty",
"tooltip": "Pokud je text v jiném jazyce, zkusit zobrazit verzi v latince."
},
"show-lyrics-even-if-inexact": {
"label": "Zobrazit i nepřesné texty"
},
"show-time-codes": {
"label": "Zobrazit časové kódy",
"tooltip": "Zobrazit časové kódy vedle textu"
}
},
"name": "Synchronizované texty",
"refetch-btn": {
"fetching": "Získávání..."
},
"warnings": {
"duration-mismatch": "⚠️ - Text nemusí být synchronizován kvůli neshodě v délce trvání.",
"inexact": "⚠️ - Text pro tuto skladbu nemusí být přesný",
"instrumental": "⚠️ - Tato skladba je instrumentální"
}
},
"taskbar-mediacontrol": {
@ -765,7 +860,8 @@
},
"name": "Přepínač videa",
"templates": {
"button-song": "Písnička"
"button-song": "Skladba",
"button-video": "Video"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Visuelle Optimierungen",
"submenu": {
"custom-window-title": {
"label": "Benutzerdefinierter Fenstertitel",
"prompt": {
"label": "Benutzerdefinierten Fenstertitel eingeben: (zum Deaktivieren leer lassen)",
"placeholder": "Beispiel: YouTube Music"
}
},
"like-buttons": {
"default": "Standard",
"force-show": "Zeigen erzwungen",
@ -345,7 +352,7 @@
"label": "Port"
}
},
"name": "Auth Proxy Adapter",
"name": "Authentifizierungs-Proxyadapter",
"prompt": {
"hostname": {
"label": "Hostnamen eingeben für lokalen Proxy-Server (Neustart erforderlich):",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Untertitelwähler öffnen"
},
"toast": {
"caption-changed": "Untertitel gewechselt zu {{language}}",
"caption-disabled": "Untertitel deaktiviert",
"no-captions": "Keine Untertitel für dieses Lied verfügbar"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Einen maßgeschneiderten Ausgabemedienträger für Lieder einrichten",
"menu": {
"device-selector": "Gerät auswählen"
},
"name": "Benutzerdefiniertes Ausgabegerät",
"prompt": {
"device-selector": {
"label": "Wähle das Ausgabegerät, welches benutzt werden soll",
"title": "Wähle ein Ausgabegerät"
}
}
},
"disable-autoplay": {
"description": "Startet Lied im pausierten Modus",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "Verbleibende Zeit verstecken",
"hide-github-button": "Knopf mit Link zu GitHub ausblenden",
"play-on-youtube-music": "Auf YouTube Music abspielen",
"set-inactivity-timeout": "Inaktivitätstimeout setzen"
"set-inactivity-timeout": "Inaktivitätstimeout setzen",
"set-status-display-type": {
"label": "Status Text",
"submenu": {
"artist": "Hört {artist} zu",
"title": "Du hörst {song title}",
"youtube-music": "Hört YouTube Music"
}
}
},
"name": "Discords Aktivitätsstatus",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Vorwärts/Zurück Navigationspfeile direkt in die Oberfläche integriert - wie in deinem geliebten Browser",
"name": "Navigation"
"name": "Navigation",
"templates": {
"back": {
"title": "Zur vorherigen Seite gehen"
},
"forward": {
"title": "Zur nächsten Seite gehen"
}
}
},
"no-google-login": {
"description": "Googles Anmelden-Knöpfe und -Links von der Oberfläche entfernen",
@ -692,7 +733,12 @@
}
},
"description": "Erlaubt die Videoqualität über einen Knopf auf dem Video",
"name": "Videoqualitätsänderer"
"name": "Videoqualitätsänderer",
"renderer": {
"quality-settings-button": {
"label": "Videoqualität ändern"
}
}
},
"scrobbler": {
"description": "Scrobbling-Unterstützung aktivieren (z.B. für last.fm, Listenbrainz)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "ListenBrainz-Benutzer-Token eintragen"
},
"scrobble-alternative-artist": "Benutze Alternative Künstler",
"scrobble-alternative-title": "Nutze alternative Titel",
"scrobble-other-media": "Andere Medien scrobbeln"
},
@ -796,6 +843,14 @@
"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)"
},
"preferred-provider": {
"label": "bevorzugter Anbieter",
"none": {
"label": "Nichts",
"tooltip": "Kein bevorzugter Anbieter"
},
"tooltip": "Standardanbieter auswählen"
},
"romanization": {
"label": "Lateinische Umschrift anzeigen",
"tooltip": "Wenn der Liedtext in einer anderen Schrift ist, zeige nach Möglichkeit eine Version in lateinischer Schrift an."
@ -828,6 +883,27 @@
"description": "Fügt ein TouchBar-Widget für macOS-Benutzer hinzu",
"name": "TouchBar"
},
"transparent-player": {
"description": "Macht das Player-Fenster transparent",
"menu": {
"opacity": {
"label": "Hintergrund-Sichtbarkeit",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Typ",
"submenu": {
"acrylic": "Acrylic",
"mica": "Mica",
"none": "Nichts",
"tabbed": "Tabbed"
}
}
},
"name": "Transparent Player"
},
"tuna-obs": {
"description": "Integration mit dem OBS-Plugin Tuna",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "Videoumschalter",
"templates": {
"button-song": "Lied"
"button-song": "Lied",
"button-video": "Video"
}
},
"visualizer": {

View File

@ -73,7 +73,7 @@
"download": "Λήψη",
"ok": "OK"
},
"detail": "Μια νέα έκδοση είναι διαθέσιμη και μπορεί να ληφθεί από τον σύνδεσμο {{downloadLink}}",
"detail": "Μια νέα έκδοση είναι διαθέσιμη και μπορεί να ληφθεί από το {{downloadLink}}",
"message": "Μια νέα έκδοση είναι διαθέσιμη",
"title": "Διατίθεται ενημέρωση"
}
@ -132,14 +132,14 @@
}
},
"resume-on-start": "Συνέχιση τελευταίου τραγουδιού όταν η εφαρμογή ξεκινά",
"single-instance-lock": "Κλείδωμα Μοναδικής Εκδοχής",
"start-at-login": "Έναρξη κατά την σύνδεση",
"single-instance-lock": "Κλείδωμα μοναδικής εκδοχής",
"start-at-login": "Έναρξη κατά τη σύνδεση",
"starting-page": {
"label": "Σελίδα έναρξης",
"label": "Αρχική σελίδα",
"unset": "Κατάργηση ορισμού"
},
"tray": {
"label": "Δίσκος",
"label": "Περιοχή συστήματος",
"submenu": {
"disabled": "Απενεργοποιημένο",
"enabled-and-hide-app": "Ενεργοποιημένο και απόκρυψη της εφαρμογής",
@ -148,8 +148,15 @@
}
},
"visual-tweaks": {
"label": "Τροποποιήσεις εμφάνισης",
"label": "Οπτικές προσαρμογές",
"submenu": {
"custom-window-title": {
"label": "Προσαρμοσμένος τίτλος παραθύρου",
"prompt": {
"label": "Εισαγωγή προσαρμοσμένου τίτλου παραθύρου: (κενό για απενεργοποίηση)",
"placeholder": "Παράδειγμα: YouTube Music"
}
},
"like-buttons": {
"default": "Προεπιλογή",
"force-show": "Επιβολή εμφάνισης",
@ -169,7 +176,7 @@
"label": "Θέμα",
"submenu": {
"import-css-file": "Εισαγωγή προσαρμοσμένου αρχείου CSS",
"no-theme": "Κανένα θέμα"
"no-theme": "Χωρίς θέμα"
}
}
}
@ -208,11 +215,11 @@
},
"plugins": {
"ad-speedup": {
"description": "Εάν παίξει διαφήμιση κάνει σίγαση του ήχου και θέτει την ταχύτητα αναπαραγωγής στο 16x",
"name": "Γρήγορη προώθηση διαφημίσεων"
"description": "Εάν ξεκινήσει διαφήμιση, ο ήχος απενεργοποιείται και η ταχύτητα αναπαραγωγής ορίζεται σε 16x",
"name": "Επιτάχυνση διαφημίσεων"
},
"adblocker": {
"description": "Αποκλεισμός όλων των διαφημίσεων και tracker",
"description": "Αποκλεισμός όλων των διαφημίσεων και της παρακολούθησης από προεπιλογή",
"menu": {
"blocker": "Πρόγραμμα αποκλεισμού"
},
@ -223,28 +230,28 @@
"name": "Ενέργειες σε Άλμπουμ"
},
"album-color-theme": {
"description": "Εφαρμόζει ένα δυναμικό θέμα και οπτικά εφέ με βάση τη χρωματική παλέτα του άλμπουμ",
"description": "Εφαρμόζει ένα δυναμικό θέμα και οπτικά εφέ βάσει της παλέτας χρωμάτων του άλμπουμ",
"menu": {
"color-mix-ratio": {
"label": "Αναλογία μίξης χρωμάτων",
"label": "Αναλογία ανάμειξης χρωμάτων",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Θέμα χρώματος άλμπουμ"
"name": "Θέμα χρωμάτων άλμπουμ"
},
"ambient-mode": {
"description": "Εφαρμόζει ένα εφέ φωτισμού ρίχνοντας απαλά χρώματα από το βίντεο στο φόντο της οθόνης σας",
"menu": {
"blur-amount": {
"label": "Ένταση θαμπώματος",
"label": "Ποσότητα θολώματος",
"submenu": {
"pixels": "{{blurAmount}} pixels"
}
},
"buffer": {
"label": "Buffer",
"label": "Ενδιάμεση μνήμη",
"submenu": {
"buffer": "{{buffer}}"
}
@ -270,18 +277,18 @@
"smoothness-transition": {
"label": "Ομαλή μετάβαση",
"submenu": {
"during": "Σε {{interpolationTime}} δευτερόλεπτα"
"during": "Για {{interpolationTime}} δευτερόλεπτα"
}
},
"use-fullscreen": {
"label": "Χρήση πλήρους οθόνης"
"label": "Σε πλήρη οθόνη"
}
},
"name": "Λειτουργία περιβάλλοντος"
},
"amuse": {
"description": "Προσθέτει υποστήριξη μουσικής YouTube για το widget Amuse now playing από την 6K Labs",
"name": "Διασκέδαση",
"description": "Προσθέτει υποστήριξη YouTube Music στο widget Amuse now playing από την 6K Labs",
"name": "Amuse",
"response": {
"query": "Ο διακομιστής Amuse API εκτελείται. GET /query για να λάβετε πληροφορίες για το τραγούδι."
}
@ -381,6 +388,11 @@
},
"templates": {
"title": "Ανοίξτε τον επιλογέα λεζάντας"
},
"toast": {
"caption-changed": "Λεζάντα άλλαξε σε {{language}}",
"caption-disabled": "Λεζάντες απενεργοποιήθηκαν",
"no-captions": "Λεζάντες μη διαθέσιμες για αυτό το τραγούδι"
}
},
"compact-sidebar": {
@ -600,7 +612,15 @@
},
"navigation": {
"description": "Βέλη πλοήγησης Επόμενο/Πίσω ενσωματωμένα απευθείας στο περιβάλλον εργασίας, όπως στο αγαπημένο σας πρόγραμμα περιήγησης",
"name": "Πλοήγηση"
"name": "Πλοήγηση",
"templates": {
"back": {
"title": "Μετάβαση στην προηγούμενη σελίδα"
},
"forward": {
"title": "Μετάβαση στην επόμενη σελίδα"
}
}
},
"no-google-login": {
"description": "Αφαίρεση των κουμπιών και των συνδέσμων σύνδεσης Google από το περιβάλλον εργασίας",
@ -692,7 +712,12 @@
}
},
"description": "Επιτρέπει την αλλαγή της ποιότητας βίντεο με ένα κουμπί στην επικάλυψη βίντεο",
"name": "Αλλαγή ποιότητας βίντεο"
"name": "Αλλαγή ποιότητας βίντεο",
"renderer": {
"quality-settings-button": {
"label": "Άνοιγμα ρυθμίσεων ποιότητας αναπαραγωγέα"
}
}
},
"scrobbler": {
"description": "Προσθήκη υποστήριξης scrobbling (κ.λπ. last.fm, Listenbrainz)",
@ -859,7 +884,8 @@
},
"name": "Εναλλαγή βίντεο",
"templates": {
"button-song": "Τραγούδι"
"button-song": "Τραγούδι",
"button-video": "Βίντεο"
}
},
"visualizer": {

View File

@ -156,6 +156,13 @@
"hide": "Hide",
"label": "Like buttons"
},
"custom-window-title": {
"label": "Custom window title",
"prompt": {
"label": "Enter custom window title: (leave empty to disable)",
"placeholder": "Example: YouTube Music"
}
},
"remove-upgrade-button": "Remove upgrade button",
"theme": {
"dialog": {
@ -334,7 +341,6 @@
"name": "Audio Compressor"
},
"auth-proxy-adapter": {
"name": "Auth Proxy Adapter",
"description": "Support for the use of authentication proxy services",
"menu": {
"disable": "Disable Proxy Adapter",
@ -346,14 +352,15 @@
"label": "Port"
}
},
"name": "Auth Proxy Adapter",
"prompt": {
"hostname": {
"title": "Proxy Hostname",
"label": "Enter hostname for local proxy server (requires restart):"
"label": "Enter hostname for local proxy server (requires restart):"
},
"port": {
"title": "Proxy Port",
"label": "Enter port for local proxy server (requires restart):"
"label": "Enter port for local proxy server (requires restart):"
}
}
},
@ -414,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Configure a custom output media device for songs",
"menu": {
"device-selector": "Select Device"
},
"name": "Custom Output Device",
"prompt": {
"device-selector": {
"label": "Choose the output media device to be used",
"title": "Select Output Device"
}
}
},
"disable-autoplay": {
"description": "Makes song start in \"paused\" mode",
"menu": {
@ -437,7 +457,15 @@
"hide-duration-left": "Hide duration left",
"hide-github-button": "Hide GitHub link Button",
"play-on-youtube-music": "Play on YouTube Music",
"set-inactivity-timeout": "Set inactivity timeout"
"set-inactivity-timeout": "Set inactivity timeout",
"set-status-display-type": {
"label": "Status text",
"submenu": {
"youtube-music": "Listening to YouTube Music",
"artist": "Listening to {artist}",
"title": "Listening to {song title}"
}
}
},
"name": "Discord Rich Presence",
"prompt": {
@ -704,13 +732,13 @@
}
}
},
"description": "Allows changing the video quality with a button on the video overlay",
"name": "Video Quality Changer",
"renderer": {
"quality-settings-button": {
"label": "Open player quality changer"
}
},
"description": "Allows changing the video quality with a button on the video overlay",
"name": "Video Quality Changer"
}
},
"scrobbler": {
"description": "Add scrobbling support (etc. last.fm, Listenbrainz)",
@ -730,6 +758,7 @@
"token": "Enter ListenBrainz user token"
},
"scrobble-alternative-title": "Use alternative titles",
"scrobble-alternative-artist": "Use alternative artists",
"scrobble-other-media": "Scrobble other media"
},
"name": "Scrobbler",
@ -784,6 +813,14 @@
"not-found": "⚠️ No lyrics found for this song."
},
"menu": {
"preferred-provider": {
"label": "Preferred Provider",
"tooltip": "Choose the default provider to use",
"none": {
"label": "None",
"tooltip": "No preferred provider"
}
},
"default-text-string": {
"label": "Default character between lyrics",
"tooltip": "Choose the default character to use for the gap between lyrics"
@ -846,6 +883,27 @@
"description": "Adds a TouchBar widget for macOS users",
"name": "TouchBar"
},
"transparent-player": {
"description": "Makes the app window transparent",
"name": "Transparent Player",
"menu": {
"opacity": {
"label": "Opacity",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Type",
"submenu": {
"acrylic": "Acrylic",
"mica": "Mica",
"tabbed": "Tabbed",
"none": "None"
}
}
}
},
"tuna-obs": {
"description": "Integration with OBS's plugin Tuna",
"name": "Tuna OBS"

View File

@ -2,14 +2,14 @@
"common": {
"console": {
"plugins": {
"execute-failed": "Error al ejecutar el plugin {{pluginName}}::{{contextName}}",
"executed-at-ms": "Plugin {{pluginName}}::{{contextName}} Ejecutó en {{ms}}ms",
"initialize-failed": "Error al inicializar el plugin \"{{pluginName}}\"",
"load-all": "Cargando todos los plugins",
"load-failed": "Error al cargar el plugin \"{{pluginName}}\"",
"loaded": "Plugin \"{{pluginName}}\" cargado",
"unload-failed": "No se ha podido descargar el plugin \"{{pluginName}}\"",
"unloaded": "Plugin \"{{pluginName}}\" descargado"
"execute-failed": "Error al ejecutar el complemento {{pluginName}}::{{contextName}}",
"executed-at-ms": "Complemento {{pluginName}}::{{contextName}} Ejecutó en {{ms}}ms",
"initialize-failed": "Error al inicializar el complemento \"{{pluginName}}\"",
"load-all": "Cargando todos los complementos",
"load-failed": "Error al cargar el complemento \"{{pluginName}}\"",
"loaded": "Complementos \"{{pluginName}}\" cargado",
"unload-failed": "No se ha podido descargar el complemento \"{{pluginName}}\"",
"unloaded": "Complemento \"{{pluginName}}\" descargado"
}
}
},
@ -45,15 +45,15 @@
"dialog": {
"hide-menu-enabled": {
"detail": "El menú está oculto, utiliza \"Alt\" para mostrarlo (o \"Escape\" si utilizas el menú integrado en la aplicación)",
"message": "Menú Oculto está habilitado",
"title": "Menú oculto habilitado"
"message": "El \"Menú Oculto\" está habilitado",
"title": "\"Menú oculto\" habilitado"
},
"need-to-restart": {
"buttons": {
"later": "Más tarde",
"restart-now": "Reiniciar ahora"
},
"detail": "El plugin \"{{pluginName}}\" requiere reiniciar para tomar efecto",
"detail": "El complemento \"{{pluginName}}\" requiere reiniciar para tomar efecto",
"message": "\"{{pluginName}}\" necesita reiniciar",
"title": "Se requiere reinicio"
},
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Ajustes visuales",
"submenu": {
"custom-window-title": {
"label": "Título de ventana personalizado",
"prompt": {
"label": "Ingresa un título de ventana personalizado: (déjalo vacío para desactivar)",
"placeholder": "Ejemplo: YouTube Music"
}
},
"like-buttons": {
"default": "Predeterminado",
"force-show": "Forzar la visualización",
@ -178,7 +185,7 @@
},
"plugins": {
"enabled": "Habilitado",
"label": "Plugins",
"label": "Complementos",
"new": "NUEVO"
},
"view": {
@ -381,6 +388,11 @@
},
"templates": {
"title": "Abrir el selector de subtítulos"
},
"toast": {
"caption-changed": "Subtítulos cambiados a {{language}}",
"caption-disabled": "Subtítulos desactivados",
"no-captions": "Sin subtítulos para ésta canción"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Configura un dispositivo de salida de audio personalizado para las canciones",
"menu": {
"device-selector": "Seleccionar un dispositivo"
},
"name": "Dispositivo de audio personalizado",
"prompt": {
"device-selector": {
"label": "Escoge el dispositivo de salida de audio que se va a usar",
"title": "Seleccionar un dispositivo de audio"
}
}
},
"disable-autoplay": {
"description": "Hace que la canción comience en modo \"pausado\"",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "Ocultar la duración restante",
"hide-github-button": "Ocultar el botón de enlace a GitHub",
"play-on-youtube-music": "Reproducir en YouTube Music",
"set-inactivity-timeout": "Establecer tiempo de inactividad"
"set-inactivity-timeout": "Establecer tiempo de inactividad",
"set-status-display-type": {
"label": "Texto de estado",
"submenu": {
"artist": "Escuchando a {artist}",
"title": "Escuchando {song title}",
"youtube-music": "Escuchando YouTube Music"
}
}
},
"name": "Discord Rich Presence",
"prompt": {
@ -457,7 +490,7 @@
"ok": "OK"
},
"detail": "({{playlistSize}} canciones)",
"message": "Descargando Playlist {{playlistTitle}}",
"message": "Descargando lista de reproducción {{playlistTitle}}",
"title": "Descarga iniciada"
}
},
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Flechas de navegación Siguiente/Atrás directamente integradas en la interfaz, como en tu navegador favorito",
"name": "Navegación"
"name": "Navegación",
"templates": {
"back": {
"title": "Volver a la página anterior"
},
"forward": {
"title": "Ir a la siguiente página"
}
}
},
"no-google-login": {
"description": "Eliminar los botones y enlaces de inicio de sesión de Google de la interfaz",
@ -692,7 +733,12 @@
}
},
"description": "Permite cambiar la calidad del vídeo con un botón sobre puesto en el vídeo",
"name": "Ajustador de calidad de vídeo"
"name": "Ajustador de calidad de vídeo",
"renderer": {
"quality-settings-button": {
"label": "Abrir selector de calidad del reproductor"
}
}
},
"scrobbler": {
"description": "Añadir soporte para scrobbling (last.fm, Listenbrainz, etc.)",
@ -711,8 +757,9 @@
"listenbrainz": {
"token": "Introduzca el token de usuario de ListenBrainz"
},
"scrobble-alternative-artist": "Usar artistas alternativos",
"scrobble-alternative-title": "Usar títulos alternativos",
"scrobble-other-media": "Scrobble en otros medios"
"scrobble-other-media": "Hacer Scrobble sobre otros medios"
},
"name": "Scrobbler",
"prompt": {
@ -762,8 +809,8 @@
"synced-lyrics": {
"description": "Proporciona letras de canciones sincronizadas, utilizando proveedores como LRClib.",
"errors": {
"fetch": "⚠️\tHa ocurrido un error al obtener la letra.\n\tPor favor, inténtalo de nuevo más tarde.",
"not-found": "⚠️ No se ha encontrado ninguna letra para esta canción."
"fetch": "⚠️\tSe produjo un error al obtener la letra.\n\tPor favor, inténtelo de nuevo más tarde.",
"not-found": "⚠️ No se han encontrado letras para esta canción."
},
"menu": {
"default-text-string": {
@ -796,6 +843,14 @@
"label": "Haz que la letra esté perfectamente sincronizada",
"tooltip": "Calcular al milisegundo la visualización de la siguiente línea (puede tener un pequeño impacto en el rendimiento)"
},
"preferred-provider": {
"label": "Proveedor preferido",
"none": {
"label": "Ninguno",
"tooltip": "Ningún proveedor preferido"
},
"tooltip": "Elige el proveedor predeterminado que deseas usar"
},
"romanization": {
"label": "Romanizar letras",
"tooltip": "Si la letra está en un idioma diferente, intenta mostrar una versión en latín."
@ -817,7 +872,7 @@
"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"
"instrumental": "⚠️ - Esta es una canción instrumental"
}
},
"taskbar-mediacontrol": {
@ -828,8 +883,29 @@
"description": "Añade un widget TouchBar para los usuarios de macOS",
"name": "TouchBar"
},
"transparent-player": {
"description": "Hace que la ventana de la aplicación sea transparente",
"menu": {
"opacity": {
"label": "Opacidad",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Tipo",
"submenu": {
"acrylic": "Acrílico",
"mica": "Mica",
"none": "Ninguno",
"tabbed": "Con pestañas"
}
}
},
"name": "Reproductor transparente"
},
"tuna-obs": {
"description": "Integración con el plugin Tuna de OBS",
"description": "Integración con el complemento Tuna de OBS",
"name": "Tuna OBS"
},
"unobtrusive-player": {
@ -859,7 +935,8 @@
},
"name": "Alternador de vídeo",
"templates": {
"button-song": "Canción"
"button-song": "Canción",
"button-video": "Vídeo"
}
},
"visualizer": {

View File

@ -0,0 +1,7 @@
{
"language": {
"code": "eu",
"local-name": "Euskara",
"name": "Basque"
}
}

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Visuaalisia tehosteita",
"submenu": {
"custom-window-title": {
"label": "Mukautettu ikkunan otsikko",
"prompt": {
"label": "Syötä mukautettu ikkunan otsikko: (jätä tyhjäksi poistaaksesi päältä)",
"placeholder": "Esimerkki: YouTube Music"
}
},
"like-buttons": {
"default": "Vakio",
"force-show": "Pakota näyttämään",
@ -280,7 +287,11 @@
"name": "Tunnelmallinen Tila"
},
"amuse": {
"description": "Lisää YouTube Music tuen Amusen nyt soitetaan -widgetille, kehittäjänä 6K Labs"
"description": "Lisää YouTube Music tuen Amusen nyt soitetaan -widgetille, kehittäjänä 6K Labs",
"name": "Amuse",
"response": {
"query": "Amuse API-palvelin on päällä. Käytä GET /query-rajapintaa saadaksesi kappaleen tiedot."
}
},
"api-server": {
"description": "Lisää API-palvelimen hallitsemaan soitinta",
@ -296,19 +307,31 @@
},
"menu": {
"auth-strategy": {
"label": "Valtuutus-strategia",
"submenu": {
"auth-at-first": {
"label": "Valtuuta ensimmäisellä kyselyllä"
},
"none": {
"label": "Ei valtuuksia"
}
}
},
"hostname": {
"label": "Isäntänimi"
},
"port": {
"label": "Portti"
}
},
"name": "API Serveri [Beta]",
"prompt": {
"hostname": {
"label": "Syötä isäntänimi (esimerkiksi 0.0.0.0) API-palvelimelle:",
"title": "Isäntänimi"
},
"port": {
"label": "Syötä API-palvelimen portti:",
"title": "Portti"
}
}
@ -317,6 +340,30 @@
"description": "Lisää äänen kompressointia (hiljentää voimakkaimpien äänien voimakkuutta ja tehostaa pehmeämpien äänien voimakkuutta)",
"name": "Äänen Kompressoija"
},
"auth-proxy-adapter": {
"description": "Tukee todennusvälipalvelinten käyttöä",
"menu": {
"disable": "Poista välipalvelimen adapteri pois käytöstä",
"enable": "Aseta välipalvelimen adapteri käyttöön",
"hostname": {
"label": "Isäntänimi"
},
"port": {
"label": "Portti"
}
},
"name": "Todennusvälipalvelinadapteri",
"prompt": {
"hostname": {
"label": "Syötä paikallisen välipalvelimen isäntänimi (vaatii uudelleenkäynnistyksen):",
"title": "Välipalvelimen isäntänimi"
},
"port": {
"label": "Syötä paikallisen välipalvelimen portti (vaatii uudelleenkäynnistyksen):",
"title": "Välipalvelimen portti"
}
}
},
"blur-nav-bar": {
"description": "Tekee siirtymäpalkista läpikuultavan ja sumean",
"name": "Sumenna Siirtymäpalkki"
@ -341,6 +388,11 @@
},
"templates": {
"title": "Avaa tekstitysten valitsin"
},
"toast": {
"caption-changed": "Tekstitys vaihdettu kieleksi {{language}}",
"caption-disabled": "Tekstitykset pois päältä",
"no-captions": "Tekstityksiä ei ole saatavilla tälle kappaleelle"
}
},
"compact-sidebar": {
@ -371,6 +423,9 @@
},
"disable-autoplay": {
"description": "Kappaleet alkavat \"pysäytetty\" tilassa",
"menu": {
"apply-once": "Käytetään vain käynnistäessä"
},
"name": "Poista automaattinen toisto käytöstä"
},
"discord": {
@ -446,12 +501,18 @@
"menu": {
"choose-download-folder": "Valitse latauskansio",
"download-finish-settings": {
"label": "Lataa toiston päätyttyä",
"prompt": {
"last-seconds": "Viimeiset x sekuntia"
"last-percent": "x prosentin jälkeen",
"last-seconds": "Viimeiset x sekuntia",
"title": "Määritä milloin ladata"
},
"submenu": {
"advanced": "Edistynyt",
"enabled": "Päällä",
"percent": "Prosentti"
"mode": "Aikatila",
"percent": "Prosentti",
"seconds": "Sekuntia"
}
},
"download-playlist": "Lataa soittolista",
@ -466,6 +527,18 @@
"button": "Lataa"
}
},
"equalizer": {
"description": "Lisää taajuuskorjaimen toistimeen",
"menu": {
"presets": {
"label": "Pohjat",
"list": {
"bass-booster": "Bassonlisääjä"
}
}
},
"name": "Taajuuskorjain"
},
"exponential-volume": {
"description": "Tekee äänenvoimakkuuden säätimestä eksponentiaalisen, jotta matalampien äänenvoimakkuuksien valinta on helpompaa.",
"name": "Eksponentiaalinen Äänenvoimakkuus"
@ -539,7 +612,15 @@
},
"navigation": {
"description": "Eteen- ja taaksepäin vievät nuolet suoraan integroituna käyttöliittymään. Juuri niin kuin lempiselaimessasi",
"name": "Siirtyminen"
"name": "Siirtyminen",
"templates": {
"back": {
"title": "Palaa edelliselle sivulle"
},
"forward": {
"title": "Siirry seuraavalle sivulle"
}
}
},
"no-google-login": {
"description": "Poista Googlen kirjautumispainikkeet ja linkit käyttöliittymästä",
@ -558,10 +639,15 @@
}
},
"priority": "Ilmoitusten tärkeys",
"toast-style": "Ponnahdusilmoitusten tyyli",
"unpause-notification": "Näytä ilmoitus toistamisen yhteydessä"
},
"name": "Ilmoitukset"
},
"performance-improvement": {
"description": "Paranna suorituskykyä käyttämällä kokeellisia skriptejä",
"name": "Suorituskykyparannus [Beta]"
},
"picture-in-picture": {
"description": "Sallii sovelluksen vaihtamisen \"kuva kuvassa\" tilaan",
"menu": {
@ -595,6 +681,7 @@
"precise-volume": {
"description": "Säädä äänenvoimakkuutta tarkasti hiiren rullaa tai pikanäppäimiä käyttäen. Kustomoidulla käyttöliittymällä ja säädettävällä äänenvoimakkuuden porrastuksella",
"menu": {
"arrows-shortcuts": "Paikallinen nuolinäppäinohjaus",
"custom-volume-steps": "Aseta mukautettu äänenvoimakkuuden porrastus",
"global-shortcuts": "Yleiset pikanäppäimet"
},
@ -605,7 +692,12 @@
"decrease": "Vähennä äänenvoimakkuutta",
"increase": "Lisää äänenvoimakkuutta"
},
"label": "Valitse yleiset äänenvoimakkuuden pikanäppäimet:"
"label": "Valitse yleiset äänenvoimakkuuden pikanäppäimet:",
"title": "Globaalit äänenvoimakkuusnäppäimet"
},
"volume-steps": {
"label": "Valitse äänenvoimakkuuden suurennus-/pienennysaskeleet",
"title": "Äänenvoimakkuusaskeleet"
}
}
},
@ -613,18 +705,52 @@
"backend": {
"dialog": {
"quality-changer": {
"detail": "Nykyinen laatu: {{quality}}"
"detail": "Nykyinen laatu: {{quality}}",
"message": "Valitse videon laatu:",
"title": "Valitse videon laatu"
}
}
},
"description": "Salli videon laadun muuttaminen videon päällä näkyvällä painikkeella",
"name": "Videonlaadunmuuttaja",
"renderer": {
"quality-settings-button": {
"label": "Avaa toistimen laadun muuttaja"
}
}
},
"scrobbler": {
"description": "Lisää jakamistuki (esim. last.fm, Listenbrainz)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Last.fm-varmennus epäonnistui\nPiilota ponnahdusikkuna kunnes käynnistät ohjelman uudelleen.",
"title": "Todennus epäonnistui"
}
}
},
"menu": {
"lastfm": {
"api-settings": "Last.fm API:n asetukset"
},
"listenbrainz": {
"token": "Syötä ListenBrainz-käyttötunnus (token)"
},
"scrobble-alternative-title": "Käytä vaihtoehtoisia otsikoita",
"scrobble-other-media": "Jaa muuta mediaa"
},
"name": "Jakaja",
"prompt": {
"lastfm": {
"api-key": "Last.fm:n API-avain",
"api-secret": "Last.fm:n API-salaisuus"
},
"listenbrainz": {
"token": {
"label": "Syötä ListenBrainz käyttötunnuksesi (token):",
"title": "ListenBrainz-käyttötunnus"
}
}
}
},
"shortcuts": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Mga Biswal na Tweak",
"submenu": {
"custom-window-title": {
"label": "Custom na window title",
"prompt": {
"label": "I-enter ang custom na window tile: (iwanang blanko para ma-disable)",
"placeholder": "Halimbawa: YouTube Music"
}
},
"like-buttons": {
"default": "Default",
"force-show": "Pilitang ipakita",
@ -378,6 +385,19 @@
}
}
},
"custom-output-device": {
"description": "I-configure ang custom na output media device para sa mga kanta",
"menu": {
"device-selector": "Pumili ng Device"
},
"name": "Custom na Output Device",
"prompt": {
"device-selector": {
"label": "Pumili ng output media device na gagamitin",
"title": "Pumili ng Output Device"
}
}
},
"disable-autoplay": {
"description": "Gawing simulan ang kanta sa \"naka-pause\" na mode",
"menu": {
@ -401,7 +421,14 @@
"hide-duration-left": "Itago ang natitirang oras",
"hide-github-button": "Itago ang button na GitHub link",
"play-on-youtube-music": "Patugtugin sa YouTube Music",
"set-inactivity-timeout": "I-set ang inactivity timeout"
"set-inactivity-timeout": "I-set ang inactivity timeout",
"set-status-display-type": {
"submenu": {
"artist": "Nakikinig sa {artist}",
"title": "Nakikinig sa {song title}",
"youtube-music": "Kumikinig sa YouTube Music"
}
}
},
"prompt": {
"set-inactivity-timeout": {
@ -649,6 +676,7 @@
"listenbrainz": {
"token": "Ilagay ang user token ng ListenBrainz"
},
"scrobble-alternative-artist": "Gumamit ng mga alternatibong artist",
"scrobble-alternative-title": "Gumamit ng alternatibong mga title",
"scrobble-other-media": "Mag-Scrobble ng ibang media"
},
@ -728,6 +756,14 @@
"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)"
},
"preferred-provider": {
"label": "Napiling Provider",
"none": {
"label": "Wala",
"tooltip": "Walang napiling provider"
},
"tooltip": "Pumili ng default na provider para gagamitin"
},
"romanization": {
"label": "I-romanize ang lyrics",
"tooltip": "Kung ang lyrics ay nasa ibang wika, subukang magpakita ng latin na bersyon."
@ -758,6 +794,19 @@
"touchbar": {
"description": "Idaragdag ang TouchBar na widget para sa mga user ng macOS"
},
"transparent-player": {
"description": "Gawing transparent ang app window",
"menu": {
"type": {
"label": "Uri",
"submenu": {
"none": "Wala",
"tabbed": "Naka-tab"
}
}
},
"name": "Transparent na Player"
},
"tuna-obs": {
"description": "Integrasyon kasama ang Tuna na OBS plugin"
},

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Ajustements visuels",
"submenu": {
"custom-window-title": {
"label": "Titre de fenêtre personnalisé",
"prompt": {
"label": "Entrés un titre de fenêtre : (Laissé vide pour déactiver)",
"placeholder": "Exemple : YouTube Musique"
}
},
"like-buttons": {
"default": "Par défaut",
"force-show": "Forcer à apparaître",
@ -280,7 +287,7 @@
"name": "Mode ambiant"
},
"amuse": {
"description": "Ajoute la prise en charge de YouTube Music pour le widget de lecture en cours Amuse par 6K Labs",
"description": "Ajout de la prise en charge de YouTube Music pour le widget Amuse now playing de 6K Labs",
"name": "Amuse",
"response": {
"query": "Le serveur API Amuse est en cours d'exécution. Envoyez une requête GET /query pour obtenir des informations sur la chanson."
@ -320,11 +327,11 @@
"name": "Serveur API [Beta]",
"prompt": {
"hostname": {
"label": "Entrer le nom de l'hôte (par exemple 0.0.0.0) pour le serveur API:",
"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": "Entrez le port du serveur de l'API:",
"label": "Entrez le port du serveur de l'API :",
"title": "Port"
}
}
@ -381,6 +388,11 @@
},
"templates": {
"title": "Ouvrir le sélecteur de sous-titres"
},
"toast": {
"caption-changed": "Sous-titres changés en {{language}}",
"caption-disabled": "Sous-titres désactivés",
"no-captions": "Aucun sous-titre disponible pour cette chanson"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Configurer un périphérique de sortie personnalisé pour les morceaux",
"menu": {
"device-selector": "Sélectionner un appareil"
},
"name": "Périphérique de sortie personnalisé",
"prompt": {
"device-selector": {
"label": "Choisissez le périphérique de sortie à utiliser",
"title": "Sélectionner le périphérique de sortie"
}
}
},
"disable-autoplay": {
"description": "Fait démarrer la chanson en mode \"pause\"",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "Masquer la durée restante",
"hide-github-button": "Masquer le bouton du lien GitHub",
"play-on-youtube-music": "Jouer sur YouTube Music",
"set-inactivity-timeout": "Définir le délai d'inactivité"
"set-inactivity-timeout": "Définir le délai d'inactivité",
"set-status-display-type": {
"label": "Texte d'état",
"submenu": {
"artist": "Écoute {artiste}",
"title": "Écoute {titre de la chanson}",
"youtube-music": "Écoute YouTube Music"
}
}
},
"name": "Discord Rich Presence",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Flèches de navigation Suivant/Retour directement intégrées dans l'interface, comme dans votre navigateur préféré",
"name": "Navigation"
"name": "Navigation",
"templates": {
"back": {
"title": "Revenir à la page précédente"
},
"forward": {
"title": "Aller à la page suivante"
}
}
},
"no-google-login": {
"description": "Supprimer les boutons et liens de connexion Google de l'interface",
@ -692,7 +733,12 @@
}
},
"description": "Permet de changer la qualité vidéo avec un bouton sur la vidéo",
"name": "Changeur de qualité vidéo"
"name": "Changeur de qualité vidéo",
"renderer": {
"quality-settings-button": {
"label": "Ouvrir le sélecteur de qualité du lecteur"
}
}
},
"scrobbler": {
"description": "Ajouter le support de scrobbling (ex. last.fm, Listenbrainz)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "Entrer le token utilisateur de ListenBrainz"
},
"scrobble-alternative-artist": "Utilisez d'autres artistes",
"scrobble-alternative-title": "Utiliser des titres alternatifs",
"scrobble-other-media": "Scrobbler d'autres médias"
},
@ -796,6 +843,14 @@
"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)"
},
"preferred-provider": {
"label": "Fournisseur privilégié",
"none": {
"label": "Aucun",
"tooltip": "Aucun fournisseur privilégié"
},
"tooltip": "Choisissez le fournisseur par défaut à utiliser"
},
"romanization": {
"label": "Romaniser les paroles",
"tooltip": "Si les paroles sont dans une autre langue, essayez de les afficher dans une version latine."
@ -828,6 +883,27 @@
"description": "Ajoute un widget TouchBar pour les utilisateurs de macOS",
"name": "TouchBar"
},
"transparent-player": {
"description": "Rend la fenêtre de l'application transparente",
"menu": {
"opacity": {
"label": "Opacité",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Type",
"submenu": {
"acrylic": "Acrylique",
"mica": "Mica",
"none": "Aucun",
"tabbed": "À onglets"
}
}
},
"name": "Lecteur transparent"
},
"tuna-obs": {
"description": "Intégration avec le plugin OBS Tuna",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "Basculer la vidéo",
"templates": {
"button-song": "Musique"
"button-song": "Musique",
"button-video": "Vidéo"
}
},
"visualizer": {

View File

@ -1,7 +1,60 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "Error ao executar o plugin {{pluginName}}::{{contextName}}",
"executed-at-ms": "O plugin {{pluginName}}::{{contextName}} foi executado a {{ms}}milisegundos",
"initialize-failed": "Erro ao iniciar o plugin \"{{pluginName}}\"",
"load-all": "Cargando todos os plugins",
"load-failed": "Erro ao cargar o plugin \"{{pluginName}}\"",
"loaded": "Plugin \"{{pluginName}}\" cargado",
"unload-failed": "Erro descargando o plugin {{pluginName}}",
"unloaded": "Plugin {{pluginName}} decargado"
}
}
},
"language": {
"code": "gl",
"local-name": "Galego",
"name": "Galician"
"name": "Galego"
},
"main": {
"console": {
"did-finish-load": {
"dev-tools": "Carga completada. DevTools aberto"
},
"i18n": {
"loaded": "i18n cargado"
},
"second-instance": {
"receive-command": "Recibido comando sobre protocolo \"{{command}}\""
},
"theme": {
"css-file-not-found": "O arquivo CSS \"{{cssFile}}\" non existe, ignorando"
},
"unresponsive": {
"details": "Error irresponsivo!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Limpando a caché da app"
},
"window": {
"tried-to-render-offscreen": "A ventana tentou de renderizarse fora da pantalla, windowSize={{windowSize}}, displaySize={{displaySize}}, position={{position}}"
}
},
"dialog": {
"hide-menu-enabled": {
"detail": "O menú está agochado, use 'Alt' para mostralo (ou 'Escape' se usa o menú dentro da app)",
"message": "Esconder Menú está deshabilitado",
"title": "Esconder Menú Habilitado"
},
"need-to-restart": {
"buttons": {
"later": "Despois",
"restart-now": "Reiniciar Agora"
},
"detail": "O plugin \"{{pluginName}}\" precisa dun reinicio para tomar efecto"
}
}
}
}

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "दृश्य परिवर्तन",
"submenu": {
"custom-window-title": {
"label": "कस्टम विंडो टाइटल",
"prompt": {
"label": "कस्टम विंडो टाइटल डालें: (डिसएबल करने के लिए खाली छोड़ें)",
"placeholder": "उदाहरण: यूट्यूब संगीत"
}
},
"like-buttons": {
"default": "डिफॉल्ट",
"force-show": "बल पूर्वक दिखाएं",
@ -381,6 +388,11 @@
},
"templates": {
"title": "कैप्शन चयनकर्ता खोलें"
},
"toast": {
"caption-changed": "कैप्शन {{language}} में बदल दिया गया है",
"caption-disabled": "कैप्शन बंद कर दिए गए हैं",
"no-captions": "इस गाने के लिए कोई कैप्शन उपलब्ध नहीं हैं"
}
},
"compact-sidebar": {
@ -477,7 +489,7 @@
"playlist-has-only-one-song": "प्लेलिस्ट में केवल एक आइटम है, इसे सीधे डाउनलोड करें",
"playlist-id-not-found": "कोई प्लेलिस्ट आईडी नहीं मिली",
"playlist-is-empty": "प्लेलिस्ट ख़ाली है",
"playlist-is-mix-or-private": "प्लेलिस्ट जानकारी प्राप्त करने में दिक्कत: सुनिश्चित करें कि यह निजी या \"आपके लिए मिश्रित\" प्लेलिस्ट नहीं है\n\n{{त्रुटि}}",
"playlist-is-mix-or-private": "प्लेलिस्ट जानकारी प्राप्त करने में दिक्कत: सुनिश्चित करें कि यह निजी या \"आपके लिए मिश्रित\" प्लेलिस्ट नहीं है\n\n{{error}}",
"preparing-file": "फ़ाइल तैयार की जा रही है…",
"saving": "सेव जा रहा है…",
"trying-to-get-playlist-id": "प्लेलिस्ट आईडी प्राप्त करने का प्रयास किया जा रहा है: {{playlistId}}",
@ -525,7 +537,7 @@
}
}
},
"name": "क्वलाइज़र"
"name": "क्विलाइज़र"
},
"exponential-volume": {
"description": "वॉल्यूम स्लाइडर को घातांकीय बनाता है ताकि कम वॉल्यूम का चयन करना आसान हो।",
@ -600,7 +612,15 @@
},
"navigation": {
"description": "आगे /पीछे नेविगेशन अर्रोस सीधे इंटरफ़ेस में एकीकृत, जैसे आपके पसंदीदा ब्राउज़र में",
"name": "नेविगेशन"
"name": "नेविगेशन",
"templates": {
"back": {
"title": "पिछले पेज पर जाएं"
},
"forward": {
"title": "अगले पेज पर जाएं"
}
}
},
"no-google-login": {
"description": "इंटरफ़ेस से गूगल लॉगिन बटन और लिंक हटाएँ",
@ -692,7 +712,12 @@
}
},
"description": "वीडियो ओवरले पर एक बटन के साथ वीडियो की गुणवत्ता बदलने की अनुमति देता है",
"name": "वीडियो गुणवत्ता परिवर्तक"
"name": "वीडियो गुणवत्ता परिवर्तक",
"renderer": {
"quality-settings-button": {
"label": "प्लेयर क्वालिटी सेटिंग खोलें"
}
}
},
"scrobbler": {
"description": "स्क्रोब्लिंग सपोर्ट जोड़ें (etc. last.fm, listenbrainz)",
@ -728,6 +753,37 @@
}
}
},
"shortcuts": {
"description": "प्लेबैक (प्ले/पॉज़/नेक्स्ट/प्रीवियस) के लिए ग्लोबल हॉटकी सेट करने की सुविधा देता है, मीडिया कुंजियों को ओवरराइड करके मीडिया OSD बंद करता है, Ctrl/CMD + F से खोज चालू करता है, Linux में मीडिया कुंजियों के लिए MPRIS सपोर्ट चालू करता है, और उन्नत उपयोगकर्ताओं के लिए कस्टम हॉटकी की अनुमति देता है",
"menu": {
"override-media-keys": "मीडिया कुंजियों पर नियंत्रण प्राप्त करें",
"set-keybinds": "वैश्विक गीत नियंत्रण सेट करें"
},
"name": "शॉर्टकट कुंजियाँ (और MPRIS)",
"prompt": {
"keybind": {
"keybind-options": {
"next": "अगला",
"play-pause": "चलाएं / विराम दें",
"previous": "पिछला"
},
"label": "गाने कंट्रोल करने के लिए ग्लोबल कीबाइंड का चयन करें:",
"title": "ग्लोबल कीबाइंडस"
}
}
},
"skip-disliked-songs": {
"description": "डिसलाइकड गानो को स्किप करता है",
"name": "डिसलाइकड गानो को स्किप करें"
},
"skip-silences": {
"description": "साइलेंट सेक्शन को ऑटोमेटिकली स्किप करें",
"name": "साइलेंस स्किप करें"
},
"sponsorblock": {
"description": "Intro/Outro जैसे गैर-संगीत भागों को स्किप करता है",
"name": "SponsorBlock"
},
"video-toggle": {
"menu": {
"align": {

View File

@ -381,6 +381,11 @@
},
"templates": {
"title": "Otvori izbornik za titlove"
},
"toast": {
"caption-changed": "Titlovi su promenjeni u {{language}}",
"caption-disabled": "Titlovi su isključeni",
"no-captions": "Za ovu pjesmu nisu dostupni titlovi"
}
},
"compact-sidebar": {
@ -600,7 +605,15 @@
},
"navigation": {
"description": "Naprijed/Nazad navigacijske strelice su izravno integrirane u sučelje, kao i u vašem omiljenom pregledniku",
"name": "Navigacija"
"name": "Navigacija",
"templates": {
"back": {
"title": "Vrati se na prijethodnu stranicu"
},
"forward": {
"title": "Idi na sljedeću stranicu"
}
}
},
"no-google-login": {
"description": "Ukloni Google prijavne gumbe i linkove iz sučelja",
@ -627,6 +640,253 @@
"performance-improvement": {
"description": "Poboljšati performanse uključivanjem eksperimentalnih skripti",
"name": "Poboljšanje performansa (Beta)"
},
"picture-in-picture": {
"description": "Dozvoljava aplikaciji da se prebaci u režim slike-u-slici",
"menu": {
"always-on-top": "Uvijek na vrhu",
"hotkey": {
"label": "Prečac",
"prompt": {
"keybind-options": {
"hotkey": "Prečac"
},
"label": "Odaberi prečac za prebacivanje u režim slike-u-slici",
"title": "Prečac za režim slike-u-slici"
}
},
"save-window-position": "Sačuvaj mjesto prozora",
"save-window-size": "Sačuvaj veličinu prozora",
"use-native-pip": "Koristi izvorni režim slike-u-slici za pretraživače"
},
"name": "Slika-u-slici",
"templates": {
"button": "Slika-u-slici"
}
},
"playback-speed": {
"description": "Slušajte brzo, slušajte sporo! Ovo će dodat klizač koji kontrolira brzinu pjesme",
"name": "Brzina pokretanja",
"templates": {
"button": "Brzina"
}
},
"precise-volume": {
"description": "Precizno kontrolirajte jačinu zvuka korištenjem točkih na mišu/prečaca, sa prilagođenim sučeljem i prilagodivim stupnjevima jačine",
"menu": {
"arrows-shortcuts": "Lokalne kontrole tipkih sa strelicama",
"custom-volume-steps": "Postavi prilagođene stope za promjenu jačine",
"global-shortcuts": "Globalni prečaci"
},
"name": "Precizna jačina zvuka",
"prompt": {
"global-shortcuts": {
"keybind-options": {
"decrease": "Snizi jačinu zvuka",
"increase": "Pojačaj jačinu zvuka"
},
"label": "Odaberi globalne prečace na tipkovnici za jačinu zvuka:",
"title": "Globalni prečaci na tipkovnici za jačinu zvuka"
},
"volume-steps": {
"label": "Odaberi stope za povišenje/sniženje jačine zvuka",
"title": "Stope za promjenu jačine zvuka"
}
}
},
"quality-changer": {
"backend": {
"dialog": {
"quality-changer": {
"detail": "Trenutni kvalitet: {{quality}}",
"message": "Odaberi kvalitet videa:",
"title": "Odaberi kvalitet videa"
}
}
},
"description": "Dozvoljava promjenu kvaliteta videa pomoću gumba na video preklopu",
"name": "Promjena kvalitete videa",
"renderer": {
"quality-settings-button": {
"label": "Otvori izbornik za promjenu kvalitete pokretača"
}
}
},
"scrobbler": {
"description": "Dodaj podršku za 'četkanje' (poput last.fm, Listenbrainz)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Autentifikacija sa Last.fm nije uspjela.\nZatvori skočni prozor do sljedećeg ponovnog pokretanja.",
"title": "Autentifikacija je neuspješna"
}
}
},
"menu": {
"lastfm": {
"api-settings": "Postavke za Last.fm API"
},
"listenbrainz": {
"token": "Unesi korisnički žeton za ListenBrainz"
},
"scrobble-alternative-title": "Koristi alternativne naslove",
"scrobble-other-media": "Učetkaj druge medije"
},
"name": "Četkarnik",
"prompt": {
"lastfm": {
"api-key": "Last.fm API ključ",
"api-secret": "Last.fm API tajna"
},
"listenbrainz": {
"token": {
"label": "Unesi svoj ListenBrainz korisnički žeton:",
"title": "ListenBrainz žeton"
}
}
}
},
"shortcuts": {
"description": "Dozvoljava postavljanje globalnih prečaca na tipkovnici za reproduciranje (pokreni/zaustavi/sljedeće/prijethodno) i isključivanje OSD-a za medije tako što će prebrisati tipke za medije, uključiti Ctrl/CMD + F za pretragu, isključiti MPRIS podršku za medijske tipke na Linux-u, i prilagođene prečace za napredne korisnike",
"menu": {
"override-media-keys": "Prebriši medijske tipke",
"set-keybinds": "Postavi globalne kontrole za pjesme"
},
"name": "Prečaci (& MPRIS)",
"prompt": {
"keybind": {
"keybind-options": {
"next": "Sljedeće",
"play-pause": "Pokreni / Zaustavi",
"previous": "Prijethodno"
},
"label": "Odaberi globalne prečace za upravljanje pjesmama:",
"title": "Globalni prečaci na tipkovnici"
}
}
},
"skip-disliked-songs": {
"description": "Preskače pjesme koje vam se ne sviđaju",
"name": "Preskočite pjesme koje vam se ne sviđaju"
},
"skip-silences": {
"description": "Automatski preskočite dijelove pjesama gdje nema zvuka",
"name": "Preskoči tišine"
},
"sponsorblock": {
"description": "Automatski preskače dijelove pjesama koji nisu glazba poput uvoda/odjave ili dijelove spotova u kojima nema muzike",
"name": "Bloker sponzora"
},
"synced-lyrics": {
"description": "Obezbjeđava sinkronizirane lirike pjesama, korištenjem dobavljača poput LRClib.",
"errors": {
"fetch": "⚠️\tDošlo je do greške prilikom dobavljanja stihova pjesme.\n\tMolimo vas da probate ponovno kasnije.",
"not-found": "⚠️ Tekst za ovu pjesmu nije pronađen."
},
"menu": {
"default-text-string": {
"label": "Zadani karakteri između stihova pjesama",
"tooltip": "Odaberi zadane karaktere koji će biti korišteni za razmake između stihova pjesama"
},
"line-effect": {
"label": "Efekat crte",
"submenu": {
"fancy": {
"label": "Kitnjast",
"tooltip": "Koristi velike (kao iz aplikacije) efekte na trenutnu crtu"
},
"focus": {
"label": "Fokus",
"tooltip": "Pretvorite samo trenutnu crtu bijelu"
},
"offset": {
"label": "Izmak",
"tooltip": "Izmak na trenutnoj crti"
},
"scale": {
"label": "Razmjera",
"tooltip": "Promjeni razmjeru trenutne crte"
}
},
"tooltip": "Odaberi efekat koji će biti primjenjen na trenutnoj crti"
},
"precise-timing": {
"label": "Napravi da tekst pjesme bude izvrsno usklađen",
"tooltip": "Izračunaj do milisekunde prikaz sljedeće crteteksta (može malo utjecati na učinak)"
},
"romanization": {
"label": "Romanizuj stihove pjesama",
"tooltip": "Ako je tekst pjesme na drugom jeziku, probajte da ga prikažete na latinici."
},
"show-lyrics-even-if-inexact": {
"label": "Prikaži tekst pjesme čak i ako je netačan",
"tooltip": "Ako pjesma nije pronađena, produžetak će probati ponovno sa novim upitom za pretragu.\nRezultat iz drugog pokušaja možda neće biti tačan."
},
"show-time-codes": {
"label": "Prikaži vremenske oznake",
"tooltip": "Prikaži vremenske oznake pored teksta pjesme"
}
},
"name": "Sinkronizovani stihovi pjesama",
"refetch-btn": {
"fetching": "Dobavljanje...",
"normal": "Ponovo dobavite tekst pjesme"
},
"warnings": {
"duration-mismatch": "⚠️ - Tekst pjesme možda nije usklađen zbog neuklapanja u daljini trajanja.",
"inexact": "⚠️ - Tekst za ovu pjesmu možda nije tačan",
"instrumental": "⚠️ - Ovo je instrumentalna glazba"
}
},
"taskbar-mediacontrol": {
"description": "Upravljajte reprodukcijom iz Windows radne trake",
"name": "Upravljanje medijima iz radne trake"
},
"touchbar": {
"description": "Dodaje dodatak dodirne trake za macOS korisnike",
"name": "Dodirna Traka"
},
"tuna-obs": {
"description": "Integracija sa OBS-ovim Tuna dodatkom",
"name": "Tuna OBS"
},
"unobtrusive-player": {
"description": "Onemogućava pokretaču da iskoči u toku pokretanja pjesme",
"name": "Nenametljivi pokretač"
},
"video-toggle": {
"description": "Dodaje gumb za šaltanje između režima za video/numeru. Dodatno, može da ukloni cijelu karticu sa videom",
"menu": {
"align": {
"label": "Izravnanje",
"submenu": {
"left": "Lijevo",
"middle": "Sredina",
"right": "Desno"
}
},
"force-hide": "Nasilno uklonite karticu sa videom",
"mode": {
"label": "Režim",
"submenu": {
"custom": "Prilagođeno šaltanje",
"disabled": "Isključeno",
"native": "Izvorno šaltanje"
}
}
},
"name": "Video šaltanje",
"templates": {
"button-song": "Pjesma",
"button-video": "Video"
}
},
"visualizer": {
"description": "Dodaje vizualizator u plejer",
"menu": {
"visualizer-type": "Tip vizualizacije"
},
"name": "Vizualizacija"
}
}
}

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Penyesuaian Visual",
"submenu": {
"custom-window-title": {
"label": "Judul jendela kustom",
"prompt": {
"label": "Masukkan judul jendela kustom (kosongkan untuk menonaktifkan)",
"placeholder": "Contoh: YouTube Music"
}
},
"like-buttons": {
"default": "Standar",
"force-show": "Pertunjukan paksa",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Buka pemilih caption"
},
"toast": {
"caption-changed": "caption diganti ke bahasa {{language}}",
"caption-disabled": "Caption dinonaktifkan",
"no-captions": "tidak tersedia caption untuk lagu ini"
}
},
"compact-sidebar": {
@ -409,6 +421,18 @@
}
}
},
"custom-output-device": {
"menu": {
"device-selector": "Pilih Perangkat"
},
"name": "Perangkat Keluaran Kustom",
"prompt": {
"device-selector": {
"label": "Pilih perangkat media keluaran yang akan digunakan",
"title": "Pilih Perangkat Keluaran"
}
}
},
"disable-autoplay": {
"description": "Buat lagu mulai dalam mode \"jeda\"",
"menu": {
@ -432,7 +456,15 @@
"hide-duration-left": "Sembunyikan sisa durasi",
"hide-github-button": "Sembunyikan tombol link GitHub",
"play-on-youtube-music": "Mainkan di YouTube Music",
"set-inactivity-timeout": "Tetapkan batas waktu tidak aktif"
"set-inactivity-timeout": "Tetapkan batas waktu tidak aktif",
"set-status-display-type": {
"label": "Teks status",
"submenu": {
"artist": "Sedang mendengarkan {artist}",
"title": "Sedang mendengarkan {song title}",
"youtube-music": "Sedang mendengarkan YouTube Music"
}
}
},
"name": "Rich Presence Discord",
"prompt": {
@ -449,16 +481,16 @@
"buttons": {
"ok": "Oke"
},
"message": "Argh! Maaf, dowloadnya gagal…",
"title": "Downloadnya error!"
"message": "Argh! Maaf, dowload gagal…",
"title": "Terjadi kesalahan dalam unduhan!"
},
"start-download-playlist": {
"buttons": {
"ok": "Oke"
},
"detail": "({{playlistSize}} lagu-lagu)",
"message": "Mengunduh Playlist {{playlistTitle}}",
"title": "Download dimulai"
"message": "Mengunduh Daftar Putar {{playlistTitle}}",
"title": "Pengunduhan dimulai"
}
},
"feedback": {
@ -469,8 +501,8 @@
"download-progress": "Mengunduh: {{percent}}%",
"downloading": "Mengunduh…",
"downloading-counter": "Mengunduh {{current}}/{{total}}…",
"downloading-playlist": "Mengunduh playlist \"{{playlistTitle}}\" - {{playlistSize}} lagu ({{playlistId}})",
"error-while-downloading": "Gagal mengunduh \"{{author}} - {{title}}\": {{error}}",
"downloading-playlist": "Mengunduh Daftar Putar \"{{playlistTitle}}\" - {{playlistSize}} lagu-lagu ({{playlistId}})",
"error-while-downloading": "Gagal dalam mengunduh \"{{author}} - {{title}}\": {{error}}",
"folder-already-exists": "Folder {{playlistFolder}} sudah ada",
"getting-playlist-info": "Mendapatkan informasi playlist…",
"loading": "Memuat…",
@ -525,7 +557,7 @@
}
}
},
"name": "Equalizer"
"name": "Ekualiser"
},
"exponential-volume": {
"description": "Buat penggeser volume menjadi eksponen sehingga memudahkan memilih volume yang lebih rendah.",
@ -600,7 +632,15 @@
},
"navigation": {
"description": "panah navigasi Selanjutnya/Sebelumnya terintegrasi pada antarmuka, layaknya peramban kesukaan Anda",
"name": "Navigasi"
"name": "Navigasi",
"templates": {
"back": {
"title": "Kunjungi halaman sebelumnya"
},
"forward": {
"title": "pergi ke halaman berikutnya"
}
}
},
"no-google-login": {
"description": "Hapus tombol dan tautan masuk Google dari antarmuka",
@ -692,7 +732,12 @@
}
},
"description": "Izinkan untuk mengubah kualitas video dengan tombol pada hamparan video",
"name": "Pengubah Kualitas Video"
"name": "Pengubah Kualitas Video",
"renderer": {
"quality-settings-button": {
"label": "pengubah kualitas pemain terbuka"
}
}
},
"scrobbler": {
"description": "Tambahkan dukungan scrobbling (mis. last.fm, Listenbrainz)",
@ -859,7 +904,8 @@
},
"name": "Peralih Video",
"templates": {
"button-song": "Lagu"
"button-song": "Lagu",
"button-video": "video"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Miglioramenti visivi",
"submenu": {
"custom-window-title": {
"label": "Personalizza titolo finestra",
"prompt": {
"label": "Inserisci un titolo della finestra personalizzato: (lascia vuoto per disattivare)",
"placeholder": "Esempio: YouTube Music"
}
},
"like-buttons": {
"default": "Predefinito",
"force-show": "Forza la visualizzazione",
@ -414,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Scegli da quale uscita audio vuoi riprodurre i brani",
"menu": {
"device-selector": "Seleziona un'uscita"
},
"name": "Dispositivo di Output Personalizzato",
"prompt": {
"device-selector": {
"label": "Scegli il dispositivo d'output da utilizzare",
"title": "Scegli il dispositivo d'output"
}
}
},
"disable-autoplay": {
"description": "Fa iniziare i brani in modalità \"pausa\"",
"menu": {
@ -437,7 +457,15 @@
"hide-duration-left": "Nascondi la durata rimasta",
"hide-github-button": "Nascondi il pulsante link a GitHub",
"play-on-youtube-music": "Riproduci su YouTube Music",
"set-inactivity-timeout": "Imposta il timeout di inattività"
"set-inactivity-timeout": "Imposta il timeout di inattività",
"set-status-display-type": {
"label": "Testo dello status",
"submenu": {
"artist": "Stai ascoltando {artist}",
"title": "Stai ascoltando {song title}",
"youtube-music": "Ascoltando YouTube Music"
}
}
},
"name": "Discord Rich Presence",
"prompt": {
@ -573,7 +601,7 @@
"connected-users": "Utenti connessi",
"disconnect": "Disconetti Music Together",
"empty-user": "Utenti non connessi",
"host": "Music Together Host",
"host": "Host di Music Together",
"join": "Unisciti a Music Together",
"permission": {
"all": "Consenti ai Guest di controllare la playlist e il player",
@ -646,13 +674,13 @@
"menu": {
"always-on-top": "Sempre in primo piano",
"hotkey": {
"label": "Hotkey",
"label": "Tasto di scelta rapida",
"prompt": {
"keybind-options": {
"hotkey": "Hotkey"
"hotkey": "Tasto di scelta rapida"
},
"label": "Scegliere un'hotkey per attivare Picture-in-picture",
"title": "Picture-in-picture Hotkey"
"title": "Tasto di scelta rapida per Picture-in-picture"
}
},
"save-window-position": "Salva la posizione della finestra",
@ -705,7 +733,12 @@
}
},
"description": "Permette di cambiare la qualità del video con un pulsante in sovrimpressione",
"name": "Cambia qualità video"
"name": "Cambia qualità video",
"renderer": {
"quality-settings-button": {
"label": "Apri il selettore di qualità del player"
}
}
},
"scrobbler": {
"description": "Aggiunge il supporto per lo scrobbling (Last.fm, Listenbrainz ecc.)",
@ -724,6 +757,7 @@
"listenbrainz": {
"token": "Inserire il token utente per ListenBrainz"
},
"scrobble-alternative-artist": "Usa artisti alternativi",
"scrobble-alternative-title": "Usa titoli alternativi",
"scrobble-other-media": "Scrobble altri media"
},
@ -761,7 +795,7 @@
}
},
"skip-disliked-songs": {
"description": "Salta i brani che non ti piacciono",
"description": "Salta le canzoni non gradite",
"name": "Salta i brani che non ti piacciono"
},
"skip-silences": {
@ -809,6 +843,14 @@
"label": "Rendi i testi perfettamente sincronizzati",
"tooltip": "Calcola al millisecondo la visualizzazione della riga successiva (può avere un piccolo impatto sulle prestazioni)"
},
"preferred-provider": {
"label": "Provider preferito",
"none": {
"label": "Nessuno",
"tooltip": "Nessun provider preferito"
},
"tooltip": "Scegli quale provider predefinito utilizzare"
},
"romanization": {
"label": "Testi in caratteri occidentali",
"tooltip": "Qualora il testo fosse scritto in una lingua non occidentale, prova a visualizzarlo in caratteri latini."
@ -841,6 +883,27 @@
"description": "Aggiunge un widget TouchBar per gli utenti macOS",
"name": "Touch Bar (per MacOS)"
},
"transparent-player": {
"description": "Rende trasparente la finestra del programma",
"menu": {
"opacity": {
"label": "Opacità",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Tipo",
"submenu": {
"acrylic": "Acrilico",
"mica": "Mica",
"none": "Nessuno",
"tabbed": "In scheda"
}
}
},
"name": "Player Trasparente"
},
"tuna-obs": {
"description": "Integrazione con il plugin OBS Tuna",
"name": "Tuna OBS"

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "見た目の微調整",
"submenu": {
"custom-window-title": {
"label": "カスタムウィンドウタイトル",
"prompt": {
"label": "カスタムウィンドウタイトルを入力: (未入力の場合無効になります)",
"placeholder": "例: YouTube Music"
}
},
"like-buttons": {
"default": "デフォルト",
"force-show": "強制的に表示",
@ -334,6 +341,7 @@
"name": "オーディオコンプレッサー"
},
"auth-proxy-adapter": {
"description": "認証プロキシサービスの利用サポート",
"menu": {
"disable": "プロキシアダプターを無効にする",
"enable": "プロキシアダプターを有効にする",
@ -344,6 +352,7 @@
"label": "ポート"
}
},
"name": "認証プロキシアダプタ",
"prompt": {
"hostname": {
"label": "ローカルプロキシサーバのホスト名を入力します(再起動が必要です):",
@ -379,6 +388,11 @@
},
"templates": {
"title": "字幕選択機を開く"
},
"toast": {
"caption-changed": "字幕を{{language}}に変更しました",
"caption-disabled": "字幕を無効にしました",
"no-captions": "この曲には字幕がありません"
}
},
"compact-sidebar": {
@ -598,7 +612,15 @@
},
"navigation": {
"description": "ブラウザの戻る・進むボタンのようにUIからコントロールできるボタン",
"name": "ナビゲーション"
"name": "ナビゲーション",
"templates": {
"back": {
"title": "前のページに戻ります"
},
"forward": {
"title": "次のページに進みます"
}
}
},
"no-google-login": {
"description": "インターフェースからGoogleのログインボタンとリンクを削除",
@ -690,7 +712,12 @@
}
},
"description": "ビデオオーバーレイのボタンを使用してビデオ品質を変更できるようにします",
"name": "ビデオ品質チェンジャー"
"name": "ビデオ品質チェンジャー",
"renderer": {
"quality-settings-button": {
"label": "ビデオ品質チェンジャーを開きます"
}
}
},
"scrobbler": {
"description": "スクロブリング対応を追加しますlast.fm、Listenbrainzなど",
@ -857,7 +884,8 @@
},
"name": "動画の切り替え",
"templates": {
"button-song": "曲"
"button-song": "曲",
"button-video": "動画"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "시각적 변경",
"submenu": {
"custom-window-title": {
"label": "사용자 정의 앱 제목",
"prompt": {
"label": "앱 제목으로 표시할 내용 : (빈 칸 일시 비활성화)",
"placeholder": "예: YouTube Music"
}
},
"like-buttons": {
"default": "기본",
"force-show": "강제로 표시",
@ -334,7 +341,7 @@
"name": "오디오 컴프레서"
},
"auth-proxy-adapter": {
"description": "인증 프록시 서비스 사용 지원",
"description": "아이디/패스워드가 필요한 프록시를 지원합니다",
"menu": {
"disable": "프록시 어댑터 차단",
"enable": "프록시 어댑터 허용",
@ -381,6 +388,11 @@
},
"templates": {
"title": "자막 선택기 열기"
},
"toast": {
"caption-changed": "자막 언어가 {{language}}(으)로 변경되었습니다",
"caption-disabled": "자막이 비활성화 되었습니다",
"no-captions": "이 곡에는 자막이 없습니다"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "미디어 출력 장치 구성",
"menu": {
"device-selector": "장치 선택"
},
"name": "출력 장치 커스텀",
"prompt": {
"device-selector": {
"label": "사용할 미디어 출력 장치를 선택하세요",
"title": "출력 장치 선택"
}
}
},
"disable-autoplay": {
"description": "노래를 '일시 정지' 모드로 시작하게 합니다",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "남은 재생 시간 숨기기",
"hide-github-button": "GitHub 링크 버튼 숨기기",
"play-on-youtube-music": "유튜브 뮤직에서 재생",
"set-inactivity-timeout": "비활성 시간 제한 설정"
"set-inactivity-timeout": "비활성 시간 제한 설정",
"set-status-display-type": {
"label": "상태 텍스트",
"submenu": {
"artist": "{아티스트} 듣는 중",
"title": "{곡 제목} 듣는 중",
"youtube-music": "YouTube Music 듣는 중"
}
}
},
"name": "디스코드 활동 상태",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "브라우저에서처럼, UI에 직접 통합된 앞으로/뒤로 탐색하는 화살표",
"name": "탐색"
"name": "탐색",
"templates": {
"back": {
"title": "이전 페이지로 이동"
},
"forward": {
"title": "다음 페이지로 이동"
}
}
},
"no-google-login": {
"description": "UI에서 Google 로그인 버튼 및 링크 제거하기",
@ -692,7 +733,12 @@
}
},
"description": "영상 오버레이의 버튼으로 영상 품질을 변경할 수 있습니다",
"name": "영상 품질 체인저"
"name": "영상 품질 체인저",
"renderer": {
"quality-settings-button": {
"label": "영상 품질 선택기 열기"
}
}
},
"scrobbler": {
"description": "스크로블링 지원을 추가합니다 (예: last.fm, Listenbrainz)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "ListenBrainz 유저 토큰 입력"
},
"scrobble-alternative-artist": "대체 아티스트 명 사용",
"scrobble-alternative-title": "대체 제목 사용하기",
"scrobble-other-media": "다른 미디어 스크로블하기"
},
@ -796,6 +843,14 @@
"label": "가사를 최대한 정교하게 동기화",
"tooltip": "다음 줄의 표시를 밀리초 단위로 계산합니다 (성능에 약간의 영향을 미칠 수 있음)"
},
"preferred-provider": {
"label": "선호하는 가사 제공자",
"none": {
"label": "없음",
"tooltip": "선호하는 가사 제공자 없음"
},
"tooltip": "사용할 기본 가사 제공자를 선택하세요"
},
"romanization": {
"label": "가사 로마자 변환",
"tooltip": "가사가 영어가 아닌 언어로 되어있는 경우, 로마자 표기를 표시합니다."
@ -828,6 +883,27 @@
"description": "macOS 사용자를 위한 TouchBar 위젯을 추가합니다",
"name": "TouchBar"
},
"transparent-player": {
"description": "애플리케이션 창을 투명하게 만듭니다",
"menu": {
"opacity": {
"label": "불투명도",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "종류",
"submenu": {
"acrylic": "아크릴",
"mica": "미카",
"none": "없음",
"tabbed": "탭"
}
}
},
"name": "투명 플레이어"
},
"tuna-obs": {
"description": "OBS의 확장인 Tuna와의 통합을 활성화합니다",
"name": "Tuna OBS"

View File

@ -207,6 +207,10 @@
}
},
"plugins": {
"ad-speedup": {
"description": "Jeigu gros reklama, bus įrašo garsas išjungtas ir pagreitintas 16x",
"name": "Reklamos Pagreitinimas"
},
"adblocker": {
"description": "Blokuoti visas reklamas ir seklius",
"menu": {
@ -215,6 +219,7 @@
"name": "Reklamų blokuotojas"
},
"album-actions": {
"description": "Prideda Nepatinka, Patinka bei atžymėti Nepatika ir Patinka visoms dainoms grojaraštyje arba albume.",
"name": "Albumo Veiksmai"
},
"album-color-theme": {
@ -274,6 +279,56 @@
},
"name": "Aplinkos rėžimas"
},
"amuse": {
"description": "Prideda Youtube Muzika palaikyma Amuse grojimo valdikliui pagal 6K Labs",
"name": "Amuse (Platforma Dainininkams)",
"response": {
"query": "Amuse API serveris yra veikiantis. Parašykite Get /query kad gautumėte dainos informacija."
}
},
"api-server": {
"description": "Prideda API serveri, kad būtų galima kontroliuoti grotuvą",
"dialog": {
"request": {
"buttons": {
"allow": "Leisti",
"deny": "Neleisti"
},
"message": "Leisti {{ID}} ({{origin}}) prieiga prie API?",
"title": "API įgaliojimo užklausa"
}
},
"menu": {
"auth-strategy": {
"label": "Įgaliojimo strategija",
"submenu": {
"auth-at-first": {
"label": "Įgalioti per pirmą užklausą"
},
"none": {
"label": "Nėra įgaliojimo"
}
}
},
"hostname": {
"label": "Serverio Pavadinimas"
},
"port": {
"label": "Prievadas"
}
},
"name": "API Serverio {Beta}",
"prompt": {
"hostname": {
"label": "Įveskite serverio pavadinimą (pavyzdžiui kaip 0.0.0.0) skirtą API serveriui:",
"title": "Serverio Pavadinimas"
},
"port": {
"label": "Įveskite prievadą API serveriui:",
"title": "Prievadas"
}
}
},
"audio-compressor": {
"description": "Pritaikyti garso kompresiją (sumažina garsiausių signalo dalių garsumą ir padidina švelniausių dalių garsumą)",
"name": "Garso Kompresorius"
@ -583,6 +638,17 @@
"description": "Automatiškai praleidžia ne muzikines dalis, pvz., įžangą/užvedimą arba muzikinių vaizdo įrašų dalis, kuriose daina negrojama",
"name": "Rėmėjų blokuotojas"
},
"synced-lyrics": {
"refetch-btn": {
"fetching": "Gaunama...",
"normal": "Atgauti dainos žodžius"
},
"warnings": {
"duration-mismatch": "⚠️ - Dainos žodžiai gali būti nesinchronizuoti dėl trukmės nesutikimo.",
"inexact": "⚠️ - Dainos žodžiai gali šiek tiek skirtis",
"instrumental": "⚠️ Tai instrumentinė daina"
}
},
"taskbar-mediacontrol": {
"description": "Valdykite atkūrimą iš „Windows“ užduočių juostos",
"name": "Užduočių juostos medijos valdymas"

View File

@ -381,6 +381,11 @@
},
"templates": {
"title": "Atvērt subtitru izvēlni"
},
"toast": {
"caption-changed": "Subtitri pamainīti uz {{language}}",
"caption-disabled": "Subtitri izslēgti",
"no-captions": "Subtitri nav pieejami priekš šīs dziesmas"
}
},
"compact-sidebar": {
@ -479,7 +484,9 @@
"playlist-is-empty": "Atskaņošanas saraksts ir tukšs",
"playlist-is-mix-or-private": "Neizdevās iegūt atskaņošanas saraksta informāciju: pārliecinieties, ka tas nav privāts vai \"Jums izveidotā izlase\" saraksts.\n\n{{error}}",
"preparing-file": "Faila sagatavošana…",
"saving": "Saglabāšana…"
"saving": "Saglabāšana…",
"video-id-not-found": "Video nav atrasts",
"writing-id3": "Rakstam ID3 tegus…"
}
}
}

View File

@ -59,6 +59,7 @@
},
"unresponsive": {
"buttons": {
"quit": "ഉപേക്ഷിക്കുക",
"relaunch": "പുനരാരംഭിക്കുക",
"wait": "കാത്തിരിക്കൂ"
},
@ -109,5 +110,22 @@
"enabled": "പ്രവർത്തനക്ഷമമാക്കി"
}
}
},
"plugins": {
"video-toggle": {
"menu": {
"align": {
"label": "ക്രമപ്പെടുത്തൽ",
"submenu": {
"left": "ഇടത്",
"middle": "മധ്യഭാഗം",
"right": "വലത്"
}
}
},
"templates": {
"button-video": "വീഡിയോ"
}
}
}
}

View File

@ -381,6 +381,11 @@
},
"templates": {
"title": "क्याप्सन चयनकर्ता खोल्नुहोस्"
},
"toast": {
"caption-changed": "क्याप्सन {{language}} मा परिवर्तन भयो",
"caption-disabled": "क्याप्सन उपलब्ध छैन",
"no-captions": "यो गीतको लागि कुनै क्याप्सन उपलब्ध छैन।"
}
},
"compact-sidebar": {
@ -600,7 +605,15 @@
},
"navigation": {
"description": "अर्को/पछाडि नेभिगेसन तपाईँको मनपर्ने ब्राउजरमा जस्तै सिधा इन्टरफेसमा एकीकृत तीरहरू",
"name": "नेभिगेसन"
"name": "नेभिगेसन",
"templates": {
"back": {
"title": "अघिल्लो पृष्ठमा जानुहोस्"
},
"forward": {
"title": "अर्को पृष्ठमा जानुहोस्"
}
}
},
"no-google-login": {
"description": "इन्टरफेसबाट गुगल लगइन बटन र लिङ्कहरू हटाउनुहोस्",
@ -859,7 +872,8 @@
},
"name": "भिडियो टगल",
"templates": {
"button-song": "गीत"
"button-song": "गीत",
"button-video": "भिडियो"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Visuele Aanpassingen",
"submenu": {
"custom-window-title": {
"label": "Aangepaste venstertitel",
"prompt": {
"label": "Voer aangepaste venstertitel in: (laat leeg om uit te schakelen)",
"placeholder": "Voorbeeld: Youtube Music"
}
},
"like-buttons": {
"default": "Standaard",
"force-show": "Forceren weergeven",
@ -163,12 +170,12 @@
"cancel": "Annuleren",
"remove": "Verwijderen"
},
"remove-theme": "Weet je zeker dat je het aangepaste thema wilt verwijderen?",
"remove-theme-message": "Dit verwijderd het aangepaste thema"
"remove-theme": "Weet je zeker dat je het aangepaste thema wil verwijderen?",
"remove-theme-message": "Dit verwijdert het aangepaste thema"
},
"label": "Thema",
"submenu": {
"import-css-file": "Aangepast CSS-bestand importeren",
"import-css-file": "Importeer aangepast CSS-bestand",
"no-theme": "Geen thema"
}
}
@ -178,11 +185,11 @@
},
"plugins": {
"enabled": "Ingeschakeld",
"label": "Plugins",
"label": "Invoegtoepassingen",
"new": "NIEUW"
},
"view": {
"label": "Weergave",
"label": "Weergeven",
"submenu": {
"force-reload": "Forceer Herladen",
"reload": "Herladen",
@ -195,31 +202,31 @@
},
"tray": {
"next": "Volgende",
"play-pause": "Afspelen/Pauzeren",
"play-pause": "Afspelen/Pauze",
"previous": "Vorige",
"quit": "Afsluiten",
"restart": "Applicatie Opnieuw Opstarten",
"show": "Venster Weergeven",
"restart": "Herstarten App",
"show": "Weergeven Venster",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
"with-song-info": "YouTube Music: {{artiest}} - {{titel}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Wanneer een advertentie afspeelt, dempt het geluid en versnelt de playback naar 16x",
"name": "Snellere advertenties"
"description": "Bij het afspelen van een advertentie wordt het geluid gedempt en wordt de afspeelsnelheid wordt verhoogd naar 16x",
"name": "Advertenties versnellen"
},
"adblocker": {
"description": "Blokkeer alle advertenties en tracking vanuit de doos",
"description": "Blokkeer alle advertenties en trackers buiten het kader",
"menu": {
"blocker": "Blokkeerder"
},
"name": "Advertentieblokkeerder"
},
"album-actions": {
"description": "Voegt knoppen toe voor Ondisliken, Disliken, Liken en Ontliken om dit toe te passen op alle nummers in een afspeellijst of album",
"description": "Voegt niet-Niet Leuk, Niet Leuk, Leuk, niet-Leuk knoppen toe om dit toe te passen op alle nummers in een afspeellijst of album",
"name": "Albumacties"
},
"album-color-theme": {
@ -345,7 +352,7 @@
"label": "Poort"
}
},
"name": "Auth proxy adapter",
"name": "Proxy-authenticatieadapter",
"prompt": {
"hostname": {
"label": "Hostname voor lokale proxy server (vereist herstart):",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Open ondertitelkeuze"
},
"toast": {
"caption-changed": "Ondertitel veranderd naar {{language}}",
"caption-disabled": "Ondertitels uitgeschakeld",
"no-captions": "Geen ondertitels beschikbaar voor dit lied"
}
},
"compact-sidebar": {
@ -600,7 +612,15 @@
},
"navigation": {
"description": "Volgende/Vorige navigatiepijlen rechtstreeks geïntegreerd in de interface, zoals in je favoriete browser",
"name": "Navigatie"
"name": "Navigatie",
"templates": {
"back": {
"title": "Ga naar de vorige pagina"
},
"forward": {
"title": "Ga naar de volgende pagina"
}
}
},
"no-google-login": {
"description": "Verwijder Google aanmeldknoppen en -links uit de interface",
@ -692,7 +712,12 @@
}
},
"description": "Maakt het mogelijk de videokwaliteit te wijzigen met een knop op de video-overlay",
"name": "Videokwaliteitwisselaar"
"name": "Videokwaliteitwisselaar",
"renderer": {
"quality-settings-button": {
"label": "Open speler kwaliteitswisselaar"
}
}
},
"scrobbler": {
"description": "Ondersteuning voor scrobbling toevoegen (etc. last.fm, Listenbrainz)",
@ -796,6 +821,11 @@
"label": "Zorg ervoor dat de songteksten perfect gesynchroniseerd zijn",
"tooltip": "Bereken tot op de milliseconde de weergave van de volgende regel (kan een kleine impact hebben op de prestaties)"
},
"preferred-provider": {
"none": {
"tooltip": "Geen provider beschikbaar"
}
},
"romanization": {
"label": "Romaniseer songtekst",
"tooltip": "Als de songtekst in een andere taal is, probeer dan een Latijnse versie weer te geven."
@ -859,7 +889,8 @@
},
"name": "Videoschakelaar",
"templates": {
"button-song": "Nummer"
"button-song": "Nummer",
"button-video": "Video"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Poprawki wizualne",
"submenu": {
"custom-window-title": {
"label": "Niestandardowy tytuł okna",
"prompt": {
"label": "Podaj niestandardowy tytuł okna (zostaw puste, aby to wyłączyć):",
"placeholder": "Przykład: YouTube Music"
}
},
"like-buttons": {
"default": "Domyślne",
"force-show": "Wymuś pokazywanie",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Otwórz selektor napisów"
},
"toast": {
"caption-changed": "Zmieniono napisy na {{language}}",
"caption-disabled": "Napisy zostały wyłączone",
"no-captions": "Nie znaleziono napisów dla tego utworu"
}
},
"compact-sidebar": {
@ -600,7 +612,15 @@
},
"navigation": {
"description": "Strzałki nawigacyjne Dalej/Wstecz zintegrowane bezpośrednio z interfejsem, tak jak w Twojej ulubionej przeglądarce",
"name": "Nawigacja"
"name": "Nawigacja",
"templates": {
"back": {
"title": "Przejdź do poprzedniej strony"
},
"forward": {
"title": "Przejdź do następnej strony"
}
}
},
"no-google-login": {
"description": "Usuń przyciski i linki logowania Google z interfejsu",
@ -692,7 +712,12 @@
}
},
"description": "Umożliwia zmianę jakości wideo za pomocą przycisku na nakładce wideo",
"name": "Zmieniacz jakości wideo"
"name": "Zmieniacz jakości wideo",
"renderer": {
"quality-settings-button": {
"label": "Otwórz manipulator jakości odtwarzacza"
}
}
},
"scrobbler": {
"description": "Umożliwia scrobbling utworów do m.in. last.fm lub Listenbrainz",
@ -859,7 +884,8 @@
},
"name": "Przełącznik wideo",
"templates": {
"button-song": "Utwór"
"button-song": "Utwór",
"button-video": "Wideo"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Ajustes visuais",
"submenu": {
"custom-window-title": {
"label": "Título da janela customizado",
"prompt": {
"label": "Insira título customizado para a janela: (deixe em branco para desabilitar)",
"placeholder": "Exemplo: Youtube Music"
}
},
"like-buttons": {
"default": "Padrão",
"force-show": "Forçar exibir",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Abrir seletor de legendas"
},
"toast": {
"caption-changed": "Legenda alterada para {{language}}",
"caption-disabled": "Legendas desativadas",
"no-captions": "Sem legendas disponíveis para essa música"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Configure um dispositivo de saída de mídia personalizado para músicas",
"menu": {
"device-selector": "Selecionar dispositivo"
},
"name": "Dispositivo de saída personalizado",
"prompt": {
"device-selector": {
"label": "Escolha o dispositivo de saída de mídia que será usado",
"title": "Selecionar dispositivo de saída"
}
}
},
"disable-autoplay": {
"description": "Faz a música começar no modo \"pausado\"",
"menu": {
@ -432,7 +457,15 @@
"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"
"set-inactivity-timeout": "Definir tempo limite de inatividade",
"set-status-display-type": {
"label": "Texto de status",
"submenu": {
"artist": "Ouvindo {artist}",
"title": "Ouvindo {song title}",
"youtube-music": "Ouvindo YouTube Music"
}
}
},
"name": "Rich Presence do Discord",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Setas de navegação para avançar/retornar diretamente integradas na interface, como no seu navegador favorito",
"name": "Navegação"
"name": "Navegação",
"templates": {
"back": {
"title": "Ir para a página anterior"
},
"forward": {
"title": "Ir para a próxima página"
}
}
},
"no-google-login": {
"description": "Remova os botões e links de login do Google da interface",
@ -692,7 +733,12 @@
}
},
"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"
"name": "Alterador de qualidade do vídeo",
"renderer": {
"quality-settings-button": {
"label": "Abrir o player de troca de qualidade"
}
}
},
"scrobbler": {
"description": "Adicionar suporte para scrobbling (last.fm, Listenbrainz, etc.)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "Insira o token de usuário ListenBrainz"
},
"scrobble-alternative-artist": "Use artistas alternativos",
"scrobble-alternative-title": "Usar títulos alternativos",
"scrobble-other-media": "Scrobble outras mídias"
},
@ -796,6 +843,14 @@
"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)"
},
"preferred-provider": {
"label": "Provedor Preferido",
"none": {
"label": "Nenhum",
"tooltip": "Sem provedor preferido"
},
"tooltip": "Escolha o provedor padrão para uso"
},
"romanization": {
"label": "Letras romanizadas",
"tooltip": "Se as letras estiverem em um idioma diferente, tente exibir uma versão latina."
@ -828,6 +883,27 @@
"description": "Adiciona um widget TouchBar para usuários do macOS",
"name": "TouchBar"
},
"transparent-player": {
"description": "Faz a janela do app transparente",
"menu": {
"opacity": {
"label": "Opacidade",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Tipo",
"submenu": {
"acrylic": "Acrílico",
"mica": "Mica",
"none": "Nenhum",
"tabbed": "Em abas"
}
}
},
"name": "Player transparente"
},
"tuna-obs": {
"description": "Integração com o plugin Tuna do OBS",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "Alternar vídeo",
"templates": {
"button-song": "Música"
"button-song": "Música",
"button-video": "Vídeo"
}
},
"visualizer": {

File diff suppressed because it is too large Load Diff

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Modificări Vizuale",
"submenu": {
"custom-window-title": {
"label": "Titlul ferestrei personalizate",
"prompt": {
"label": "Introduceți titlul ferestrei personalizate: (lăsați gol pentru a dezactiva)",
"placeholder": "Exemplu: Youtube Music"
}
},
"like-buttons": {
"default": "Default",
"force-show": "Forțează randarea",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Deschide selectorul de subtitrări"
},
"toast": {
"caption-changed": "Subtitrare schimbata in {{language}}",
"caption-disabled": "Subtitrari dezactivate",
"no-captions": "Nu exista subtitrari disponibile pentru aceasta piesa"
}
},
"compact-sidebar": {
@ -600,7 +612,15 @@
},
"navigation": {
"description": "Săgețile pentru Următorul/Anteriorul integrate direct în interfață, ca în browser-ul tău preferat",
"name": "Navigație"
"name": "Navigație",
"templates": {
"back": {
"title": "Inapoi la pagina anterioara"
},
"forward": {
"title": "Urmatoarea pagina"
}
}
},
"no-google-login": {
"description": "Elimină butonul de autentificare Google și link-urile din interfață",
@ -859,7 +879,8 @@
},
"name": "Comutator video",
"templates": {
"button-song": "Melodie"
"button-song": "Melodie",
"button-video": "Video"
}
},
"visualizer": {

View File

@ -21,7 +21,7 @@
"main": {
"console": {
"did-finish-load": {
"dev-tools": "Загрузка завершена. DevTools открыт"
"dev-tools": "Загрузка завершена. DevTools открыты"
},
"i18n": {
"loaded": "i18n загружен"
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Визуальные настройки",
"submenu": {
"custom-window-title": {
"label": "Собственное название окна",
"prompt": {
"label": "Введите собственное название окна: (оставьте пустым, чтобы отключить)",
"placeholder": "Например: YouTube Music"
}
},
"like-buttons": {
"default": "Default",
"force-show": "Всегда показывать",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Открыть выбор субтитров"
},
"toast": {
"caption-changed": "Субтитры изменены на {{language}}",
"caption-disabled": "Субтитры отключены",
"no-captions": "Нет доступных субтитров для этой песни"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Настройка устройства вывода медиа для песен",
"menu": {
"device-selector": "Выберите устройство"
},
"name": "Пользовательское устройство вывода",
"prompt": {
"device-selector": {
"label": "Выберите устройство вывода медиа, которое будет использоваться",
"title": "Выберите устройство вывода"
}
}
},
"disable-autoplay": {
"description": "Запускает песню сразу на паузе",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "Скрыть сколько осталось времени",
"hide-github-button": "Скрыть ссылку на GitHub",
"play-on-youtube-music": "Воспроизвести на YouTube Music",
"set-inactivity-timeout": "Поставить таймер неактивности"
"set-inactivity-timeout": "Поставить таймер неактивности",
"set-status-display-type": {
"label": "Текст статуса",
"submenu": {
"artist": "Слушает {исполнитель}",
"title": "Слушает {название трека}",
"youtube-music": "Слушает YouTube Music"
}
}
},
"name": "Discord Rich Presence",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Стрелки навигации \"вперед/назад\" интегрированы в интерфейс, как в вашем любимом браузере",
"name": "Навигация"
"name": "Навигация",
"templates": {
"back": {
"title": "Предыдущая страница"
},
"forward": {
"title": "Следующая страница"
}
}
},
"no-google-login": {
"description": "Убрать из интерфейса кнопки и ссылки для входа через Google",
@ -692,7 +733,12 @@
}
},
"description": "Позволяет изменять качество видео с помощью кнопки на оверлее видео",
"name": "Изменение качества видео"
"name": "Изменение качества видео",
"renderer": {
"quality-settings-button": {
"label": "Открыть настройки качества плеера"
}
}
},
"scrobbler": {
"description": "Добавляет поддержку скробблинга (last.fm, Listenbrainz)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "Введите токен пользователя ListenBrainz"
},
"scrobble-alternative-artist": "Использовать альтернативных исполнителей",
"scrobble-alternative-title": "Использовать альтернативные названия",
"scrobble-other-media": "Скробблинг других медиа"
},
@ -796,6 +843,14 @@
"label": "Идеально синхронизировать слова",
"tooltip": "До миллисекунды рассчитывает отображение следующей строки(может оказать небольшое влияние на производительность)"
},
"preferred-provider": {
"label": "Предпочитаемый источник",
"none": {
"label": "Никакой",
"tooltip": "Нет предпочитаемого источника"
},
"tooltip": "Выберите источник по умолчанию"
},
"romanization": {
"label": "Романизировать слова",
"tooltip": "Если слова на другом языке, пытаться отображать версию на латинице."
@ -828,6 +883,27 @@
"description": "Добавляет виджет тачбара для пользователей macOS",
"name": "Тачбар"
},
"transparent-player": {
"description": "Делает окно приложения прозрачным",
"menu": {
"opacity": {
"label": "Непрозрачность",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Тип",
"submenu": {
"acrylic": "Acrylic",
"mica": "Mica",
"none": "Отключено",
"tabbed": "Tabbed"
}
}
},
"name": "Прозрачный плеер"
},
"tuna-obs": {
"description": "Интеграция с плагином Tuna от OBS",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "Переключатель видео",
"templates": {
"button-song": "Песня"
"button-song": "Песня",
"button-video": "Видео"
}
},
"visualizer": {

View File

@ -44,7 +44,7 @@
},
"dialog": {
"hide-menu-enabled": {
"detail": "මෙනුව සැගවී ඇත, නැවත පෙන්වීමට 'Alt' යතුර භාවිතා කරන්න. (හෝ In-App මෙනුවේ 'Escape')",
"detail": "මෙනුව සැගවී ඇත, නැවත පෙන්වීමට 'Alt' භාවිතා කරන්න. (මෙනුවේ 'Escape')",
"message": "මෙනුව සැගවීම සක්‍රීය කර ඇත",
"title": "මෙනුව සැගවීම සක්‍රීයයි"
},
@ -175,7 +175,40 @@
}
}
}
},
"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": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
}
}
},
"plugins": {
"adblocker": {
"description": "සියලුම දැන්වීම් අවහිර කර කොටුවෙන් පිටත ලුහුබැඳීම"
}
}
}

View File

@ -0,0 +1,10 @@
{
"common": {
"console": {
"plugins": {
"execute-failed": "Dështoi në ekzekutimin e plugin-it {{pluginName}}::{{contextName}}",
"executed-at-ms": "Shtojca {{pluginName}}::{{contextName}} u ekzekutua në {{ms}}ms"
}
}
}
}

View File

@ -30,10 +30,10 @@
"receive-command": "Primljena je komanda kroz protokol: \"{{command}}\""
},
"theme": {
"css-file-not-found": "CSS datoteka \"{{cssFile}}\" ne postoji, ignorisano"
"css-file-not-found": "CSS datoteka \"{{cssFile}}\" ne postoji, ignorišem"
},
"unresponsive": {
"details": "Aplikacija ne odgovara!\n{{error}}"
"details": "Aplikacija se ne odaziva!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Čišćenje keširanih podataka"
@ -116,7 +116,7 @@
"auto-update": "Automatsko ažuriranje",
"hide-menu": {
"dialog": {
"message": "Meni će biti sakriven posle sledećeg pokretanje, upotrebite [Alt]da ga ponovo prikažete (ili backtick [`] ukoliko koristite meni u aplikaciji)",
"message": "Meni će biti sakriven posle sledećeg pokretanje, upotrebite [Alt] da ga ponovo prikažete (ili backtick [`] ukoliko koristite meni u aplikaciji)",
"title": "Sakrivanje menija je omogućeno"
},
"label": "Sakrij meni"
@ -132,7 +132,7 @@
}
},
"resume-on-start": "Nastavi trenutnu numeru pri sledećem pokretanju",
"single-instance-lock": "Jedna instanca aplikacije",
"single-instance-lock": "Sprečavanje višestrukog pokretanja",
"start-at-login": "Pokreni po prijavi u sistem",
"starting-page": {
"label": "Početna strana",
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Vizuelna podešavanja",
"submenu": {
"custom-window-title": {
"label": "Prilagođeni naziv prozora",
"prompt": {
"label": "Unesite prilagođeni naslov prozora: (ostavite prazno da onemogućite)",
"placeholder": "Primer: YouTube Muzika"
}
},
"like-buttons": {
"default": "Podrazumevano",
"force-show": "Prinudno prikaži",
@ -281,9 +288,9 @@
},
"amuse": {
"description": "Dodaje podršku za 'Amuse now' vidžet (6K Labs) u YouTube Muziku",
"name": "Amuse",
"name": "Zabavi",
"response": {
"query": "Amuse API server je pokrenut. GET /query da biste dobili informacije o numeri."
"query": "Amuse API server je pokrenut. Koristite GET /query da biste dobili informacije o numeri."
}
},
"api-server": {
@ -292,7 +299,7 @@
"request": {
"buttons": {
"allow": "Dozvoli",
"deny": "Ne dozvoli"
"deny": "Odbij"
},
"message": "Dozvoli {{ID}} ({{origin}}) da pristupa API-ju?",
"title": "Zahtev za autorizaciju na API"
@ -311,7 +318,7 @@
}
},
"hostname": {
"label": "Host"
"label": "Ime host-a"
},
"port": {
"label": "Port"
@ -320,8 +327,8 @@
"name": "API Server [Beta]",
"prompt": {
"hostname": {
"label": "Unesite host (npr. 0.0.0.0) za API server:",
"title": "Host"
"label": "Unesite ime host-a (npr. 0.0.0.0) za API server:",
"title": "Ime host-a"
},
"port": {
"label": "Unesite port za API server:",
@ -339,7 +346,7 @@
"disable": "Onemogući Proxy adapter",
"enable": "Omogući Proxy adapter",
"hostname": {
"label": "Host"
"label": "Ime host-a"
},
"port": {
"label": "Port"
@ -348,8 +355,8 @@
"name": "Proxy adapter za autentifikaciju",
"prompt": {
"hostname": {
"label": "Unesi host za lokalni proxy server (zahteva ponovno pokretanje):",
"title": "Proxy Host"
"label": "Unesi ime host-a za lokalni proxy server (zahteva ponovno pokretanje):",
"title": "Ime host-a za Proxy"
},
"port": {
"label": "Unesi port za lokalni proxy server (zahteva ponovno pokretanje):",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Otvori meni za izbor prevoda"
},
"toast": {
"caption-changed": "Prevod promenjen u {{language}}",
"caption-disabled": "Prevod onemogućen",
"no-captions": "Za ovu pesmu nisu dostupni prevodi"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Konfigurišite prilagođeni izlazni medijski uređaj za pesme",
"menu": {
"device-selector": "Izaberite uređaj"
},
"name": "Prilagođeni izlazni uređaj",
"prompt": {
"device-selector": {
"label": "Izaberite izlazni medijski uređaj koji će se koristiti",
"title": "Izaberite izlazni uređaj"
}
}
},
"disable-autoplay": {
"description": "Numere se pokreću u pauziranom režimu",
"menu": {
@ -418,7 +443,7 @@
},
"discord": {
"backend": {
"already-connected": "Pokušaj da se poveže u momentu aktivne veze",
"already-connected": "Pokušano je da se poveže sa aktivnom vezom",
"connected": "Spojeno sa Discord-om",
"disconnected": "Poništeno povezivanje sa Discord-om"
},
@ -429,11 +454,20 @@
"clear-activity-after-timeout": "Očisti aktivnosti nakon isteka vremena",
"connected": "Povezano",
"disconnected": "Nije povezano",
"hide-github-button": "Sakrij GitHub link dugme",
"hide-duration-left": "Sakrij preostalo vreme",
"hide-github-button": "Sakrij dugme sa GitHub linkom",
"play-on-youtube-music": "Reprodukuj na YouTube Muzici",
"set-inactivity-timeout": "Podesi tajmer za neaktivnost"
"set-inactivity-timeout": "Podesi tajmer za neaktivnost",
"set-status-display-type": {
"label": "Tekst statusa",
"submenu": {
"artist": "Slušanje {artist}",
"title": "Slušanje {song title}",
"youtube-music": "Slušanje YouTube muzike"
}
}
},
"name": "Discord Rich Presence",
"name": "Discord Bogato Prisustvo",
"prompt": {
"set-inactivity-timeout": {
"label": "Unesi vreme za tajmer neaktivnosti u sekundama:",
@ -476,7 +510,7 @@
"playlist-has-only-one-song": "Plejlista sadrži samo jednu numeru, preuzima se direktno",
"playlist-id-not-found": "Nije pronađen ID plejliste",
"playlist-is-empty": "Plejlista je prazna",
"playlist-is-mix-or-private": "Greška pri preuzimanju informacija o plejlisti: proverite da li je možda skrivena ili \"Mixed for you\" plejlista\n\n{{error}}",
"playlist-is-mix-or-private": "Greška pri preuzimanju informacija o plejlisti: proverite da li je možda skrivena ili \"Za tebe\" plejlista\n\n{{error}}",
"preparing-file": "Pripremanje datoteke…",
"saving": "Čuvanje…",
"trying-to-get-playlist-id": "Pokušaj preuzimanja ID plejliste: {{playlistId}}",
@ -508,14 +542,14 @@
},
"name": "Servis za preuzimanje",
"renderer": {
"can-not-update-progress": "Nemoguće ažuriranje trenutnog progresa"
"can-not-update-progress": "Nemoguće ažuriranje trenutnog napretka"
},
"templates": {
"button": "Preuzimanje"
}
},
"equalizer": {
"description": "Dodaje 'equalizer' u muzički plejer",
"description": "Dodaje ekvilajzer u muzički plejer",
"menu": {
"presets": {
"label": "Predefinisana podešavanja",
@ -524,7 +558,393 @@
}
}
},
"name": "Equalizer"
"name": "Ekvilajzer"
},
"exponential-volume": {
"description": "Postavlja slajder jačine kao eksponencijalan radi lakšeg izbora nižih jačina.",
"name": "Eksponencijalna jačina"
},
"in-app-menu": {
"description": "Daje izbornim trakama fensi, tamni ili izgled prema boji albuma",
"menu": {
"hide-dom-window-controls": "Sakrij kontrole DOM prozora"
},
"name": "Izborni menu unutar aplikacije"
},
"lumiastream": {
"description": "Dodaje podršku za Lumia Stream",
"name": "Lumia Stream [Beta]"
},
"lyrics-genius": {
"description": "Dodaje podršku za tekstove za većinu pesama",
"menu": {
"romanized-lyrics": "Romanizovani tekstovi"
},
"name": "Genius tekstovi",
"renderer": {
"fetched-lyrics": "Dobavljen tekst pesme sa Genius-a"
}
},
"music-together": {
"description": "Podeli plejlistu sa drugima. Kada domaćin (host) pusti pesmu, svi ostali će čuti istu pesmu",
"dialog": {
"enter-host": "Unesi ID host-a"
},
"internal": {
"save": "Sačuvaj",
"track-source": "Izvor pesme",
"unknown-user": "Nepoznat korisnik"
},
"menu": {
"click-to-copy-id": "Kopiraj ID host-a",
"close": "Zatvori 'Music Together'",
"connected-users": "Spojeni korisnici",
"disconnect": "Prekini vezu sa 'Music Together'",
"empty-user": "Nema povezanih korisnika",
"host": "'Music Together' domaćin (host)",
"join": "Pridruži se 'Music Together'",
"permission": {
"all": "Dozvoli gostima da kontrolišu plejlistu i reprodukciju",
"host-only": "Samo domaćin (host) može da kontroliše plejlistu i reprodukciju",
"playlist": "Dozvoli gostima da kontrolišu plejlistu"
},
"set-permission": "Promeni dozvole za upravljanje",
"status": {
"disconnected": "Nije povezan",
"guest": "Povezan kao gost",
"host": "Povezan kao domaćin (host)"
}
},
"name": "Music Together [Beta]",
"toast": {
"add-song-failed": "Dodavanje pesme nije uspelo",
"closed": "'Music Together' je zatvorena",
"disconnected": "Veza sa 'Music Together' je prekinuta",
"host-failed": "Pokretanje 'Music Together' kao domaćin (host) nije uspelo",
"id-copied": "ID domaćina (host) kopiran u privremenu memoriju",
"id-copy-failed": "Kopiranje ID domaćina (host) u privremenu memoriju nije uspelo",
"join-failed": "Povezivanje na 'Music Together' neuspešno",
"joined": "Povezan na 'Music Together'",
"permission-changed": "Dozvola 'Music Together' promenjena na \"{{permission}}\"",
"remove-song-failed": "Uklanjanje pesme nije uspelo",
"user-connected": "{{name}} se pridružio na 'Music Together'",
"user-disconnected": "{{name}} je napustio 'Music Together'"
}
},
"navigation": {
"description": "Strelice za navigaciju napred/nazad su direktno integrisane u interfejs, kao i u tvom omiljenom pregledaču",
"name": "Navigacija",
"templates": {
"back": {
"title": "Vrati se na prethodnu stranicu"
},
"forward": {
"title": "Idi na sledeću stranicu"
}
}
},
"no-google-login": {
"description": "Ukloni Google dugmad i linkove za prijavu sa interfejsa",
"name": "Bez Google prijave"
},
"notifications": {
"description": "Prikaži obaveštenje kada numera krene sa reprodukcijom (interaktivna obaveštenja su dostupna na Windows-u)",
"menu": {
"interactive": "Interaktivna obaveštenja",
"interactive-settings": {
"label": "Podešavanja za interakciju",
"submenu": {
"hide-button-text": "Sakrij tekst dugmeta",
"refresh-on-play-pause": "Osveži prilikom Pokreni/Pauziraj",
"tray-controls": "Otvori/Zatvori klikom na sistemsku traku"
}
},
"priority": "Prioritet obaveštenja",
"toast-style": "Toast stil obaveštenja",
"unpause-notification": "Prikaži obaveštenje prilikom nastavka reprodukcije"
},
"name": "Obaveštenja"
},
"performance-improvement": {
"description": "Poboljšaj performanse omogućavanjem eksperimentalnih skripti",
"name": "Poboljšaj performanse [Beta]"
},
"picture-in-picture": {
"description": "Dozvoljava aplikaciji da se prebaci u režim slike-u-slici",
"menu": {
"always-on-top": "Uvek na vrhu",
"hotkey": {
"label": "Prečica",
"prompt": {
"keybind-options": {
"hotkey": "Prečica"
},
"label": "Izaberi prečicu za prebacivanje u režim slike-u-slici",
"title": "Prečica za režim slike-u-slici"
}
},
"save-window-position": "Sačuvaj poziciju prozora",
"save-window-size": "Sačuvaj veličinu prozora",
"use-native-pip": "Koristi izvorni režim slike-u-slici za pregledače"
},
"name": "Slika-u-slici",
"templates": {
"button": "Slika-u-slici"
}
},
"playback-speed": {
"description": "Slušaj brzo, slušaj sporo! Dodaje slajder koji kontroliše brzinu pesme",
"name": "Brzina reprodukcije",
"templates": {
"button": "Brzina"
}
},
"precise-volume": {
"description": "Precizno kontroliši jačinu zvuka korišćenjem točka na mišu/prečica, sa prilagođenim interfejsom i prilagodivim inkrementalnim koracima jačine",
"menu": {
"arrows-shortcuts": "Lokalne kontrole tastera sa strelicama",
"custom-volume-steps": "Postavi prilagođene korake za promenu jačine",
"global-shortcuts": "Globalne prečice"
},
"name": "Precizna jačina",
"prompt": {
"global-shortcuts": {
"keybind-options": {
"decrease": "Smanji jačinu",
"increase": "Povećaj jačinu"
},
"label": "Izaberi globalne prečice na tastaturi za jačinu:",
"title": "Globalne prečice na tastaturi za jačinu"
},
"volume-steps": {
"label": "Izaberi korake za povećanje/smanjenje jačine",
"title": "Koraci za promenu jačine"
}
}
},
"quality-changer": {
"backend": {
"dialog": {
"quality-changer": {
"detail": "Trenutni kvalitet: {{quality}}",
"message": "Izaberi kvalitet videa:",
"title": "Izaberi kvalitet videa"
}
}
},
"description": "Dozvoljava promenu kvaliteta videa pomoću dugmeta na video preklapanju",
"name": "Promena kvaliteta videa",
"renderer": {
"quality-settings-button": {
"label": "Otvori meni za promenu kvaliteta plejera"
}
}
},
"scrobbler": {
"description": "Dodaj podršku za 'četkanje' (poput last.fm, Listenbrainz)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Autentifikacija sa Last.fm nije uspela.\nZatvori iskačući prozor do sledećeg ponovnog pokretanja.",
"title": "Autentifikacija neuspešna"
}
}
},
"menu": {
"lastfm": {
"api-settings": "Podešavanja za Last.fm API"
},
"listenbrainz": {
"token": "Unesi korisnički žeton za ListenBrainz"
},
"scrobble-alternative-artist": "Koristi alternativne izvođače",
"scrobble-alternative-title": "Koristi alternativne naslove",
"scrobble-other-media": "Učetkaj druge medije"
},
"name": "Četkarnik",
"prompt": {
"lastfm": {
"api-key": "Last.fm API ključ",
"api-secret": "Last.fm API tajna"
},
"listenbrainz": {
"token": {
"label": "Unesi svoj ListenBrainz korisnički žeton:",
"title": "ListenBrainz žeton"
}
}
}
},
"shortcuts": {
"description": "Dozvoljava postavljanje globalnih prečica na tastaturi za reproduciju (pusti/pauziraj/sledeće/prethodno) i isključivanje OSD za medije tako što će prepisati tastere za medije, uključiti Ctrl/CMD + F za pretragu, isključiti MPRIS podršku za medija tastere na Linux-u, i prilagođene prečice za napredne korisnike",
"menu": {
"override-media-keys": "Prepiši medija tastere",
"set-keybinds": "Podesi globalne kontrole za pesme"
},
"name": "Prečice (& MPRIS)",
"prompt": {
"keybind": {
"keybind-options": {
"next": "Sledeće",
"play-pause": "Pusti / Pauziraj",
"previous": "Prethodno"
},
"label": "Izaberi globalne prečice za upravljanje pesmama:",
"title": "Globalne prečice na tastaturi"
}
}
},
"skip-disliked-songs": {
"description": "Preskače pesme koje vam se nisu svidele",
"name": "Preskočite pesme koje vam se nisu svidele"
},
"skip-silences": {
"description": "Automatski preskočite delove pesama gde nema zvuka",
"name": "Preskoči tišine"
},
"sponsorblock": {
"description": "Automatski preskače delove pesama koji nisu muzika poput uvod/odjava ili delove muzičkih spotova u kojima nema muzike",
"name": "Blok sponzora"
},
"synced-lyrics": {
"description": "Obezbeđuje sinhronizovane lirike pesama, korišćenjem dobavljača poput LRClib.",
"errors": {
"fetch": "⚠️\tDošlo je do greške prilikom dobavljanja stihova pesme.\n\tMolimo vas da pokušate ponovo kasnije.",
"not-found": "⚠️ Tekst za ovu pesmu nije pronađen."
},
"menu": {
"default-text-string": {
"label": "Podrazumevani karakteri između tekstova pesama",
"tooltip": "Izaberi podrazumevane karaktere koji će biti korišćeni za razmake između tekstova pesama"
},
"line-effect": {
"label": "Efekat linije",
"submenu": {
"fancy": {
"label": "Kitnjast",
"tooltip": "Koristi velike (kao iz aplikacije) efekte na trenutnu liniju"
},
"focus": {
"label": "Fokus",
"tooltip": "Učini samo trenutnu liniju belom"
},
"offset": {
"label": "Pomeraj",
"tooltip": "Pomeraj na trenutnoj liniji"
},
"scale": {
"label": "Razmera",
"tooltip": "Promeni razmeru trenutne linije"
}
},
"tooltip": "Izaberi efekat koji će biti primenjen na trenutnoj liniji"
},
"precise-timing": {
"label": "Učini da tekst pesme bude savršeno usklađen",
"tooltip": "Izračunaj do milisekunde prikaz sledeće linije teksta (može malo uticati na učinak)"
},
"preferred-provider": {
"label": "Preferirani dobavljač",
"none": {
"label": "Nijedan",
"tooltip": "Bez preferiranog dobavljača"
},
"tooltip": "Izaberite podrazumevanog dobavljača kog ćete koristiti"
},
"romanization": {
"label": "Romanizuj tekstove pesama",
"tooltip": "Ako je tekst pesme na drugom jeziku, pokušaj da ga prikažeš u latiničnoj varijanti."
},
"show-lyrics-even-if-inexact": {
"label": "Prikaži tekst pesme čak iako nije tačan",
"tooltip": "Ako pesma nije pronađena, produžetak će pokušati ponovo sa novim upitom za pretragu.\nRezultat iz drugog pokušaja možda neće biti tačan."
},
"show-time-codes": {
"label": "Prikaži vremenske oznake",
"tooltip": "Prikaži vremenske oznake pored teksta pesme"
}
},
"name": "Sinhronizovani tekstovi pesama",
"refetch-btn": {
"fetching": "Dobavljanje...",
"normal": "Ponovo dobavi tekst pesme"
},
"warnings": {
"duration-mismatch": "⚠️ - Tekst pesme možda nije usklađen zbog neuklapanja u dužini trajanja.",
"inexact": "⚠️ - Tekst za ovu pesmu možda nije tačan",
"instrumental": "⚠️ - Ovo je instrumentalna pesma"
}
},
"taskbar-mediacontrol": {
"description": "Upravljaj reprodukcijom iz Windows trake sa zadacima",
"name": "Upravljanje medijima iz trake sa zadacima"
},
"touchbar": {
"description": "Dodaje dodatak dodirne trake za macOS korisnike",
"name": "Dodirna Traka"
},
"transparent-player": {
"description": "Čini prozor aplikacije transparentnim",
"menu": {
"opacity": {
"label": "Neprozirnost",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Tip",
"submenu": {
"acrylic": "Akrilan",
"mica": "Mika",
"none": "Nijedan",
"tabbed": "Kartice"
}
}
},
"name": "Transparentni plejer"
},
"tuna-obs": {
"description": "Integracija sa OBS-ovim Tuna dodatkom",
"name": "Tuna OBS"
},
"unobtrusive-player": {
"description": "Onemogućava plejeru da iskače u toku pokretanja pesme",
"name": "Nenametljivi plejer"
},
"video-toggle": {
"description": "Dodaje dugme za promenu između režima za video/numeru. Opciono, može da ukloni celu karticu sa videom",
"menu": {
"align": {
"label": "Poravnanje",
"submenu": {
"left": "Levo",
"middle": "Sredina",
"right": "Desno"
}
},
"force-hide": "Nasilno ukloni karticu sa videom",
"mode": {
"label": "Režim",
"submenu": {
"custom": "Prilagođeno prebacivanje",
"disabled": "Onemogućeno",
"native": "Izvorno prebacivanje"
}
}
},
"name": "Video prebacivanje",
"templates": {
"button-song": "Pesma",
"button-video": "Video"
}
},
"visualizer": {
"description": "Dodaje vizualizaciju u plejer",
"menu": {
"visualizer-type": "Tip vizualizacije"
},
"name": "Vizualizacija"
}
}
}

View File

@ -2,14 +2,14 @@
"common": {
"console": {
"plugins": {
"execute-failed": "Misslyckades med att köra plugin {{pluginName}}::{{contextName}}",
"executed-at-ms": "Plugin {{pluginName}}::{{contextName}} kördes på {{ms}} ms",
"initialize-failed": "Misslyckades med att initialisera pluginen \"{{pluginName}}\"",
"load-all": "Laddar alla pluginer",
"load-failed": "Misslyckades med att ladda pluginen \"{{pluginName}}\"",
"loaded": "Pluginen \"{{pluginName}}\" laddad",
"unload-failed": "Misslyckades med att avlasta pluginen \"{{pluginName}}\"",
"unloaded": "Pluginen \"{{pluginName}}\" avlastad"
"execute-failed": "Misslyckades med att köra tillägget {{pluginName}}::{{contextName}}",
"executed-at-ms": "Tillägget {{pluginName}}::{{contextName}} kördes på {{ms}}ms",
"initialize-failed": "Misslyckades med att initialisera tillägget \"{{pluginName}}\"",
"load-all": "Laddar alla tillägg",
"load-failed": "Misslyckades med att ladda tillägget \"{{pluginName}}\"",
"loaded": "Tillägget \"{{pluginName}}\" laddades in",
"unload-failed": "Kunde inte inaktivera {{pluginName}}-tillägget",
"unloaded": "{{pluginName}}-tillägget inaktiverat"
}
}
},
@ -21,7 +21,7 @@
"main": {
"console": {
"did-finish-load": {
"dev-tools": "Laddning klar. DevTools öppnad"
"dev-tools": "Laddning slutförd. Utvecklarverktyg öppnad"
},
"i18n": {
"loaded": "i18n laddad"
@ -45,16 +45,16 @@
"dialog": {
"hide-menu-enabled": {
"detail": "Menyn är dold, använd 'Alt' för att visa den (eller 'Escape' om du använder inbyggd meny)",
"message": "Dölj Meny är aktiverat",
"title": "Dölj Meny aktiverad"
"message": "Dölj meny är aktiverad",
"title": "Dölj meny aktiverad"
},
"need-to-restart": {
"buttons": {
"later": "Senare",
"restart-now": "Starta om nu"
},
"detail": "\"{{pluginName}}\" pluginen kräver en omstart för att träda i kraft",
"message": "\"{{pluginName}}\" behöver startas om",
"detail": "\"{{pluginName}}\"-tillägget kräver en omstart för att träda i kraft",
"message": "\"{{pluginName}}\"-tillägget behöver startas om",
"title": "Omstart krävs"
},
"unresponsive": {
@ -84,17 +84,17 @@
"label": "Navigering",
"submenu": {
"copy-current-url": "Kopiera nuvarande länk",
"go-back": "Föregående",
"go-forward": "Nästa",
"quit": "Lämna",
"go-back": "Gå tillbaka",
"go-forward": "Gå framåt",
"quit": "Avsluta",
"restart": "Starta om appen"
}
},
"options": {
"label": "Valmöjligheter",
"label": "Alternativ",
"submenu": {
"advanced-options": {
"label": "Avancerade valmöjligheter",
"label": "Avancerade alternativ",
"submenu": {
"auto-reset-app-cache": "Nollställ appcache när appen startar",
"disable-hardware-acceleration": "Stäng av hårdvaruacceleration",
@ -114,60 +114,610 @@
},
"always-on-top": "Alltid överst",
"auto-update": "Uppdatera automatiskt",
"hide-menu": {
"dialog": {
"message": "Menyn kommer att döljas efter omstart, använd [Alt] för att visa menyn (eller [`] vid användning av menyn inuti applikationen)",
"title": "Dölj meny aktiverad"
},
"label": "Dölj meny"
},
"language": {
"dialog": {
"message": "Språket ändras efter omstart",
"title": "Språket har ändrats"
},
"label": "Språk"
"label": "Språk",
"submenu": {
"to-help-translate": "Vill du hjälpa till att översätta? Klicka här"
}
},
"resume-on-start": "Fortsätt spela när appen öppnas"
"resume-on-start": "Fortsätt spela när appen öppnas",
"single-instance-lock": "Lås enskild instans",
"start-at-login": "Starta vid inloggning",
"starting-page": {
"label": "Startsidа",
"unset": "Ej inställt"
},
"tray": {
"label": "Systemfält",
"submenu": {
"disabled": "Inaktiverad",
"enabled-and-hide-app": "Aktiverad och dölj app",
"enabled-and-show-app": "Aktiverad och visa app",
"play-pause-on-click": "Spela/Pausa vid klick"
}
},
"visual-tweaks": {
"label": "Visuella justeringar",
"submenu": {
"custom-window-title": {
"label": "Anpassad titel på fönstret",
"prompt": {
"label": "Ange anpassad fönstertitel: (lämna tomt för att inaktivera)",
"placeholder": "Exempelvis: YouTube Music"
}
},
"like-buttons": {
"default": "Standard",
"force-show": "Tvinga fram visning",
"hide": "Dölj",
"label": "Gilla-knappar"
},
"remove-upgrade-button": "Ta bort knappen för uppgradering",
"theme": {
"dialog": {
"button": {
"cancel": "Avbryt",
"remove": "Ta bort"
},
"remove-theme": "Vill du verkligen radera det anpassade temat?",
"remove-theme-message": "Det här raderar ditt anpassade tema"
},
"label": "Tema",
"submenu": {
"import-css-file": "Importera anpassad CSS-fil",
"no-theme": "Inget tema"
}
}
}
}
}
},
"plugins": {
"enabled": "Aktiverad",
"label": "Tillägg",
"new": "NY"
},
"view": {
"label": "Visa",
"submenu": {
"force-reload": "Tvinga omladdning",
"reload": "Ladda om",
"reset-zoom": "Verklig storlek",
"toggle-fullscreen": "Växla helskärm",
"zoom-in": "Zooma in",
"zoom-out": "Zooma ut"
}
}
},
"tray": {
"next": "Nästa",
"play-pause": "Spela/Pausa",
"previous": "Föregående",
"quit": "Stäng",
"restart": "Starta om appen",
"show": "Visa fönster",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} {{title}}"
}
}
},
"plugins": {
"ad-speedup": {
"description": "Om en annons spelas, tystas ljudet och uppspelningshastigheten sätts till 16×",
"name": "Snabba upp annonser"
},
"adblocker": {
"description": "Blockerar annonser och spårning automatiskt",
"menu": {
"blocker": "Blockerare"
},
"name": "Annonsblockerare"
},
"album-actions": {
"description": "Lägger till knappar för Undislike, Dislike, Like och Unlike för att använda detta på alla spår i en spellista eller ett album",
"name": "Albumåtgärder"
},
"album-color-theme": {
"description": "Använder ett dynamiskt tema och visuella effekter baserat på albumets färgpalett",
"menu": {
"color-mix-ratio": {
"label": "Färgblandningsförhållande",
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Albumfärgtema"
},
"ambient-mode": {
"description": "Ger en ljuseffekt genom att försiktigt kasta färger från videon på skärmens bakgrund",
"menu": {
"blur-amount": {
"label": "Oskärpa",
"submenu": {
"pixels": "{{blurAmount}} pixlar"
}
},
"buffer": {
"label": "Buffert",
"submenu": {
"buffer": "{{buffer}}"
}
},
"opacity": {
"label": "Opacitet",
"submenu": {
"percent": "{{opacity}}%"
}
},
"quality": {
"label": "Kvalitet",
"submenu": {
"pixels": "{{quality}} pixlar"
}
},
"size": {
"label": "Storlek",
"submenu": {
"percent": "{{size}}%"
}
},
"smoothness-transition": {
"label": "Mjuk övergång",
"submenu": {
"during": "Under {{interpolationTime}} s"
}
},
"use-fullscreen": {
"label": "Använder helskärm"
}
},
"name": "Ambiensläge"
},
"amuse": {
"description": "Lägger till stöd för YouTube Music i Amuse Now Playing-widgeten av 6K Labs",
"name": "Amuse",
"response": {
"query": "Amuse API-servern körs. Använd GET /query för att hämta information om låt."
}
},
"api-server": {
"description": "Lägger till en API-server för att styra spelaren",
"dialog": {
"request": {
"buttons": {
"allow": "Tillåt",
"deny": "Avvisa"
},
"message": "Tillåt {{ID}} ({{origin}}) att få åtkomst till API:et?",
"title": "Förfrågan om API-åtkomst"
}
},
"menu": {
"auth-strategy": {
"label": "Metod för åtkomstkontroll",
"submenu": {
"auth-at-first": {
"label": "Ge åtkomst vid första begäran"
},
"none": {
"label": "Ingen åtkomstkontroll"
}
}
},
"hostname": {
"label": "Värdnamn"
},
"port": {
"label": "Port"
}
},
"name": "API-server [Beta]",
"prompt": {
"hostname": {
"label": "Ange värdnamnet (t.ex. 0.0.0.0) för API-servern:",
"title": "Värdnamn"
},
"port": {
"label": "Ange porten för API-servern:",
"title": "Port"
}
}
},
"audio-compressor": {
"description": "Applicera komprimering på ljudet (sänker volymen på de starkaste delarna av signalen och höjer volymen på de svagaste delarna)",
"name": "Ljudkompressor"
},
"auth-proxy-adapter": {
"description": "Stöd för användning av autentiseringsproxy-tjänster",
"menu": {
"disable": "Inaktivera proxy-adapter",
"enable": "Aktivera proxy-adapter",
"hostname": {
"label": "Värdnamn"
},
"port": {
"label": "Port"
}
},
"name": "Adapter För Autentiseringsproxy",
"prompt": {
"hostname": {
"label": "Ange värdnamn för lokal proxyserver (kräver omstart):",
"title": "Proxy-värdnamn"
},
"port": {
"label": "Ange port för lokal proxyserver (kräver omstart):",
"title": "Port för proxy"
}
}
},
"blur-nav-bar": {
"description": "Gör navigeringsfältet transparent och suddigt",
"name": "Suddigt Navigeringsfält"
},
"bypass-age-restrictions": {
"description": "Hoppa över YouTubes åldersverifiering",
"name": "Hoppa Över Åldersbegränsningar"
},
"captions-selector": {
"description": "Välj textning för YouTube Music-ljudspår",
"menu": {
"autoload": "Välj automatiskt senast använda textning",
"disable-captions": "Ingen textning som standard"
},
"name": "Textväljare",
"prompt": {
"selector": {
"label": "Aktuellt textningsspråk: {{language}}",
"none": "Inget",
"title": "Välj textspråk"
}
},
"templates": {
"title": "Öppna textväljaren"
},
"toast": {
"caption-changed": "Textning ändrad till {{language}}",
"caption-disabled": "Textning inaktiverad",
"no-captions": "Inga undertexter tillgängliga för denna låt"
}
},
"compact-sidebar": {
"description": "Sätt alltid sidomenyn i kompakt läge",
"name": "Kompakt Sidomeny"
},
"crossfade": {
"description": "Mjuk övergång mellan låtar",
"menu": {
"advanced": "Avancerat"
},
"name": "Mjuk Övergång [Beta]",
"prompt": {
"options": {
"multi-input": {
"fade-in-duration": "Fade-in-varaktighet (ms)",
"fade-out-duration": "Fade-out-varaktighet (ms)",
"fade-scaling": {
"label": "Fade-skalning",
"linear": "Linjär",
"logarithmic": "Logaritmisk"
},
"seconds-before-end": "Övergång i sekunder före slutet"
},
"title": "Övergångsinställningar"
}
}
},
"custom-output-device": {
"description": "Konfigurera en anpassad utdataenhet för låtar",
"menu": {
"device-selector": "Välj enhet"
},
"name": "Anpassad Utdataenhet",
"prompt": {
"device-selector": {
"label": "Välj den utdataenhet som ska användas",
"title": "Välj utdataenhet"
}
}
},
"disable-autoplay": {
"description": "Starta låt i \"pausat\" läge",
"menu": {
"apply-once": "Gäller endast vid uppstart"
},
"name": "Inaktivera Automatisk Uppspelning"
},
"discord": {
"backend": {
"already-connected": "Försökte ansluta med aktiv anslutning",
"connected": "Ansluten till Discord",
"disconnected": "Frånkopplad från Discord"
},
"description": "Visa dina vänner vad du lyssnar på med Aktivitetsdelning",
"menu": {
"auto-reconnect": "Automatisk återanslutning",
"clear-activity": "Rensa aktivitet",
"clear-activity-after-timeout": "Rensa aktivitet efter tidsgräns",
"connected": "Ansluten",
"disconnected": "Frånkopplad",
"hide-duration-left": "Dölj återstående tid",
"hide-github-button": "Dölj knapp för GitHub-länk",
"play-on-youtube-music": "Spela på YouTube Music",
"set-inactivity-timeout": "Ställ in inaktivitetstid",
"set-status-display-type": {
"label": "Statusmeddelande",
"submenu": {
"artist": "Lyssnar på {artist}",
"title": "Lyssnar på {song title}",
"youtube-music": "Lyssnar på YouTube Music"
}
}
},
"name": "Discord Aktivitetsdelning",
"prompt": {
"set-inactivity-timeout": {
"label": "Ange inaktivitetstid i sekunder:",
"title": "Ställ in inaktivitetstid"
}
}
},
"downloader": {
"backend": {
"dialog": {
"error": {
"buttons": {
"ok": "OK"
},
"message": "Hoppsan! Nedladdningen misslyckades…",
"title": "Fel vid nedladdning!"
},
"start-download-playlist": {
"buttons": {
"ok": "OK"
},
"detail": "({{playlistSize}} låtar)",
"message": "Laddar ner {{playlistTitle}}-spellistan",
"title": "Nedladdning påbörjad"
}
},
"feedback": {
"conversion-progress": "Konvertering: {{percent}}%",
"converting": "Konverterar…",
"done": "Klart: {{filePath}}",
"download-info": "Laddar ner {{artist}} - {{title}} [{{videoId}}",
"download-progress": "Nedladdning: {{percent}}%",
"downloading": "Laddar ner…",
"downloading-counter": "Laddar ner {{current}}/{{total}}…",
"downloading-playlist": "Laddar ner {{playlistTitle}}-spellistan — {{playlistSize}} spår ({{playlistId}})",
"error-while-downloading": "Fel vid nedladdning \"{{author}} - {{title}}\": {{error}}",
"folder-already-exists": "Mappen {{playlistFolder}} finns redan",
"getting-playlist-info": "Hämtar information om spellista…",
"loading": "Laddar…",
"playlist-has-only-one-song": "Spellistan innehåller bara ett objekt. Laddar ner direkt.",
"playlist-id-not-found": "Hittade inget ID för spellista",
"playlist-is-empty": "Spellistan är tom",
"playlist-is-mix-or-private": "Fel vid hämtning av spellisteinformation. Se till att den inte är privat eller en 'Mixed for you'-spellista\n\n{{error}}",
"preparing-file": "Förbereder fil…",
"saving": "Sparar…",
"trying-to-get-playlist-id": "Försöker hämta spelliste-ID: {{playlistId}}",
"video-id-not-found": "Videon hittades inte",
"writing-id3": "Skriver ID3-taggar…"
}
},
"description": "Laddar ner MP3 / originalljud direkt från gränssnittet",
"menu": {
"choose-download-folder": "Välj nedladdningsmapp",
"download-finish-settings": {
"label": "Ladda ner när klart",
"prompt": {
"last-percent": "Efter x procent",
"last-seconds": "Senaste x sekunderna",
"title": "Ställ in när nedladdning ska ske"
},
"submenu": {
"advanced": "Avancerat",
"enabled": "Aktiverad",
"mode": "Tidsläge",
"percent": "Procent",
"seconds": "Sekunder"
}
},
"download-playlist": "Ladda ner spellista",
"presets": "Förinställningar",
"skip-existing": "Hoppa över befintliga filer"
},
"name": "Nedladdare",
"renderer": {
"can-not-update-progress": "Kan inte uppdatera förlopp"
},
"templates": {
"button": "Ladda ner"
}
},
"equalizer": {
"description": "Lägger till en equalizer i spelaren",
"menu": {
"presets": {
"label": "Förinställningar",
"list": {
"bass-booster": "Basförstärkning"
}
}
},
"name": "Equalizer"
},
"exponential-volume": {
"description": "Gör volymreglaget exponentiellt så att det blir lättare att välja lägre volymer.",
"name": "Exponentiell Volym"
},
"in-app-menu": {
"description": "Ger menyrader ett snyggt, mörkt, eller albumfärgat utseende",
"menu": {
"hide-dom-window-controls": "Dölj DOM-fönsterkontroller"
},
"name": "Meny I Appen"
},
"lumiastream": {
"description": "Lägger till stöd för Lumia Stream",
"name": "Lumia Stream [Beta]"
},
"lyrics-genius": {
"description": "Lägger till stöd för texter till de flesta låtar",
"menu": {
"romanized-lyrics": "Romiserade texter"
},
"name": "Texter från Genius",
"renderer": {
"fetched-lyrics": "Hämtade texter från Genius"
}
},
"music-together": {
"description": "Dela en spellista med andra. När värden spelar en låt kommer alla andra höra samma låt",
"dialog": {
"enter-host": "Ange värd-ID"
},
"internal": {
"save": "Spara",
"track-source": "Ljudkälla",
"unknown-user": "Okänd användare"
},
"menu": {
"click-to-copy-id": "Kopiera värd-ID",
"close": "Stäng \"Music Together\"",
"connected-users": "Anslutna användare",
"disconnect": "Koppla från \"Music Together\"",
"empty-user": "Inga anslutna användare",
"host": "Värd för \"Music Together\"",
"join": "Gå med i \"Music Together\"",
"permission": {
"all": "Tillåt gäster att styra spellista och spelare",
"host-only": "Endast värden kan styra spellista och spelare",
"playlist": "Tillåt gäster att styra spellistan"
},
"set-permission": "Ändra behörighet för styrning",
"status": {
"disconnected": "Frånkopplad",
"guest": "Ansluten som gäst",
"host": "Ansluten som värd"
}
},
"name": "Music Together [Beta]",
"toast": {
"add-song-failed": "Misslyckades med att lägga till låt",
"closed": "\"Music Together\" stängdes",
"disconnected": "\"Music Together\" frånkopplad",
"host-failed": "Misslyckades med att vara värd för \"Music Together\"",
"id-copied": "Värd-ID kopierat till urklipp",
"id-copy-failed": "Misslyckades med att kopiera värd-ID till urklipp",
"join-failed": "Misslyckades med att gå med i \"Music Together\"",
"joined": "Gick med i \"Music Together\"",
"permission-changed": "Behörighet för \"Music Together\" ändrad till \"{{permission}}\"",
"remove-song-failed": "Misslyckades med att radera låt",
"user-connected": "{{name}} gick med i \"Music Together\"",
"user-disconnected": "{{name}} lämnade \"Music Together\""
}
},
"navigation": {
"name": "Navigering"
"description": "Direkt integrering av Nästa-/Tillbaka-navigeringspilar i gränssnittet, som i din favoritwebbläsare",
"name": "Navigering",
"templates": {
"back": {
"title": "Gå till föregående sida"
},
"forward": {
"title": "Gå till nästa sida"
}
}
},
"no-google-login": {
"name": "Inget Google Login"
"description": "Ta bort Google-inloggningsknappar och länkar från gränssnittet",
"name": "Ingen Google-inloggning"
},
"notifications": {
"description": "Visa en notis när en låt börjar spelas (interaktiva notiser finns på Windows)",
"menu": {
"interactive": "Interaktiva notiser",
"interactive-settings": {
"label": "Interaktiva inställningar",
"submenu": {
"hide-button-text": "Dölj knapptext",
"refresh-on-play-pause": "Uppdatera vid Play/Pause",
"tray-controls": "Öppna/stäng vid klick i systemfältet"
}
},
"priority": "Notisprioritet",
"toast-style": "Stil för \"toast\"-notiser",
"unpause-notification": "Visa notis när uppspelning återupptas"
},
"name": "Notiser"
},
"performance-improvement": {
"description": "Förbättra prestanda genom att aktivera experimentella skript",
"name": "Prestandaförbättring [Beta]"
},
"picture-in-picture": {
"description": "Tillåter appen att växla till bild-i-bild-läge",
"menu": {
"always-on-top": "Alltid överst",
"hotkey": {
"label": "Snabbkommando",
"prompt": {
"keybind-options": {
"hotkey": "Snabbkommando"
},
"label": "Välj ett snabbkommando för att växla bild-i-bild-läge",
"title": "Bild-I-Bild genväg"
}
}
},
"save-window-position": "Spara fönsterposition",
"save-window-size": "Spara fönsterstorlek",
"use-native-pip": "Använd webbläsarens inbyggda bild-i-bild"
},
"name": "Bild-I-Bild",
"name": "Bild-i-bild",
"templates": {
"button": "Bild-i-bild"
}
},
"playback-speed": {
"description": "Lägger till ett reglage för att ändra uppspelningshastighet",
"name": "Uppspelningshastighet",
"templates": {
"button": "Hasighet"
"button": "Hastighet"
}
},
"precise-volume": {
"description": "Styr ljudstyrkan exakt med mushjul/snabbtangenter, med anpassat skärmlager och justerbara volymsteg",
"menu": {
"arrows-shortcuts": "Kontroller för lokala piltangenter",
"custom-volume-steps": "Ställ in egna volymsteg",
"global-shortcuts": "Globala snabbkommandon"
},
"name": "Noggrann Volymkontroll",
"prompt": {
"global-shortcuts": {
"keybind-options": {
"decrease": "Minska Volym",
"increase": "Öka Volym"
}
"decrease": "Sänk volymen",
"increase": "Öka volymen"
},
"label": "Välj globala kortkommandon för volym:",
"title": "Globala kortkommandon för volym"
},
"volume-steps": {
"label": "Välj volymsteg för ökning/minskning",
"title": "Volymsteg"
}
}
@ -176,54 +726,225 @@
"backend": {
"dialog": {
"quality-changer": {
"detail": "Nuvarande kvalité: {{quality}}",
"message": "Välj Video Kvalité:",
"title": "Välj Video Kvalité"
"detail": "Nuvarande kvalitet: {{quality}}",
"message": "Välj videokvalitet:",
"title": "Välj videokvalitet"
}
}
},
"description": "Tillåter att ändra videokvalitet med en knapp i videons overlay",
"name": "Videokvalitetsväxlare",
"renderer": {
"quality-settings-button": {
"label": "Öppna kvalitetsväxlare för spelaren"
}
}
},
"scrobbler": {
"description": "Lägg till scrobbling-stöd (t.ex. last.fm, Listenbrainz)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Misslyckades att autentisera med Last.fm\nDölj popup-fönstret till nästa omstart.",
"title": "Autentisering misslyckades"
}
}
},
"menu": {
"lastfm": {
"api-settings": "Last.fm API-inställningar"
},
"listenbrainz": {
"token": "Ange ListenBrainz användartoken"
},
"scrobble-alternative-artist": "Använd alternativa artister",
"scrobble-alternative-title": "Använd alternativa titlar",
"scrobble-other-media": "Scrobbla annan media"
},
"name": "Scrobbler",
"prompt": {
"lastfm": {
"api-key": "Last.fm API nyckel"
"api-key": "Last.fm API nyckel",
"api-secret": "Last.fm API-hemlighet"
},
"listenbrainz": {
"token": {
"label": "Ange din ListenBrainz användartoken:",
"title": "ListenBrainz token"
}
}
}
},
"shortcuts": {
"description": "Tillåter inställning av globala kortkommandon för uppspelning (spela/pausa/nästa/föregående) och inaktiverar medie-OSD genom att åsidosätta medietangenter. Aktiverar Ctrl/CMD + F för sökning. Aktiverar Linux MPRIS-stöd för medietangenter och anpassade kortkommandon för avancerade användare",
"menu": {
"override-media-keys": "Åsidosätt medietangenter",
"set-keybinds": "Ställ in globala kontroller för låtar"
},
"name": "Genvägar (& MPRIS)",
"prompt": {
"keybind": {
"keybind-options": {
"next": "Nästa",
"play-pause": "Spela / Pausa",
"previous": "Föregående"
}
},
"label": "Välj globala kortkommandon för kontroll av låtar:",
"title": "Globala kortkommandon"
}
}
},
"skip-disliked-songs": {
"description": "Hoppar över låtar du inte gillar",
"name": "Hoppa Över Låtar Du Inte Gillar"
},
"skip-silences": {
"description": "Hoppa automatiskt över tysta partier i låtar",
"name": "Hoppa Över Tysta Partier"
},
"sponsorblock": {
"description": "Hoppar automatiskt över icke-musikdelar som intro/outro eller delar av musikvideor där ingen musik spelas",
"name": "Blockera Sponsorer"
},
"synced-lyrics": {
"description": "Visar synkroniserade låttexter med hjälp av tjänster som LRClib.",
"errors": {
"fetch": "⚠️ Ett fel uppstod när texterna skulle hämtas.\n\tFörsök igen senare.",
"not-found": "⚠️ Inga texter hittades för denna låt."
},
"menu": {
"default-text-string": {
"label": "Standardtecken mellan låttexter",
"tooltip": "Välj standardtecken att använda för mellanrummet mellan låttexter"
},
"line-effect": {
"label": "Linjeeffekt",
"submenu": {
"fancy": {
"label": "Stiligt",
"tooltip": "Använd stora, app-liknande effekter på den aktuella raden"
},
"focus": {
"label": "Fokus",
"tooltip": "Gör endast den aktuella raden vit"
},
"offset": {
"label": "Förskjutning",
"tooltip": "Förskjut den aktuella raden åt höger"
},
"scale": {
"label": "Skala",
"tooltip": "Skala den aktuella raden"
}
},
"tooltip": "Välj effekt att applicera på den aktuella raden"
},
"precise-timing": {
"label": "Gör låttexterna perfekt synkroniserade",
"tooltip": "Beräkna till millisekunden när nästa rad ska visas (kan ha en liten inverkan på prestanda)"
},
"preferred-provider": {
"label": "Föredragen leverantör",
"none": {
"label": "Ingen",
"tooltip": "Ingen föredragen leverantör"
},
"tooltip": "Välj standardleverantör att använda"
},
"romanization": {
"label": "Romanisera låttexter",
"tooltip": "Om låttexterna är på ett annat språk, försök visa en latinsk version."
},
"show-lyrics-even-if-inexact": {
"label": "Visa låttexter även om de inte är exakta",
"tooltip": "Om låten inte hittas försöker tillägget igen med en annan sökförfrågan.\nResultatet från det andra försöket kanske inte är exakt."
},
"show-time-codes": {
"label": "Visa tidskoder",
"tooltip": "Visa tidskoderna bredvid låttexterna"
}
},
"name": "Synkroniserade Låttexter",
"refetch-btn": {
"fetching": "Hämtar...",
"normal": "Hämta låttexter igen"
},
"warnings": {
"duration-mismatch": "⚠️ - Texterna kan vara osynkroniserade på grund av en skillnad i spårlängd.",
"inexact": "⚠️ - Låttexterna för den här låten kanske inte är exakta",
"instrumental": "⚠️ - Det här är en instrumentallåt"
}
},
"taskbar-mediacontrol": {
"description": "Kontrollera uppspelning från aktivitetsfältet i Windows",
"name": "Mediakontroll i aktivitetsfältet"
},
"touchbar": {
"description": "Lägger till en TouchBar-widget för macOS-användare",
"name": "TouchBar"
},
"transparent-player": {
"description": "Gör appfönstret genomskinligt",
"menu": {
"opacity": {
"label": "Opacitet",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Typ",
"submenu": {
"acrylic": "Akryl",
"mica": "Mica",
"none": "Ingen",
"tabbed": "Flikad"
}
}
},
"name": "Genomskinlig Spelare"
},
"tuna-obs": {
"description": "Integration med OBS-pluginprogrammet Tuna",
"name": "Tuna OBS"
},
"unobtrusive-player": {
"description": "Undviker att spelaren visas när musik spelas",
"name": "Diskret Spelare"
},
"video-toggle": {
"description": "Lägger till en knapp för att växla mellan video/musik-läge. Kan också valfritt ta bort hela videofliken",
"menu": {
"align": {
"label": "Justering",
"submenu": {
"left": "Vänster",
"middle": "Mitten",
"right": "Höger"
}
},
"force-hide": "Tvinga borttagning av videoflik",
"mode": {
"label": "Läge",
"submenu": {
"disabled": "Inaktiverad"
"custom": "Anpassad växling",
"disabled": "Inaktiverad",
"native": "Inbyggd växling"
}
}
},
"name": "Video PÅ/AV",
"templates": {
"button-song": "Låt"
"button-song": "Låt",
"button-video": "Video"
}
},
"visualizer": {
"description": "Lägger till en visualisering i spelaren",
"menu": {
"visualizer-type": "Visualiseringstyp"
},
"name": "Visualiserare"
}
}
}

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "காட்சி மாற்றங்கள்",
"submenu": {
"custom-window-title": {
"label": "தனிப்பயன் சாளர தலைப்பு",
"prompt": {
"label": "தனிப்பயன் சாளர தலைப்பை உள்ளிடவும்: (முடக்க காலியாக விடவும்)",
"placeholder": "எடுத்துக்காட்டு: YouTube இசை"
}
},
"like-buttons": {
"default": "இயல்புநிலை",
"force-show": "படை நிகழ்ச்சி",
@ -381,6 +388,11 @@
},
"templates": {
"title": "திறந்த தலைப்புகள் தேர்வாளர்"
},
"toast": {
"caption-changed": "தலைப்பு {{language}} என மாற்றப்பட்டது",
"caption-disabled": "தலைப்புகள் முடக்கப்பட்டன",
"no-captions": "இந்த பாடலுக்கு தலைப்புகள் எதுவும் கிடைக்கவில்லை"
}
},
"compact-sidebar": {
@ -600,7 +612,15 @@
},
"navigation": {
"description": "உங்களுக்கு பிடித்த உலாவியைப் போலவே இடைமுகத்தில் நேரடியாக ஒருங்கிணைக்கப்பட்ட அடுத்த/பின் வழிசெலுத்தல் அம்புகள்",
"name": "வானோடல்"
"name": "வானோடல்",
"templates": {
"back": {
"title": "முந்தைய பக்கத்திற்குச் செல்"
},
"forward": {
"title": "அடுத்த பக்கத்திற்குச் செல்"
}
}
},
"no-google-login": {
"description": "இடைமுகத்திலிருந்து Google உள்நுழைவு பொத்தான்கள் மற்றும் இணைப்புகளை அகற்று",
@ -692,7 +712,12 @@
}
},
"description": "வீடியோ மேலடுக்கில் ஒரு பொத்தானைக் கொண்டு வீடியோ தரத்தை மாற்ற அனுமதிக்கிறது",
"name": "வீடியோ தர மாற்றி"
"name": "வீடியோ தர மாற்றி",
"renderer": {
"quality-settings-button": {
"label": "திறந்த பிளேயர் தர மாற்றி"
}
}
},
"scrobbler": {
"description": "ச்க்ரோப்ளிங் ஆதரவைச் சேர் (last.fm, Listenbrainz முதலியன)",
@ -859,7 +884,8 @@
},
"name": "வீடியோ மாற்று",
"templates": {
"button-song": "பாடல்"
"button-song": "பாடல்",
"button-video": "காணொளி"
}
},
"visualizer": {

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "ปรับแต่งหน้าตาแอป",
"submenu": {
"custom-window-title": {
"label": "ชื่อหน้าต่างกำหนดเอง",
"prompt": {
"label": "กำหนดชื่อหน้าต่างที่ต้องการ: (ปล่อยว่างเพื่อปิดใช้งาน)",
"placeholder": "ตัวอย่าง: Youtube Music"
}
},
"like-buttons": {
"default": "ค่าเริ่มต้น",
"force-show": "บังคับให้แสดง",
@ -381,6 +388,11 @@
},
"templates": {
"title": "เปิดตัวเลือกคำบรรยาย"
},
"toast": {
"caption-changed": "เปลี่ยนคำบรรยายเป็นภาษา {{language}}",
"caption-disabled": "คำบรรยายถูกปิดใช้งาน",
"no-captions": "ไม่มีคำบรรยายสำหรับเพลงนี้"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "ตั้งค่าอุปกรณ์เสียงออกสำหรับเพลง",
"menu": {
"device-selector": "เลือกอุปกรณ์"
},
"name": "อุปกรณ์เสียงออกที่กำหนดเอง",
"prompt": {
"device-selector": {
"label": "เลือกอุปกรณ์เสียงออกที่ต้องการใช้",
"title": "เลือกอุปกรณ์เสียงออก"
}
}
},
"disable-autoplay": {
"description": "เริ่มเพลงในโหมดหยุดชั่วคราว",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "ซ่อนระยะเวลาที่เหลือ",
"hide-github-button": "ซ่อนปุ่มลิงก์ GitHub",
"play-on-youtube-music": "เล่นบน YouTube Music",
"set-inactivity-timeout": "ตั้งระยะเวลาไม่มีกิจกรรม"
"set-inactivity-timeout": "ตั้งระยะเวลาไม่มีกิจกรรม",
"set-status-display-type": {
"label": "ข้อความสถานะ",
"submenu": {
"artist": "กำลังฟัง {ชื่อนักร้อง}",
"title": "กำลังฟัง {ชื่อเพลง}",
"youtube-music": "กำลังฟัง YouTube Music"
}
}
},
"name": "แสดงกิจกรรมบนดิสคอร์ด",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "ลูกศรนำทางถัดไป/ย้อนกลับรวมอยู่ในอินเทอร์เฟซโดยตรง เช่นเดียวกับในเบราว์เซอร์ที่คุณชื่นชอบ",
"name": "การนำทาง"
"name": "การนำทาง",
"templates": {
"back": {
"title": "ไปหน้าก่อนหน้า"
},
"forward": {
"title": "ไปหน้าถัดไป"
}
}
},
"no-google-login": {
"description": "ลบปุ่มเข้าสู่ระบบ Google และลิงก์ออกจากอินเทอร์เฟซ",
@ -692,7 +733,12 @@
}
},
"description": "อนุญาตให้เปลี่ยนคุณภาพของวิดีโอด้วยปุ่มที่แสดงเหนือวิดีโอ",
"name": "ที่เปลี่ยนคุณภาพวิดีโอ"
"name": "ที่เปลี่ยนคุณภาพวิดีโอ",
"renderer": {
"quality-settings-button": {
"label": "เปิดตัวเปลี่ยนคุณภาพเครื่องเล่น"
}
}
},
"scrobbler": {
"description": "รองรับการบันทึกการเล่นเพลง (เช่น last.fm, Listenbrainz)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "ใส่ user token ของ ListenBrainz"
},
"scrobble-alternative-artist": "ใช้ชื่อศิลปินอื่น",
"scrobble-alternative-title": "ใช้ชื่ออื่น",
"scrobble-other-media": "บันทึกการเล่นสื่ออื่นๆ"
},
@ -796,6 +843,14 @@
"label": "ให้เนื้อเพลงตรงกับเพลงเป๊ะๆ",
"tooltip": "คำนวณมิลิวินาทีในการแสดงบรรทัดถัดไป (มีผลเล็กน้อยกับประสิทธิภาพการทำงาน)"
},
"preferred-provider": {
"label": "ผู้ให้บริการที่ต้องการ",
"none": {
"label": "ไม่มี",
"tooltip": "ไม่มีผู้ให้บริการที่ต้องการ"
},
"tooltip": "เลือกผู้ให้บริการที่ต้องการใช้งาน"
},
"romanization": {
"label": "เนื้อเพลงตัวด้วยอักษรโรมัน",
"tooltip": "ถ้าหากเนื้อเพลงอยู่ในภาษาอื่น ลองเปลี่ยนการแสดงผลโดยใช้เวอร์ชั่นลาติน"
@ -828,6 +883,27 @@
"description": "เพิ่ม Widget บน TouchBar สำหรับผู้ใช้ macOS",
"name": "TouchBar"
},
"transparent-player": {
"description": "ทำให้หน้าต่างของแอปโปร่งใส",
"menu": {
"opacity": {
"label": "ความทึบแสง",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "ประเภท",
"submenu": {
"acrylic": "อะคริลิก",
"mica": "ไมกา",
"none": "ไม่มี",
"tabbed": "Tabbed"
}
}
},
"name": "ที่เล่นเพลงโปร่งใส"
},
"tuna-obs": {
"description": "ใช้งานร่วมกันกับปลั้กอิน Tuna บน OBS",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "ปุ่มวิดีโอ",
"templates": {
"button-song": "เพลง"
"button-song": "เพลง",
"button-video": "วิดีโอ"
}
},
"visualizer": {

View File

@ -36,7 +36,7 @@
"details": "Yanıt verilmedi!\n{{error}}"
},
"when-ready": {
"clearing-cache-after-20s": "Uygulama ön belleği temizleme"
"clearing-cache-after-20s": "Uygulama ön belleği temizle"
},
"window": {
"tried-to-render-offscreen": "Pencere ekranın dışında oluşturulmaya çalışıldı, windowSize={{windowSize}}, displaySize={{displaySize}}, position={{position}}"
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Görsel İnce Ayarlar",
"submenu": {
"custom-window-title": {
"label": "Özel pencere başlığı",
"prompt": {
"label": "Özel pencere başlığı girin: (devre dışı bırakmak için boş bırakın)",
"placeholder": "Örnek: Youtube Music"
}
},
"like-buttons": {
"default": "Varsayılan",
"force-show": "Zorla göster",
@ -209,7 +216,7 @@
"plugins": {
"ad-speedup": {
"description": "Bir reklam oynatılırsa sesi kapatır ve oynatma hızını 16x olarak ayarlar",
"name": "Hızlandırma"
"name": "Reklam Hızlandırma"
},
"adblocker": {
"description": "Tüm reklamları ve izleyicileri engelle",
@ -287,7 +294,7 @@
}
},
"api-server": {
"description": "APİ ekle ve oynatıcıyı kontrol et",
"description": "Oynatıcıyı kontrol etmek için bir API sunucusu ekle",
"dialog": {
"request": {
"buttons": {
@ -321,7 +328,7 @@
"prompt": {
"hostname": {
"label": "API sunucusu için hostname (örneğin 0.0.0.0) girin:",
"title": "Hostname"
"title": "Hostname(Ana bilgisayar adı)"
},
"port": {
"label": "API sunucusu için port girin:",
@ -381,6 +388,11 @@
},
"templates": {
"title": "Altyazı seçiciyi aç"
},
"toast": {
"caption-changed": "Başlık {{language}} olarak değiştirildi",
"caption-disabled": "Altyazılar devre dışı",
"no-captions": "Bu şarkı için altyazı mevcut değil"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "Şarkılar için özel bir medya çıkış aygıtı ayarlayın",
"menu": {
"device-selector": "Aygıt Seçin"
},
"name": "Özel Çıkış Aygıtı",
"prompt": {
"device-selector": {
"label": "Kullanılacak medya çıkış aygıtını seçin",
"title": ıkış Aygıtını Seçin"
}
}
},
"disable-autoplay": {
"description": "Şarkıların otomatik olarak duraklatılmasını sağlar",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "Kalan süreyi gizle",
"hide-github-button": "GitHub bağlantısını gizle",
"play-on-youtube-music": "YouTube Music de oynat",
"set-inactivity-timeout": "Hareketsizlik zaman aşımını ayarla"
"set-inactivity-timeout": "Hareketsizlik zaman aşımını ayarla",
"set-status-display-type": {
"label": "Durum metni",
"submenu": {
"artist": "{artist} Dinleniyor",
"title": "{song title} Dinleniyor",
"youtube-music": "YouTube Müzik Dinleniyor"
}
}
},
"name": "Discord Etkinlik Durumu",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "Favori tarayıcınızdaki gibi doğrudan arayüze entegre edilmiş İleri/Geri gezinme okları",
"name": "Navigasyon"
"name": "Navigasyon",
"templates": {
"back": {
"title": "Önceki sayfaya git"
},
"forward": {
"title": "Sonraki sayfaya geç"
}
}
},
"no-google-login": {
"description": "Google giriş düğmelerini ve bağlantılarını arayüzden kaldır",
@ -692,7 +733,12 @@
}
},
"description": "Video katmanı üzerindeki bir düğme ile video kalitesinin değiştirilmesine izin verir",
"name": "Video Kalitesi Değiştirici"
"name": "Video Kalitesi Değiştirici",
"renderer": {
"quality-settings-button": {
"label": "Açık oynatıcı kalite değiştirici"
}
}
},
"scrobbler": {
"description": "Listeleme desteği ekler (lastfm, listenbrainz ve benzeri)",
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "ListenBrainz kullanıcı kimliğinizi girin"
},
"scrobble-alternative-artist": "Alternatif sanatçıları kullan",
"scrobble-alternative-title": "Alternatif başlıklar kullan",
"scrobble-other-media": "Diğer medya ortamlarında listele"
},
@ -796,6 +843,14 @@
"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)"
},
"preferred-provider": {
"label": "Tercih edilen Sağlayıcı",
"none": {
"label": "Hiçbiri",
"tooltip": "Varsayılan sağlayıcı yok"
},
"tooltip": "Kullanmak İçin varsayılan sağlayıcıyı seçin"
},
"romanization": {
"label": "Sözleri Romanize Et",
"tooltip": "Sözler başka bir dilde gözüküyorsa, Latin versiyonunu dene."
@ -828,6 +883,27 @@
"description": "macOS kullanıcıları için bir TouchBar widget'ı ekler",
"name": "TouchBar"
},
"transparent-player": {
"description": "Uygulama penceresini şeffaf yapar",
"menu": {
"opacity": {
"label": "Opaklık",
"submenu": {
"percent": "%{{opacity}}"
}
},
"type": {
"label": "Tür",
"submenu": {
"acrylic": "Akrilik",
"mica": "Mika",
"none": "Hiçbiri",
"tabbed": "Sekmeli"
}
}
},
"name": "Şeffaf Oynatıcı"
},
"tuna-obs": {
"description": "OBS eklentisi Tuna ile entegrasyon sağlar",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "Video Geçiş",
"templates": {
"button-song": "Şarkı"
"button-song": "Şarkı",
"button-video": "Video"
}
},
"visualizer": {

View File

@ -30,7 +30,7 @@
"receive-command": "Đã nhận được lệnh qua giao thức: \"{{command}}\""
},
"theme": {
"css-file-not-found": "Tệp tin CSS \"{{cssFile}}\"không tồn tại, đang bỏ qua"
"css-file-not-found": "Tệp CSS \"{{cssFile}}\" không tồn tại, đang bỏ qua"
},
"unresponsive": {
"details": "Lỗi không phản hồi!\n{{error}}"
@ -44,7 +44,7 @@
},
"dialog": {
"hide-menu-enabled": {
"detail": "Menu đã ẩn, ấn phím 'Alt' để hiện menu (hoặc ấn 'Escape' nếu bạn đang bật In-app Menu)",
"detail": "Menu đã ẩn, ấn phím 'Alt' để hiện menu (hoặc ấn phím 'Esc' nếu bạn đang bật In-app Menu)",
"message": "Ẩn Menu đã được bật",
"title": "Ẩn Menu đã được bật"
},
@ -53,7 +53,7 @@
"later": "Để sau",
"restart-now": "Khởi động lại ngay"
},
"detail": "Tiện ích mở rộng \"{{pluginName}}\" yêu cầu khởi động lại ứng dụng để áp dụng",
"detail": "Phần mở rộng \"{{pluginName}}\" yêu cầu khởi động lại ứng dụng để áp dụng",
"message": "\"{{pluginName}}\" cần khởi động lại",
"title": "Yêu cầu khởi động lại"
},
@ -74,7 +74,7 @@
"ok": "Đồng ý"
},
"detail": "Đã có phiên bản mới hơn, bạn có thể tải xuống tại {{downloadLink}}",
"message": "Đã có phiên bản mới",
"message": "Đã có một phiên bản mới",
"title": "Cập nhật có sẵn"
}
},
@ -96,7 +96,7 @@
"advanced-options": {
"label": "Tùy chọn nâng cao",
"submenu": {
"auto-reset-app-cache": "Làm mới bộ nhớ đệm khi khởi động ứng dụng",
"auto-reset-app-cache": "Làm mới bộ nhớ đệm khi mở ứng dụng",
"disable-hardware-acceleration": "Vô hiệu hóa tăng tốc phần cứng",
"edit-config-json": "Chỉnh sửa config.json",
"override-user-agent": "Ghi đè User-Agent",
@ -106,7 +106,7 @@
"prompt": {
"label": "Nhập địa chỉ Proxy: (để trống nếu muốn tắt)",
"placeholder": "Ví dụ: SOCKS5://127.0.0.1:9999",
"title": "Cài proxy"
"title": "Cài đặt proxy"
}
},
"toggle-dev-tools": "Bật/tắt DevTools"
@ -116,19 +116,19 @@
"auto-update": "Tự động cập nhật",
"hide-menu": {
"dialog": {
"message": "Menu sẽ bị ẩn khi ứng dụng được chạy vào lần tới, dùng phím [Alt] để hiện nó (hoặc phím [`] nếu sử dụng in-app-menu)",
"message": "Menu sẽ bị ẩn trong lần khởi chạy tiếp theo, dùng phím [Alt] để hiện nó (hoặc phím [`] nếu sử dụng in-app-menu)",
"title": "Ẩn Menu đã được bật"
},
"label": "Ẩn Menu"
},
"language": {
"dialog": {
"message": "Ngôn ngữ sẽ được thay đổi sau khi ứng dụng khởi động lại",
"message": "Ngôn ngữ sẽ được thay đổi sau khi khởi động lại ứng dụng",
"title": "Ngôn ngữ đã thay đổi"
},
"label": "Ngôn ngữ",
"submenu": {
"to-help-translate": "Bạn muốn giúp dịch? Bấm vào đây"
"to-help-translate": "Bạn muốn hỗ trợ dịch? Bấm vào đây"
}
},
"resume-on-start": "Tiếp tục bài hát cuối cùng khi ứng dụng khởi động",
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Tinh chỉnh hình ảnh",
"submenu": {
"custom-window-title": {
"label": "Tiêu đề cửa sổ tùy chỉnh",
"prompt": {
"label": "Nhập tiêu đề cửa sổ tùy chỉnh: (để trống để vô hiệu hóa)",
"placeholder": "Ví dụ: Youtube Music"
}
},
"like-buttons": {
"default": "Mặc định",
"force-show": "Tập trung hiển thị",
@ -163,7 +170,7 @@
"cancel": "Hủy",
"remove": "Loại bỏ"
},
"remove-theme": "Bạn có chắc muốn loại bỏ chủ đề tùy chỉnh không?",
"remove-theme": "Bạn có chắc muốn loại bỏ chủ đề tùy chỉnh này không?",
"remove-theme-message": "Tùy chọn này sẽ loại bỏ chủ đề tùy chỉnh"
},
"label": "Chủ đề",
@ -186,7 +193,7 @@
"submenu": {
"force-reload": "Buộc tải lại",
"reload": "Tải lại",
"reset-zoom": "Kích thước thực",
"reset-zoom": "Đặt lại",
"toggle-fullscreen": "Bật chế độ toàn màn hình",
"zoom-in": "Phóng to",
"zoom-out": "Thu nhỏ"
@ -202,7 +209,7 @@
"show": "Hiện cửa sổ",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
"with-song-info": "YouTube Music: {{title}} - {{artist}}"
}
}
},
@ -219,7 +226,7 @@
"name": "Chặn quảng cáo"
},
"album-actions": {
"description": "Thêm nút hủy không thích, không thích, thích và không thích để áp dụng cho tất cả danh sách phát hoặc album",
"description": "Thêm nút Hủy không thích, Không thích, Thích và Hủy thích để áp dụng cho tất cả bài hát trong danh sách phát hoặc album",
"name": "Tác vụ với album"
},
"album-color-theme": {
@ -280,7 +287,7 @@
"name": "Chế độ Môi trường xung quanh"
},
"amuse": {
"description": "Thêm hỗ trợ YouTube Music cho tiện ích hiển thị bài hát đang phát Amuse của 6K Labs.",
"description": "Thêm hỗ trợ YouTube Music cho tiện ích hiển thị bài hát đang phát Amuse của 6K Labs",
"name": "Amuse",
"response": {
"query": "Máy chủ API của Amuse đang chạy. GET /query để lấy thông tin về bài hát."
@ -317,7 +324,7 @@
"label": "Cổng"
}
},
"name": "Máy chủ API [Beta]",
"name": "Máy chủ API [Thử nghiệm]",
"prompt": {
"hostname": {
"label": "Điền tên máy chủ (như 0.0.0.0) cho máy chủ API:",
@ -348,7 +355,7 @@
"name": "Bộ chuyển đổi xác minh máy chủ Proxy",
"prompt": {
"hostname": {
"label": "Nhập tên của máy chủ proxy lân cận (bắt buộc khởi động lại ứng dụng):",
"label": "Nhập tên của máy chủ proxy lân cận (yêu cầu khởi động lại ứng dụng):",
"title": "Tên máy chủ Proxy"
},
"port": {
@ -369,7 +376,7 @@
"description": "Bộ lựa chọn phụ đề cho các bài hát trên Youtube Music",
"menu": {
"autoload": "Tự động chọn phụ đề vừa sử dụng",
"disable-captions": "Không có phụ đề đặt làm mặc định"
"disable-captions": "Không có phụ đề làm mặc định"
},
"name": "Bộ lựa chọn phụ đề",
"prompt": {
@ -381,10 +388,15 @@
},
"templates": {
"title": "Mở lựa chọn phụ đề"
},
"toast": {
"caption-changed": "Phụ đề đã chuyển sang {{language}}",
"caption-disabled": "Tắt phụ đề",
"no-captions": "Không có phụ đề nào cho bài hát này"
}
},
"compact-sidebar": {
"description": "Luôn đặt thanh bên cạnh ở chế độ thu gọn",
"description": "Luôn đặt thanh bên ở chế độ thu gọn",
"name": "Thanh bên thu gọn"
},
"crossfade": {
@ -392,12 +404,12 @@
"menu": {
"advanced": "Nâng cao"
},
"name": "Xen kẽ [thử nghiệm]",
"name": "Xen kẽ [Thử nghiệm]",
"prompt": {
"options": {
"multi-input": {
"fade-in-duration": "Xuất hiện mờ dần trong khoảng thời gian (ms)",
"fade-out-duration": "Khoảng thời gian hoát ra mờ dần (ms)",
"fade-in-duration": "Thời lượng mờ dần vào (ms)",
"fade-out-duration": "Thời lượng mờ dần ra (ms)",
"fade-scaling": {
"label": "Làm mờ theo tỉ lệ",
"linear": "Trực tuyến",
@ -409,10 +421,23 @@
}
}
},
"disable-autoplay": {
"description": "Bắt đầu bài hát khi ở chế độ \"tạm dừng\"",
"custom-output-device": {
"description": "Cài đặt cho thiết bị đầu ra tùy chỉnh cho bài hát",
"menu": {
"apply-once": "Áp dụng khi khởi động"
"device-selector": "Chọn thiết bị"
},
"name": "Thiết bị đầu ra tùy chỉnh",
"prompt": {
"device-selector": {
"label": "Chọn thiết bị phát làm đầu ra để dùng",
"title": "Chọn thiết bị đầu ra"
}
}
},
"disable-autoplay": {
"description": "Làm nhạc bắt đầu ở chế độ \"tạm dừng\". Ngoài ra có thể dừng nhạc khi khởi động ứng dụng (nếu có bật tính năng \"Tiếp tục bài hát cuối cùng khi ứng dụng khởi động\")",
"menu": {
"apply-once": "Chỉ áp dụng khi khởi động"
},
"name": "Tắt tự động phát"
},
@ -432,9 +457,17 @@
"hide-duration-left": "Ẩn thời lượng còn lại",
"hide-github-button": "Ẩn nút liên kết GitHub",
"play-on-youtube-music": "Phát trong Youtube Music",
"set-inactivity-timeout": "Đặt thời gian chờ không hoạt động"
"set-inactivity-timeout": "Đặt thời gian chờ không hoạt động",
"set-status-display-type": {
"label": "Văn bản trạng thái",
"submenu": {
"artist": "Đang nghe nhạc của {artist}",
"title": "Đang nghe nhạc {song title}",
"youtube-music": "Đang nghe Youtube Music"
}
}
},
"name": "Discord Rich Presence",
"name": "Tích hợp trạng thái Discord",
"prompt": {
"set-inactivity-timeout": {
"label": "Nhập thời gian chờ không hoạt động tính bằng giây:",
@ -477,8 +510,8 @@
"playlist-has-only-one-song": "Danh sách phát chỉ có một mục, tải trực tiếp",
"playlist-id-not-found": "Không tìm thấy ID danh sách phát",
"playlist-is-empty": "Danh sách phát trống",
"playlist-is-mix-or-private": "Lỗi lấy thông tin danh sách phát: đảm bảo danh sách phát không ở chế độ riêng tư hoặc danh sách phát \"Dành cho bạn\"\n\n{{error}}",
"preparing-file": "Đang chuẩn bị thư mục…",
"playlist-is-mix-or-private": "Lỗi lấy thông tin danh sách phát: hãy đảm bảo danh sách phát không ở chế độ riêng tư hoặc danh sách phát \"Dành cho bạn\"\n\n{{error}}",
"preparing-file": "Đang chuẩn bị tệp…",
"saving": "Đang lưu…",
"trying-to-get-playlist-id": "Đang lấy ID danh sách phát: {{playlistId}}",
"video-id-not-found": "Không tìm thấy video",
@ -504,8 +537,8 @@
}
},
"download-playlist": "Tải danh sách phát",
"presets": "Cài đặt sẵn",
"skip-existing": "Bỏ qua các tập tin hiện có"
"presets": "Tùy chọn định dạng",
"skip-existing": "Bỏ qua các tập tin đã có"
},
"name": "Trình tải xuống",
"renderer": {
@ -516,15 +549,16 @@
}
},
"equalizer": {
"description": "Thêm bộ cân bằng âm thanh o trình phát nhạc.",
"description": "Thêm bộ chỉnh âm để điều chỉnh âm thanh cho trình phát nhạc",
"menu": {
"presets": {
"label": "Thiết lập có sẵn",
"list": {
"bass-booster": "Bộ tăng âm trầm"
"bass-booster": "Tăng âm trầm"
}
}
},
"name": "Cân bằng âm thanh"
"name": "Bộ chỉnh âm"
},
"exponential-volume": {
"description": "Làm cho thanh trượt âm lượng theo cấp số nhân để dễ dàng chọn âm lượng thấp hơn.",
@ -544,7 +578,7 @@
"lyrics-genius": {
"description": "Thêm hỗ trợ lời bài hát cho hầu hết các bài hát",
"menu": {
"romanized-lyrics": "Lời bài hát La Mã"
"romanized-lyrics": "Chuyển lời bài hát sang chữ Latin"
},
"name": "Lời bài hát từ Genius",
"renderer": {
@ -599,7 +633,15 @@
},
"navigation": {
"description": "Mũi tên điều hướng Tiếp theo/Quay lại được tích hợp trực tiếp trong giao diện, giống như trong trình duyệt yêu thích của bạn",
"name": "Điều hướng"
"name": "Điều hướng",
"templates": {
"back": {
"title": "Đi đến trang trước"
},
"forward": {
"title": "Đi đến trang tiếp theo"
}
}
},
"no-google-login": {
"description": "Xóa các nút và liên kết đăng nhập Google khỏi giao diện",
@ -613,7 +655,7 @@
"label": "Cài đặt tương tác",
"submenu": {
"hide-button-text": "Ẩn tên nút",
"refresh-on-play-pause": "Làm mới khi phát/tạm dừng",
"refresh-on-play-pause": "Làm mới khi Phát/Tạm dừng",
"tray-controls": "Mở/Đóng khi nhấp vào khay"
}
},
@ -625,20 +667,20 @@
},
"performance-improvement": {
"description": "Cải thiện hiệu suất thông qua kích hoạt scripts thử nghiệm",
"name": "Cải thiện hiệu năng [Beta]"
"name": "Cải thiện hiệu năng [Thử nghiệm]"
},
"picture-in-picture": {
"description": "Cho phép chuyển ứng dụng sang chế độ ảnh trong ảnh",
"menu": {
"always-on-top": "Luôn ở trên cùng",
"hotkey": {
"label": "Phím nóng",
"label": "Phím tắt",
"prompt": {
"keybind-options": {
"hotkey": "Phím nóng"
"hotkey": "Phím tắt"
},
"label": "Chọn phím nóng để chuyển đổi ảnh trong ảnh",
"title": "Phím nóng ảnh trong ảnh"
"label": "Chọn phím tắt để chuyển đổi ảnh trong ảnh",
"title": "Phím tắt ảnh trong ảnh"
}
},
"save-window-position": "Lưu vị trí cửa sổ",
@ -686,19 +728,24 @@
"quality-changer": {
"detail": "Chất lượng hiện tại: {{quality}}",
"message": "Chọn chất lượng video:",
"title": "Chọn chất lượng video:"
"title": "Chọn chất lượng video"
}
}
},
"description": "Cho phép thay đổi chất lượng video bằng một nút trên lớp phủ video",
"name": "Thay đổi chất lượng video"
"name": "Thay đổi chất lượng video",
"renderer": {
"quality-settings-button": {
"label": "Mở trình thay đổi chất lượng"
}
}
},
"scrobbler": {
"description": "Thêm hỗ trợ scrobbling (v.v. Last.fm, Listenbrainz)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Không thể xác minh với \nẨn thông báo cho đến lần bật ứng dụng tiếp theo.",
"message": "Không thể xác minh với Last.fm \nẨn thông báo cho đến lần bật ứng dụng tiếp theo.",
"title": "Xác minh thất bại"
}
}
@ -710,6 +757,7 @@
"listenbrainz": {
"token": "Nhập mã người dùng ListenBrainz"
},
"scrobble-alternative-artist": "Dùng nghệ sĩ thay thế",
"scrobble-alternative-title": "Dùng tiêu đề thay thế",
"scrobble-other-media": "Scrobber nội dung khác"
},
@ -747,45 +795,46 @@
}
},
"skip-disliked-songs": {
"description": "Bỏ qua những bài hát không thích",
"name": "Bỏ qua những bài hát không thích"
"description": "Tự động bỏ qua những bài hát bạn nhấn không thích",
"name": "Bỏ qua bài hát không thích"
},
"skip-silences": {
"description": "Tự động bỏ qua các đoạn im lặng trong bài hát",
"name": "Bỏ qua đoạn im lặng"
},
"sponsorblock": {
"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",
"description": "Tự động bỏ qua các phần không phải âm nhạc như phần intro/outro hoặc các phần không được phát của video nhạc",
"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.",
"description": "Cung cấp lời được đồng bộ với bài hát, sử dụng các nhà cung cấp như LRClib.",
"errors": {
"fetch": "⚠️\t\tĐã xảy ra lỗi khi tìm lời bài hát.\n\tVui 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",
"label": "Kí tự 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",
"label": "Kiểu lời nhạc",
"submenu": {
"fancy": {
"label": "Màu mè"
"label": "Màu mè",
"tooltip": "Làm đoạn lời nhạc đang nghe to hơn và nổi bật hơn"
},
"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"
"label": "Lệch",
"tooltip": "Làm dòng hiện tại lệch sang bên phải"
},
"scale": {
"label": "Tỉ lệ",
"tooltip": "Áp dng tỉ lệ cho dòng hiện tại"
"label": "Phóng to",
"tooltip": "Làm dòng hiện tại to hơn các dòng khác"
}
},
"tooltip": "Chọn kiểu để áp dụng cho dòng hiện tại"
@ -794,6 +843,14 @@
"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)"
},
"preferred-provider": {
"label": "Nhà cung cấp ưa thích",
"none": {
"label": "Không có",
"tooltip": "Không có nhà cung cấp ưu thích"
},
"tooltip": "Chọn nhà cung cấp lời bài hát mặc định để sử dụng"
},
"romanization": {
"label": "Chuyển lời bài hát sang chữ Latin",
"tooltip": "Nếu lời bài hát đang ở ngôn ngữ khác, thử hiển thị phiên bản bảng chữ cái La-tinh."
@ -815,27 +872,48 @@
"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í"
"instrumental": "⚠️ - Đây là một bài hát không lời"
}
},
"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ụ"
"description": "Điều khiển nhạc từ cửa sổ xem trước trên thanh tác vụ Windows của bạn",
"name": "Điều khiển phương tiện trên thanh tác vụ"
},
"touchbar": {
"description": "Thêm tiện ích TouchBar cho người dùng macOS",
"name": "TouchBar"
},
"transparent-player": {
"description": "Làm cho cửa sổ ứng dụng có hiệu ứng trong suốt",
"menu": {
"opacity": {
"label": "Độ mờ",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "Kiểu nền",
"submenu": {
"acrylic": "Acrylic",
"mica": "Mica",
"none": "Không có",
"tabbed": "Tabbed"
}
}
},
"name": "Trình phát trong suốt"
},
"tuna-obs": {
"description": "Tích hợp với plugin Tuna của OBS",
"name": "Tuna OBS"
},
"unobtrusive-player": {
"description": "Ngăn trình phát nhạc xuất hiện đột ngột khi phát một bài hát.",
"name": "Trình phát nhạc ẩn"
"description": "Ngăn trình phát nhạc xuất hiện đột ngột khi phát một bài hát",
"name": "Không hiện trình phát nhạc khi phát"
},
"video-toggle": {
"description": "Thêm nút để chuyển giữa chế độ Video/Bài hát. Cũng có thể tùy ý xóa toàn bộ tab video",
"description": "Thêm nút để chuyển giữa chế độ Video/Bài hát. Cũng có thể ẩn toàn bộ video",
"menu": {
"align": {
"label": "Căn chỉnh",
@ -845,27 +923,28 @@
"right": "Phải"
}
},
"force-hide": "Buộc loại bỏ tab video",
"force-hide": "Buộc ẩn video",
"mode": {
"label": "Chế độ",
"submenu": {
"custom": "Chuyển đổi tùy chỉnh",
"custom": "Tùy chỉnh",
"disabled": "Vô hiệu hoá",
"native": "Chuyển đổi gốc"
"native": "Gốc"
}
}
},
"name": "Chuyển đổi video",
"templates": {
"button-song": "Bài hát"
"button-song": "Bài hát",
"button-video": "Video"
}
},
"visualizer": {
"description": "Thêm trình hiển th cho trình phát",
"description": "Hiển thị sóng nhạc thay thế cho video (hay \"Music visualizer\")",
"menu": {
"visualizer-type": "Loại trình hiển thị"
"visualizer-type": "Loại Sóng nhạc"
},
"name": "Trình hiển thị"
"name": "Sóng nhạc"
}
}
}

View File

@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "视觉调整",
"submenu": {
"custom-window-title": {
"label": "自定义窗口标题",
"prompt": {
"label": "输入自定义窗口标题:(留空表示停用)",
"placeholder": "示例YouTube Music"
}
},
"like-buttons": {
"default": "默认",
"force-show": "强制显示",
@ -414,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "配置歌曲的自定义输出媒体设备",
"menu": {
"device-selector": "选择设备"
},
"name": "自定义输出设备",
"prompt": {
"device-selector": {
"label": "选择要使用的输出媒体设备",
"title": "选择输出设备"
}
}
},
"disable-autoplay": {
"description": "让曲目开始时处于 “暂停” 模式",
"menu": {
@ -437,7 +457,15 @@
"hide-duration-left": "隐藏剩余时长",
"hide-github-button": "隐藏 GitHub 链接按钮",
"play-on-youtube-music": "转至 YouTube Music 播放",
"set-inactivity-timeout": "设置非活跃时长"
"set-inactivity-timeout": "设置非活跃时长",
"set-status-display-type": {
"label": "状态文本",
"submenu": {
"artist": "在听 {artist}",
"title": "在听 {song title}",
"youtube-music": "在听 YouTube Music"
}
}
},
"name": "Discord Rich Presence 状态显示",
"prompt": {
@ -729,6 +757,7 @@
"listenbrainz": {
"token": "输入 ListenBrainz 用户令牌"
},
"scrobble-alternative-artist": "使用替代艺术家",
"scrobble-alternative-title": "使用替代标题",
"scrobble-other-media": "记录其他媒体文件"
},
@ -814,6 +843,14 @@
"label": "让滚动歌词完全同步",
"tooltip": "以毫秒精度估算下句歌词的显示时间(可能对性能有小幅影响)"
},
"preferred-provider": {
"label": "首选歌词源",
"none": {
"label": "无",
"tooltip": "没有首选的歌词源"
},
"tooltip": "选择默认要用的源"
},
"romanization": {
"label": "将歌词罗马化",
"tooltip": "如果歌词以不同语言显示,试着展示拉丁字母版本。"
@ -846,6 +883,27 @@
"description": "为 macOS 用户启用 TouchBar 支持",
"name": "TouchBar"
},
"transparent-player": {
"description": "把应用窗口变透明",
"menu": {
"opacity": {
"label": "不透明",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "类型",
"submenu": {
"acrylic": "亚克力",
"mica": "云母",
"none": "无",
"tabbed": "标签"
}
}
},
"name": "透明播放器"
},
"tuna-obs": {
"description": "与 OBS 的 Tuna 插件集成",
"name": "Tuna OBS"

View File

@ -53,17 +53,17 @@
"later": "稍後",
"restart-now": "立即重啟"
},
"detail": "\"{{pluginName}}\" 外掛需要重新啟動之後才會生效",
"message": "\"{{pluginName}}\" 需要重新啟動",
"title": "需要重新啟動"
"detail": "外掛 \"{{pluginName}}\" 需要重啟應用才會生效",
"message": "\"{{pluginName}}\" 需要重啟應用",
"title": "需要重啟應用"
},
"unresponsive": {
"buttons": {
"quit": "結束",
"relaunch": "重新啟動",
"wait": "等一下"
"quit": "離開",
"relaunch": "重啟應用",
"wait": "等"
},
"detail": "造成不便我們深表歉意!請選擇動作",
"detail": "造成不便我們深表歉意!請選擇動作:",
"message": "應用程式沒有回應",
"title": "視窗沒有回應"
},
@ -73,7 +73,7 @@
"download": "前往下載",
"ok": "略過"
},
"detail": "新版本已經推出,你可以至 {{downloadLink}} 下載",
"detail": "新版本已經推出,前往下載 {{downloadLink}}",
"message": "有新版本可用",
"title": "有可用的更新"
}
@ -83,11 +83,11 @@
"navigation": {
"label": "導覽列",
"submenu": {
"copy-current-url": "複製前頁面的網址",
"go-back": "回上一頁",
"go-forward": "回到下一頁",
"quit": "結束",
"restart": "重新啟動"
"copy-current-url": "複製前頁面的網址",
"go-back": "回上一頁",
"go-forward": "前往下一頁",
"quit": "退出",
"restart": "重啟應用"
}
},
"options": {
@ -96,20 +96,20 @@
"advanced-options": {
"label": "進階選項",
"submenu": {
"auto-reset-app-cache": "啟動時重設應用快取",
"auto-reset-app-cache": "啟動時清除應用程式快取",
"disable-hardware-acceleration": "關閉硬體加速",
"edit-config-json": "編輯 config.json",
"override-user-agent": "覆寫使用者代理",
"restart-on-config-changes": "設定變更時自動重新啟動",
"restart-on-config-changes": "設定變更時自動重啟應用",
"set-proxy": {
"label": "設定代理伺服器",
"prompt": {
"label": "輸入代理伺服器位置:(留空以停用本設定)",
"placeholder": "範例:SOCKS5://127.0.0.1:9999",
"placeholder": "例: SOCKS5://127.0.0.1:9999",
"title": "設定代理伺服器"
}
},
"toggle-dev-tools": "切換開發人員工具"
"toggle-dev-tools": "開發人員工具"
}
},
"always-on-top": "最上層顯示",
@ -123,7 +123,7 @@
},
"language": {
"dialog": {
"message": "語言會在重新啟動後變更",
"message": "語言會在重啟應用後變更",
"title": "語言已變更"
},
"label": "語言",
@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "介面設定",
"submenu": {
"custom-window-title": {
"label": "客製化窗口標題",
"prompt": {
"label": "輸入客製化窗口標題: (留空讓其停用)",
"placeholder": "例如: YouTube 音樂"
}
},
"like-buttons": {
"default": "預設",
"force-show": "強制顯示",
@ -201,8 +208,8 @@
"restart": "重新啟動應用程式",
"show": "顯示視窗",
"tooltip": {
"default": "YouTube Music",
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
"default": "YouTube 音樂",
"with-song-info": "YouTube 音樂: {{artist}} - {{title}}"
}
}
},
@ -366,21 +373,26 @@
"name": "繞過年齡驗證"
},
"captions-selector": {
"description": "YouTube Music 音軌字幕選擇器",
"description": "Youtube Music 音軌字幕選",
"menu": {
"autoload": "自動選擇上次使用的字幕",
"disable-captions": "預設無標題"
"disable-captions": "預設無字幕"
},
"name": "標題選擇器",
"name": "字幕選項",
"prompt": {
"selector": {
"label": "目前字幕語言:{{language}}",
"label": "當前語言: {{language}}",
"none": "無",
"title": "選擇字幕語言"
}
},
"templates": {
"title": "打開標題選擇器"
"title": "開啟字幕選項"
},
"toast": {
"caption-changed": "字幕語言已更改至 {{language}}",
"caption-disabled": "字幕已停用",
"no-captions": "該首歌曲無可用的字幕"
}
},
"compact-sidebar": {
@ -409,6 +421,19 @@
}
}
},
"custom-output-device": {
"description": "為歌曲設定自訂輸出媒體裝置",
"menu": {
"device-selector": "選擇裝置"
},
"name": "自訂輸出裝置",
"prompt": {
"device-selector": {
"label": "選擇要使用的輸出媒體裝置",
"title": "選擇輸出裝置"
}
}
},
"disable-autoplay": {
"description": "讓歌曲開始時為暫停模式",
"menu": {
@ -432,7 +457,15 @@
"hide-duration-left": "隱藏音樂剩餘時間狀態",
"hide-github-button": "隱藏 GitHub 頁面按鈕",
"play-on-youtube-music": "顯示 Play on YouTube Music 按鈕",
"set-inactivity-timeout": "設定閒置狀態時長"
"set-inactivity-timeout": "設定閒置狀態時長",
"set-status-display-type": {
"label": "狀態文字",
"submenu": {
"artist": "正在聽 {artist}",
"title": "正在聽 {song title}",
"youtube-music": "正在聽 YouTube Music"
}
}
},
"name": "Discord 狀態",
"prompt": {
@ -600,7 +633,15 @@
},
"navigation": {
"description": "允許應用程式上方顯示上一頁/下一頁按鈕",
"name": "導覽列"
"name": "導覽列",
"templates": {
"back": {
"title": "回到上一頁"
},
"forward": {
"title": "前往下一頁"
}
}
},
"no-google-login": {
"description": "移除 Google 登入按鈕及連結",
@ -625,8 +666,8 @@
"name": "歌曲播放通知"
},
"performance-improvement": {
"description": "使用實驗性的腳本以化效能",
"name": "效能化 [Beta]"
"description": "使用實驗性的腳本以最佳化效能",
"name": "效能最佳化 [Beta]"
},
"picture-in-picture": {
"description": "允許應用程式切換至子母畫面模式",
@ -692,14 +733,19 @@
}
},
"description": "允許在影片內進行畫質更改",
"name": "允許變更影片畫質"
"name": "允許變更影片畫質",
"renderer": {
"quality-settings-button": {
"label": "開啟畫質調整器"
}
}
},
"scrobbler": {
"description": "額外新增 scrobbling 支援 (例如last.fm, Listenbrainz)",
"dialog": {
"lastfm": {
"auth-failed": {
"message": "Last.fm 認證失敗\n將隱藏彈窗直到重啟。",
"message": "Last.fm 認證失敗\n將隱藏彈出視窗直到重啟。",
"title": "認證失敗"
}
}
@ -711,6 +757,7 @@
"listenbrainz": {
"token": "輸入 ListenBrainz 使用者憑證"
},
"scrobble-alternative-artist": "使用替代的藝人",
"scrobble-alternative-title": "使用替代歌曲標題",
"scrobble-other-media": "紀錄其他媒體檔案"
},
@ -718,7 +765,7 @@
"prompt": {
"lastfm": {
"api-key": "Last.fm API 金鑰",
"api-secret": "Last.fm API 鑰"
"api-secret": "Last.fm API 鑰"
},
"listenbrainz": {
"token": {
@ -796,6 +843,14 @@
"label": "使歌詞完美同步",
"tooltip": "更精確的計算下一行歌詞的顯示 (將會降低些許效能)"
},
"preferred-provider": {
"label": "偏好提供者",
"none": {
"label": "無",
"tooltip": "沒有偏好的提供者"
},
"tooltip": "選擇要使用的預設提供者"
},
"romanization": {
"label": "羅馬拼音化歌詞",
"tooltip": "如果歌詞使用不同語言,嘗試使用拉丁文顯示。"
@ -828,6 +883,27 @@
"description": "為 macOS 使用者新增觸控列支援",
"name": "觸控列 (Touchbar) 支援"
},
"transparent-player": {
"description": "讓應用程式視窗變為透明",
"menu": {
"opacity": {
"label": "不透明度",
"submenu": {
"percent": "{{opacity}}%"
}
},
"type": {
"label": "類型",
"submenu": {
"acrylic": "壓克力",
"mica": "雲母",
"none": "無",
"tabbed": "分頁式"
}
}
},
"name": "透明撥放器"
},
"tuna-obs": {
"description": "與 OBS 的 Tuna 外掛連線",
"name": "Tuna OBS"
@ -859,7 +935,8 @@
},
"name": "歌曲/影片切換",
"templates": {
"button-song": "歌曲"
"button-song": "歌曲",
"button-video": "影片"
}
},
"visualizer": {

View File

@ -15,7 +15,7 @@ import {
type BrowserWindowConstructorOptions,
} from 'electron';
import enhanceWebRequest, {
BetterSession,
type BetterSession,
} from '@jellybrick/electron-better-web-request';
import is from 'electron-is';
import unhandled from 'electron-unhandled';
@ -29,7 +29,7 @@ import { allPlugins, mainPlugins } from 'virtual:plugins';
import { languageResources } from 'virtual:i18n';
import config from '@/config';
import * as config from '@/config';
import { refreshMenu, setApplicationMenu } from '@/menu';
import { fileExists, injectCSS, injectCSSAsFile } from '@/plugins/utils/main';
@ -61,13 +61,6 @@ import { defaultAuthProxyConfig } from '@/plugins/auth-proxy-adapter/config';
import type { PluginConfig } from '@/types/plugins';
if (!is.macOS()) {
delete (await allPlugins())['touchbar'];
}
if (!is.windows()) {
delete (await allPlugins())['taskbar-mediacontrol'];
}
// Catch errors and log them
unhandled({
logger: console.error,
@ -126,6 +119,8 @@ app.commandLine.appendSwitch(
'enable-features',
'OverlayScrollbar,SharedArrayBuffer,UseOzonePlatform,WaylandWindowDecorations',
);
// Disable Fluent Scrollbar (for OverlayScrollbar)
app.commandLine.appendSwitch('disable-features', 'FluentScrollbar');
if (config.get('options.disableHardwareAcceleration')) {
if (is.dev()) {
console.log('Disabling hardware acceleration');
@ -354,10 +349,12 @@ async function createMainWindow() {
delete decorations.titleBarStyle;
}
const win = new BrowserWindow({
const electronWindowSettings: Electron.BrowserWindowConstructorOptions = {
icon,
width: windowSize.width,
height: windowSize.height,
minWidth: 325,
minHeight: 425,
backgroundColor: '#000',
show: false,
webPreferences: {
@ -372,7 +369,10 @@ async function createMainWindow() {
}),
},
...decorations,
});
};
const win = new BrowserWindow(electronWindowSettings);
await initHook(win);
initTheme(win);
@ -597,6 +597,15 @@ app.once('browser-window-created', (_event, win) => {
win.webContents.on('will-prevent-unload', (event) => {
event.preventDefault();
});
const customWindowTitle = config.get('options.customWindowTitle');
if (customWindowTitle) {
win.on('page-title-updated', (event) => {
event.preventDefault();
win.setTitle(customWindowTitle);
});
}
});
app.on('window-all-closed', () => {

View File

@ -1,9 +1,9 @@
import { BrowserWindow, ipcMain } from 'electron';
import { type BrowserWindow, ipcMain } from 'electron';
import { deepmerge } from 'deepmerge-ts';
import { allPlugins, mainPlugins } from 'virtual:plugins';
import config from '@/config';
import * as config from '@/config';
import { LoggerPrefix, startPlugin, stopPlugin } from '@/utils';
import { t } from '@/i18n';

View File

@ -1,7 +1,7 @@
import { deepmerge } from 'deepmerge-ts';
import { allPlugins } from 'virtual:plugins';
import config from '@/config';
import * as config from '@/config';
import { setApplicationMenu } from '@/menu';
import { LoggerPrefix } from '@/utils';

View File

@ -3,7 +3,7 @@ import { allPlugins, preloadPlugins } from 'virtual:plugins';
import { LoggerPrefix, startPlugin, stopPlugin } from '@/utils';
import config from '@/config';
import * as config from '@/config';
import { t } from '@/i18n';

View File

@ -1,11 +1,11 @@
import is from 'electron-is';
import {
app,
BrowserWindow,
type BrowserWindow,
clipboard,
dialog,
Menu,
MenuItem,
type MenuItem,
shell,
} from 'electron';
import prompt from 'custom-electron-prompt';
@ -15,7 +15,7 @@ import { allPlugins } from 'virtual:plugins';
import { languageResources } from 'virtual:i18n';
import config from './config';
import * as config from './config';
import { restart } from './providers/app-controls';
import { startingPages } from './providers/extracted-data';
@ -216,6 +216,37 @@ export const mainMenuTemplate = async (
);
},
},
{
label: t(
'main.menu.options.submenu.visual-tweaks.submenu.custom-window-title.label',
),
async click() {
const output = await prompt(
{
title: t(
'main.menu.options.submenu.visual-tweaks.submenu.custom-window-title.label',
),
label: t(
'main.menu.options.submenu.visual-tweaks.submenu.custom-window-title.prompt.label',
),
value: config.get('options.customWindowTitle') || '',
type: 'input',
inputAttrs: {
type: 'text',
placeholder: t(
'main.menu.options.submenu.visual-tweaks.submenu.custom-window-title.prompt.placeholder',
),
},
width: 500,
...promptOptions(),
},
win,
);
if (typeof output === 'string') {
config.setMenuOption('options.customWindowTitle', output);
}
},
},
{
label: t(
'main.menu.options.submenu.visual-tweaks.submenu.like-buttons.label',

View File

@ -81,26 +81,26 @@ export default createPlugin<
<>
<Show when={showUnDislike()}>
<UnDislikeButton
onClick={this.loadFullList}
maskSize={unDislikeMaskSize()}
onClick={this.loadFullList}
/>
</Show>
<Show when={showDislike()}>
<DislikeButton
onClick={this.loadFullList}
maskSize={dislikeMaskSize()}
onClick={this.loadFullList}
/>
</Show>
<Show when={showLike()}>
<LikeButton
onClick={this.loadFullList}
maskSize={likeMaskSize()}
onClick={this.loadFullList}
/>
</Show>
<Show when={showUnLike()}>
<UnLikeButton
onClick={this.loadFullList}
maskSize={unLikeMaskSize()}
onClick={this.loadFullList}
/>
</Show>
</>

View File

@ -6,22 +6,23 @@ export interface DislikeButtonProps {
export const DislikeButton = (props: DislikeButtonProps) => (
<div class="style-scope">
<button
id="alldislike"
data-type="dislike"
data-filled="false"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
aria-pressed="false"
aria-label="Dislike all"
aria-pressed="false"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
data-filled="false"
data-type="dislike"
id="alldislike"
onClick={(e) => props.onClick?.(e)}
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'var(--ytmusic-setting-item-toggle-active)',
}}
aria-hidden="true"
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'white',
@ -32,24 +33,23 @@ export const DislikeButton = (props: DislikeButtonProps) => (
'z-index': 1,
'position': 'absolute',
}}
aria-hidden="true"
>
<div style={{ 'width': '24px', 'height': '24px' }}>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M18,4h3v10h-3V4z M5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21c0.58,0,1.14-0.24,1.52-0.65L17,14V4H6.57 C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14z"
class="style-scope yt-icon"
d="M18,4h3v10h-3V4z M5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21c0.58,0,1.14-0.24,1.52-0.65L17,14V4H6.57 C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14z"
/>
</g>
</svg>
@ -62,20 +62,20 @@ export const DislikeButton = (props: DislikeButtonProps) => (
}}
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M18,4h3v10h-3V4z M5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21c0.58,0,1.14-0.24,1.52-0.65L17,14V4H6.57 C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14z"
class="style-scope yt-icon"
d="M18,4h3v10h-3V4z M5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21c0.58,0,1.14-0.24,1.52-0.65L17,14V4H6.57 C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14z"
/>
</g>
</svg>
@ -87,8 +87,8 @@ export const DislikeButton = (props: DislikeButtonProps) => (
}}
>
<div
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
aria-hidden="true"
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
>
<div class="yt-spec-touch-feedback-shape__stroke" />
<div class="yt-spec-touch-feedback-shape__fill" />

View File

@ -6,22 +6,23 @@ export interface LikeButtonProps {
export const LikeButton = (props: LikeButtonProps) => (
<div class="style-scope">
<button
id="alllike"
data-type="like"
data-filled="false"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
aria-pressed="false"
aria-label="Like all"
aria-pressed="false"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
data-filled="false"
data-type="like"
id="alllike"
onClick={(e) => props.onClick?.(e)}
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'var(--ytmusic-setting-item-toggle-active)',
}}
aria-hidden="true"
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'white',
@ -32,24 +33,23 @@ export const LikeButton = (props: LikeButtonProps) => (
'z-index': 1,
'position': 'absolute',
}}
aria-hidden="true"
>
<div style={{ 'width': '24px', 'height': '24px' }}>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M3,11h3v10H3V11z M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11v10h10.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z"
class="style-scope yt-icon"
d="M3,11h3v10H3V11z M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11v10h10.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z"
/>
</g>
</svg>
@ -57,20 +57,20 @@ export const LikeButton = (props: LikeButtonProps) => (
</div>
<div style={{ 'width': '24px', 'height': '24px' }}>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M3,11h3v10H3V11z M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11v10h10.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z"
class="style-scope yt-icon"
d="M3,11h3v10H3V11z M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11v10h10.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z"
/>
</g>
</svg>
@ -78,8 +78,8 @@ export const LikeButton = (props: LikeButtonProps) => (
</div>
<yt-touch-feedback-shape style={{ 'border-radius': 'inherit' }}>
<div
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
aria-hidden="true"
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
>
<div class="yt-spec-touch-feedback-shape__stroke" />
<div class="yt-spec-touch-feedback-shape__fill" />

View File

@ -6,22 +6,23 @@ export interface UnDislikeButtonProps {
export const UnDislikeButton = (props: UnDislikeButtonProps) => (
<div class="style-scope">
<button
id="allundislike"
data-type="dislike"
data-filled="true"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
aria-pressed="false"
aria-label="Undislike all"
aria-pressed="false"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
data-filled="true"
data-type="dislike"
id="allundislike"
onClick={(e) => props.onClick?.(e)}
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
color: 'var(--ytmusic-setting-item-toggle-active)',
}}
aria-hidden="true"
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'white',
@ -32,7 +33,6 @@ export const UnDislikeButton = (props: UnDislikeButtonProps) => (
'z-index': 1,
'position': 'absolute',
}}
aria-hidden="true"
>
<div
style={{
@ -41,20 +41,20 @@ export const UnDislikeButton = (props: UnDislikeButtonProps) => (
}}
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M17,4h-1H6.57C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21 c0.58,0,1.14-0.24,1.52-0.65L17,14h4V4H17z M10.4,19.67C10.21,19.88,9.92,20,9.62,20c-0.26,0-0.5-0.11-0.63-0.3 c-0.07-0.1-0.15-0.26-0.09-0.47l1.52-4.94l0.4-1.29H9.46H5.23c-0.41,0-0.8-0.17-1.03-0.46c-0.12-0.15-0.25-0.4-0.18-0.72l1.34-6 C5.46,5.35,5.97,5,6.57,5H16v8.61L10.4,19.67z M20,13h-3V5h3V13z"
class="style-scope yt-icon"
d="M17,4h-1H6.57C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21 c0.58,0,1.14-0.24,1.52-0.65L17,14h4V4H17z M10.4,19.67C10.21,19.88,9.92,20,9.62,20c-0.26,0-0.5-0.11-0.63-0.3 c-0.07-0.1-0.15-0.26-0.09-0.47l1.52-4.94l0.4-1.29H9.46H5.23c-0.41,0-0.8-0.17-1.03-0.46c-0.12-0.15-0.25-0.4-0.18-0.72l1.34-6 C5.46,5.35,5.97,5,6.57,5H16v8.61L10.4,19.67z M20,13h-3V5h3V13z"
/>
</g>
</svg>
@ -67,20 +67,20 @@ export const UnDislikeButton = (props: UnDislikeButtonProps) => (
}}
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M17,4h-1H6.57C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21 c0.58,0,1.14-0.24,1.52-0.65L17,14h4V4H17z M10.4,19.67C10.21,19.88,9.92,20,9.62,20c-0.26,0-0.5-0.11-0.63-0.3 c-0.07-0.1-0.15-0.26-0.09-0.47l1.52-4.94l0.4-1.29H9.46H5.23c-0.41,0-0.8-0.17-1.03-0.46c-0.12-0.15-0.25-0.4-0.18-0.72l1.34-6 C5.46,5.35,5.97,5,6.57,5H16v8.61L10.4,19.67z M20,13h-3V5h3V13z"
class="style-scope yt-icon"
d="M17,4h-1H6.57C5.5,4,4.59,4.67,4.38,5.61l-1.34,6C2.77,12.85,3.82,14,5.23,14h4.23l-1.52,4.94C7.62,19.97,8.46,21,9.62,21 c0.58,0,1.14-0.24,1.52-0.65L17,14h4V4H17z M10.4,19.67C10.21,19.88,9.92,20,9.62,20c-0.26,0-0.5-0.11-0.63-0.3 c-0.07-0.1-0.15-0.26-0.09-0.47l1.52-4.94l0.4-1.29H9.46H5.23c-0.41,0-0.8-0.17-1.03-0.46c-0.12-0.15-0.25-0.4-0.18-0.72l1.34-6 C5.46,5.35,5.97,5,6.57,5H16v8.61L10.4,19.67z M20,13h-3V5h3V13z"
/>
</g>
</svg>
@ -92,8 +92,8 @@ export const UnDislikeButton = (props: UnDislikeButtonProps) => (
}}
>
<div
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
aria-hidden="true"
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
>
<div class="yt-spec-touch-feedback-shape__stroke" />
<div class="yt-spec-touch-feedback-shape__fill" />

View File

@ -6,22 +6,23 @@ export interface UnLikeButtonProps {
export const UnLikeButton = (props: UnLikeButtonProps) => (
<div class="style-scope">
<button
id="allunlike"
data-type="like"
data-filled="true"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
aria-pressed="false"
aria-label="Unlike all"
aria-pressed="false"
class="like-menu yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--icon-button"
data-filled="true"
data-type="like"
id="allunlike"
onClick={(e) => props.onClick?.(e)}
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'var(--ytmusic-setting-item-toggle-active)',
}}
aria-hidden="true"
>
<div
aria-hidden="true"
class="yt-spec-button-shape-next__icon"
style={{
'color': 'white',
@ -32,7 +33,6 @@ export const UnLikeButton = (props: UnLikeButtonProps) => (
'z-index': 1,
'position': 'absolute',
}}
aria-hidden="true"
>
<div
style={{
@ -41,20 +41,20 @@ export const UnLikeButton = (props: UnLikeButtonProps) => (
}}
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11H3v10h4h1h9.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z M7,20H4v-8h3V20z M19.98,13.17l-1.34,6 C18.54,19.65,18.03,20,17.43,20H8v-8.61l5.6-6.06C13.79,5.12,14.08,5,14.38,5c0.26,0,0.5,0.11,0.63,0.3 c0.07,0.1,0.15,0.26,0.09,0.47l-1.52,4.94L13.18,12h1.35h4.23c0.41,0,0.8,0.17,1.03,0.46C19.92,12.61,20.05,12.86,19.98,13.17z"
class="style-scope yt-icon"
d="M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11H3v10h4h1h9.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z M7,20H4v-8h3V20z M19.98,13.17l-1.34,6 C18.54,19.65,18.03,20,17.43,20H8v-8.61l5.6-6.06C13.79,5.12,14.08,5,14.38,5c0.26,0,0.5,0.11,0.63,0.3 c0.07,0.1,0.15,0.26,0.09,0.47l-1.52,4.94L13.18,12h1.35h4.23c0.41,0,0.8,0.17,1.03,0.46C19.92,12.61,20.05,12.86,19.98,13.17z"
/>
</g>
</svg>
@ -67,20 +67,20 @@ export const UnLikeButton = (props: UnLikeButtonProps) => (
}}
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style={{
'pointer-events': 'none',
'display': 'block',
'width': '100%',
'height': '100%',
}}
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
d="M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11H3v10h4h1h9.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z M7,20H4v-8h3V20z M19.98,13.17l-1.34,6 C18.54,19.65,18.03,20,17.43,20H8v-8.61l5.6-6.06C13.79,5.12,14.08,5,14.38,5c0.26,0,0.5,0.11,0.63,0.3 c0.07,0.1,0.15,0.26,0.09,0.47l-1.52,4.94L13.18,12h1.35h4.23c0.41,0,0.8,0.17,1.03,0.46C19.92,12.61,20.05,12.86,19.98,13.17z"
class="style-scope yt-icon"
d="M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11H3v10h4h1h9.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z M7,20H4v-8h3V20z M19.98,13.17l-1.34,6 C18.54,19.65,18.03,20,17.43,20H8v-8.61l5.6-6.06C13.79,5.12,14.08,5,14.38,5c0.26,0,0.5,0.11,0.63,0.3 c0.07,0.1,0.15,0.26,0.09,0.47l-1.52,4.94L13.18,12h1.35h4.23c0.41,0,0.8,0.17,1.03,0.46C19.92,12.61,20.05,12.86,19.98,13.17z"
/>
</g>
</svg>
@ -92,8 +92,8 @@ export const UnLikeButton = (props: UnLikeButtonProps) => (
}}
>
<div
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
aria-hidden="true"
class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response"
>
<div class="yt-spec-touch-feedback-shape__stroke" />
<div class="yt-spec-touch-feedback-shape__fill" />

View File

@ -1,5 +1,5 @@
import { FastAverageColor } from 'fast-average-color';
import Color, { ColorInstance } from 'color';
import Color, { type ColorInstance } from 'color';
import style from './style.css?inline';
@ -31,7 +31,7 @@ export default createPlugin<
alpha?: number,
ratioMultiply?: number,
): string;
updateColor(): void;
updateColor(alpha: number): void;
},
{
enabled: boolean;
@ -143,7 +143,16 @@ export default createPlugin<
document.documentElement.style.setProperty(DARK_COLOR_KEY, '0, 0, 0');
}
this.updateColor();
let alpha: number | null = null;
if (await window.mainConfig.plugins.isEnabled('transparent-player')) {
const value: unknown = window.mainConfig.get(
'plugins.transparent-player.opacity',
);
if (typeof value === 'number' && value >= 0 && value <= 1) {
alpha = value;
}
}
this.updateColor(alpha ?? 1);
});
},
onConfigChange(config) {
@ -163,7 +172,7 @@ export default createPlugin<
}
return `color-mix(in srgb, ${color} ${originalRatio}, ${keyColor} ${colorRatio})`;
},
updateColor() {
updateColor(alpha: number) {
const variableMap = {
'--ytmusic-color-black1': '#212121',
'--ytmusic-color-black2': '#181818',
@ -202,19 +211,20 @@ export default createPlugin<
Object.entries(variableMap).map(([variable, color]) => {
document.documentElement.style.setProperty(
variable,
this.getMixedColor(color, COLOR_KEY),
this.getMixedColor(color, COLOR_KEY, alpha),
'important',
);
});
document.body.style.setProperty(
'background',
this.getMixedColor('#030303', COLOR_KEY),
this.getMixedColor('rgba(3, 3, 3)', DARK_COLOR_KEY, alpha),
'important',
);
document.documentElement.style.setProperty(
'--ytmusic-background',
this.getMixedColor('#030303', DARK_COLOR_KEY),
// #030303
this.getMixedColor('rgba(3, 3, 3)', DARK_COLOR_KEY, alpha),
'important',
);
},

View File

@ -3,7 +3,7 @@ import style from './style.css?inline';
import { t } from '@/i18n';
import { createPlugin } from '@/utils';
import { menu } from './menu';
import { AmbientModePluginConfig } from './types';
import { type AmbientModePluginConfig } from './types';
import { waitForElement } from '@/utils/wait-for-element';
const defaultConfig: AmbientModePluginConfig = {

View File

@ -1,8 +1,8 @@
import { MenuItemConstructorOptions } from 'electron';
import { type MenuItemConstructorOptions } from 'electron';
import { t } from '@/i18n';
import { MenuContext } from '@/types/contexts';
import { AmbientModePluginConfig } from './types';
import { type MenuContext } from '@/types/contexts';
import { type AmbientModePluginConfig } from './types';
export interface menuParameters {
getConfig: () => AmbientModePluginConfig | Promise<AmbientModePluginConfig>;

View File

@ -4,7 +4,7 @@ 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 { registerCallback, type SongInfo } from '@/providers/song-info';
import { createBackend } from '@/utils';
import type { AmuseSongInfo } from './types';

View File

@ -0,0 +1 @@
export const API_VERSION = 'v1';

View File

@ -3,31 +3,39 @@ 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 { createNodeWebSocket } from '@hono/node-ws';
import registerCallback from '@/providers/song-info';
import { registerCallback } from '@/providers/song-info';
import { createBackend } from '@/utils';
import { JWTPayloadSchema } from './scheme';
import { registerAuth, registerControl } from './routes';
import { registerAuth, registerControl, registerWebsocket } from './routes';
import { type APIServerConfig, AuthStrategy } from '../config';
import type { BackendType } from './types';
import type { RepeatMode } from '@/types/datahost-get-state';
import type {
LikeType,
RepeatMode,
VolumeState,
} from '@/types/datahost-get-state';
export const backend = createBackend<BackendType, APIServerConfig>({
async start(ctx) {
const config = await ctx.getConfig();
await this.init(ctx);
this.init(ctx);
registerCallback((songInfo) => {
this.songInfo = songInfo;
});
ctx.ipc.on('ytmd:player-api-loaded', () => {
ctx.ipc.send('ytmd:setup-seeked-listener');
ctx.ipc.send('ytmd:setup-time-changed-listener');
ctx.ipc.send('ytmd:setup-repeat-changed-listener');
ctx.ipc.send('ytmd:setup-like-changed-listener');
ctx.ipc.send('ytmd:setup-volume-changed-listener');
ctx.ipc.send('ytmd:setup-shuffle-changed-listener');
});
ctx.ipc.on(
@ -37,7 +45,7 @@ export const backend = createBackend<BackendType, APIServerConfig>({
ctx.ipc.on(
'ytmd:volume-changed',
(newVolume: number) => (this.volume = newVolume),
(newVolumeState: VolumeState) => (this.volumeState = newVolumeState),
);
this.run(config.hostname, config.port);
@ -60,10 +68,13 @@ export const backend = createBackend<BackendType, APIServerConfig>({
},
// Custom
async init(ctx) {
const config = await ctx.getConfig();
init(backendCtx) {
this.app = new Hono();
const ws = createNodeWebSocket({
app: this.app,
});
this.app.use('*', cors());
// for web remote control
@ -74,6 +85,8 @@ export const backend = createBackend<BackendType, APIServerConfig>({
// middlewares
this.app.use('/api/*', async (ctx, next) => {
const config = await backendCtx.getConfig();
if (config.authStrategy !== AuthStrategy.NONE) {
return await jwt({
secret: config.secret,
@ -83,6 +96,7 @@ export const backend = createBackend<BackendType, APIServerConfig>({
});
this.app.use('/api/*', async (ctx, next) => {
const result = await JWTPayloadSchema.spa(await ctx.get('jwtPayload'));
const config = await backendCtx.getConfig();
const isAuthorized =
config.authStrategy === AuthStrategy.NONE ||
@ -98,12 +112,17 @@ export const backend = createBackend<BackendType, APIServerConfig>({
// routes
registerControl(
this.app,
ctx,
backendCtx,
() => this.songInfo,
() => this.currentRepeatMode,
() => this.volume,
() =>
backendCtx.window.webContents.executeJavaScript(
'document.querySelector("#like-button-renderer")?.likeStatus',
) as Promise<LikeType>,
() => this.volumeState,
);
registerAuth(this.app, ctx);
registerAuth(this.app, backendCtx);
registerWebsocket(this.app, backendCtx, ws);
// swagger
this.app.openAPIRegistry.registerComponent(
@ -131,6 +150,8 @@ export const backend = createBackend<BackendType, APIServerConfig>({
});
this.app.get('/swagger', swaggerUI({ url: '/doc' }));
this.injectWebSocket = ws.injectWebSocket.bind(this);
},
run(hostname, port) {
if (!this.app) return;
@ -141,6 +162,10 @@ export const backend = createBackend<BackendType, APIServerConfig>({
port,
hostname,
});
if (this.injectWebSocket && this.server) {
this.injectWebSocket(this.server);
}
} catch (err) {
console.error(err);
}

View File

@ -75,9 +75,11 @@ export const register = (
// SKIP CHECK
}
setConfig({
authorizedClients: [...config.authorizedClients, id],
});
if (!config.authorizedClients.includes(id)) {
setConfig({
authorizedClients: [...config.authorizedClients, id],
});
}
const token = await sign(
{

View File

@ -1,8 +1,12 @@
import { createRoute, z } from '@hono/zod-openapi';
import { ipcMain } from 'electron';
import getSongControls from '@/providers/song-controls';
import { getSongControls } from '@/providers/song-controls';
import {
LikeType,
type RepeatMode,
type VolumeState,
} from '@/types/datahost-get-state';
import {
AddSongToQueueSchema,
@ -19,8 +23,8 @@ import {
SwitchRepeatSchema,
type ResponseSongInfo,
} from '../scheme';
import { API_VERSION } from '../api-version';
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';
@ -28,8 +32,6 @@ 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',
@ -87,6 +89,24 @@ const routes = {
},
},
}),
getLikeState: createRoute({
method: 'get',
path: `/api/${API_VERSION}/like-state`,
summary: 'get like state',
description: 'Get the current like state',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({
state: z.enum(LikeType).nullable(),
}),
},
},
},
},
}),
like: createRoute({
method: 'post',
path: `/api/${API_VERSION}/like`,
@ -274,6 +294,7 @@ const routes = {
'application/json': {
schema: z.object({
state: z.number(),
isMuted: z.boolean(),
}),
},
},
@ -526,12 +547,15 @@ const routes = {
}),
};
type PromiseOrValue<T> = T | Promise<T>;
export const register = (
app: HonoApp,
{ window }: BackendContext<APIServerConfig>,
songInfoGetter: () => SongInfo | undefined,
repeatModeGetter: () => RepeatMode | undefined,
volumeGetter: () => number | undefined,
songInfoGetter: () => PromiseOrValue<SongInfo | undefined>,
repeatModeGetter: () => PromiseOrValue<RepeatMode | undefined>,
likeTypeGetter: () => PromiseOrValue<LikeType | undefined>,
volumeStateGetter: () => PromiseOrValue<VolumeState | undefined>,
) => {
const controller = getSongControls(window);
@ -565,6 +589,10 @@ export const register = (
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.getLikeState, async (ctx) => {
ctx.status(200);
return ctx.json({ state: (await likeTypeGetter()) ?? null });
});
app.openapi(routes.like, (ctx) => {
controller.like();
@ -624,9 +652,9 @@ export const register = (
return ctx.body(null);
});
app.openapi(routes.repeatMode, (ctx) => {
app.openapi(routes.repeatMode, async (ctx) => {
ctx.status(200);
return ctx.json({ mode: repeatModeGetter() ?? null });
return ctx.json({ mode: (await repeatModeGetter()) ?? null });
});
app.openapi(routes.switchRepeat, (ctx) => {
const { iteration } = ctx.req.valid('json');
@ -642,9 +670,11 @@ export const register = (
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.getVolumeState, (ctx) => {
app.openapi(routes.getVolumeState, async (ctx) => {
ctx.status(200);
return ctx.json({ state: volumeGetter() ?? 0 });
return ctx.json(
(await volumeStateGetter()) ?? { state: 0, isMuted: false },
);
});
app.openapi(routes.setFullscreen, (ctx) => {
const { state } = ctx.req.valid('json');
@ -678,8 +708,8 @@ export const register = (
return ctx.json({ state: fullscreen });
});
const songInfo = (ctx: Context) => {
const info = songInfoGetter();
const songInfo = async (ctx: Context) => {
const info = await songInfoGetter();
if (!info) {
ctx.status(204);

View File

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

View File

@ -0,0 +1,154 @@
import { createRoute } from '@hono/zod-openapi';
import { type NodeWebSocket } from '@hono/node-ws';
import {
registerCallback,
type SongInfo,
SongInfoEvent,
} from '@/providers/song-info';
import { API_VERSION } from '../api-version';
import type { WSContext } from 'hono/ws';
import type { Context, Next } from 'hono';
import type { RepeatMode, VolumeState } from '@/types/datahost-get-state';
import type { HonoApp } from '../types';
import type { BackendContext } from '@/types/contexts';
import type { APIServerConfig } from '@/plugins/api-server/config';
enum DataTypes {
PlayerInfo = 'PLAYER_INFO',
VideoChanged = 'VIDEO_CHANGED',
PlayerStateChanged = 'PLAYER_STATE_CHANGED',
PositionChanged = 'POSITION_CHANGED',
VolumeChanged = 'VOLUME_CHANGED',
RepeatChanged = 'REPEAT_CHANGED',
ShuffleChanged = 'SHUFFLE_CHANGED',
}
type PlayerState = {
song?: SongInfo;
isPlaying: boolean;
muted: boolean;
position: number;
volume: number;
repeat: RepeatMode;
shuffle: boolean;
};
export const register = (
app: HonoApp,
{ ipc }: BackendContext<APIServerConfig>,
{ upgradeWebSocket }: NodeWebSocket,
) => {
let volumeState: VolumeState | undefined = undefined;
let repeat: RepeatMode = 'NONE';
let shuffle = false;
let lastSongInfo: SongInfo | undefined = undefined;
const sockets = new Set<WSContext<WebSocket>>();
const send = (type: DataTypes, state: Partial<PlayerState>) => {
sockets.forEach((socket) =>
socket.send(JSON.stringify({ type, ...state })),
);
};
const createPlayerState = ({
songInfo,
volumeState,
repeat,
shuffle,
}: {
songInfo?: SongInfo;
volumeState?: VolumeState;
repeat: RepeatMode;
shuffle: boolean;
}): PlayerState => ({
song: songInfo,
isPlaying: songInfo ? !songInfo.isPaused : false,
muted: volumeState?.isMuted ?? false,
position: songInfo?.elapsedSeconds ?? 0,
volume: volumeState?.state ?? 100,
repeat,
shuffle,
});
registerCallback((songInfo, event) => {
if (event === SongInfoEvent.VideoSrcChanged) {
send(DataTypes.VideoChanged, { song: songInfo, position: 0 });
}
if (event === SongInfoEvent.PlayOrPaused) {
send(DataTypes.PlayerStateChanged, {
isPlaying: !(songInfo?.isPaused ?? true),
position: songInfo.elapsedSeconds,
});
}
if (event === SongInfoEvent.TimeChanged) {
send(DataTypes.PositionChanged, { position: songInfo.elapsedSeconds });
}
lastSongInfo = { ...songInfo };
});
ipc.on('ytmd:volume-changed', (newVolumeState: VolumeState) => {
volumeState = newVolumeState;
send(DataTypes.VolumeChanged, {
volume: volumeState.state,
muted: volumeState.isMuted,
});
});
ipc.on('ytmd:repeat-changed', (mode: RepeatMode) => {
repeat = mode;
send(DataTypes.RepeatChanged, { repeat });
});
ipc.on('ytmd:seeked', (t: number) => {
send(DataTypes.PositionChanged, { position: t });
});
ipc.on('ytmd:shuffle-changed', (newShuffle: boolean) => {
shuffle = newShuffle;
send(DataTypes.ShuffleChanged, { shuffle });
});
app.openapi(
createRoute({
method: 'get',
path: `/api/${API_VERSION}/ws`,
summary: 'websocket endpoint',
description: 'WebSocket endpoint for real-time updates',
responses: {
101: {
description: 'Switching Protocols',
},
},
}),
upgradeWebSocket(() => ({
onOpen(_, ws) {
// "Unsafe argument of type `WSContext<WebSocket>` assigned to a parameter of type `WSContext<WebSocket>`. (@typescript-eslint/no-unsafe-argument)" ????? what?
sockets.add(ws as WSContext<WebSocket>);
ws.send(
JSON.stringify({
type: DataTypes.PlayerInfo,
...createPlayerState({
songInfo: lastSongInfo,
volumeState,
repeat,
shuffle,
}),
}),
);
},
onClose(_, ws) {
sockets.delete(ws as WSContext<WebSocket>);
},
})) as (ctx: Context, next: Next) => Promise<Response>,
);
};

View File

@ -1,9 +1,9 @@
import { OpenAPIHono as Hono } from '@hono/zod-openapi';
import { serve } from '@hono/node-server';
import { type OpenAPIHono as Hono } from '@hono/zod-openapi';
import { type serve } from '@hono/node-server';
import type { RepeatMode, VolumeState } from '@/types/datahost-get-state';
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;
@ -13,9 +13,10 @@ export type BackendType = {
oldConfig?: APIServerConfig;
songInfo?: SongInfo;
currentRepeatMode?: RepeatMode;
volume?: number;
volumeState?: VolumeState;
injectWebSocket?: (server: ReturnType<typeof serve>) => void;
init: (ctx: BackendContext<APIServerConfig>) => Promise<void>;
init: (ctx: BackendContext<APIServerConfig>) => void;
run: (hostname: string, port: number) => void;
end: () => void;
};

View File

@ -1,26 +1,133 @@
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import { type YoutubePlayer } from '@/types/youtube-player';
const lazySafeTry = (...fns: (() => void)[]) => {
for (const fn of fns) {
try {
fn();
} catch {}
}
};
const createCompressorNode = (
audioContext: AudioContext,
): DynamicsCompressorNode => {
const compressor = audioContext.createDynamicsCompressor();
compressor.threshold.value = -50;
compressor.ratio.value = 12;
compressor.knee.value = 40;
compressor.attack.value = 0;
compressor.release.value = 0.25;
return compressor;
};
class Storage {
lastSource: MediaElementAudioSourceNode | null = null;
lastContext: AudioContext | null = null;
lastCompressor: DynamicsCompressorNode | null = null;
connected: WeakMap<MediaElementAudioSourceNode, DynamicsCompressorNode> =
new WeakMap();
connectToCompressor = (
source: MediaElementAudioSourceNode | null = null,
audioContext: AudioContext | null = null,
compressor: DynamicsCompressorNode | null = null,
): boolean => {
if (!(source && audioContext && compressor)) return false;
const current = this.connected.get(source);
if (current === compressor) return false;
this.lastSource = source;
this.lastContext = audioContext;
this.lastCompressor = compressor;
if (current) {
lazySafeTry(
() => source.disconnect(current),
() => current.disconnect(audioContext.destination),
);
} else {
lazySafeTry(() => source.disconnect(audioContext.destination));
}
try {
source.connect(compressor);
compressor.connect(audioContext.destination);
this.connected.set(source, compressor);
return true;
} catch (error) {
console.error('connectToCompressor failed', error);
return false;
}
};
disconnectCompressor = (): boolean => {
const source = this.lastSource;
const audioContext = this.lastContext;
if (!(source && audioContext)) return false;
const current = this.connected.get(source);
if (!current) return false;
lazySafeTry(
() => source.connect(audioContext.destination),
() => source.disconnect(current),
() => current.disconnect(audioContext.destination),
);
this.connected.delete(source);
return true;
};
}
const storage = new Storage();
const audioCanPlayHandler = ({
detail: { audioSource, audioContext },
}: CustomEvent<Compressor>) => {
storage.connectToCompressor(
audioSource,
audioContext,
createCompressorNode(audioContext),
);
};
const ensureAudioContextLoad = (playerApi: YoutubePlayer) => {
if (playerApi.getPlayerState() !== 1 || storage.lastContext) return;
playerApi.loadVideoById(
playerApi.getPlayerResponse().videoDetails.videoId,
playerApi.getCurrentTime(),
playerApi.getUserPlaybackQualityPreference(),
);
};
export default createPlugin({
name: () => t('plugins.audio-compressor.name'),
description: () => t('plugins.audio-compressor.description'),
renderer() {
document.addEventListener(
'ytmd:audio-can-play',
({ detail: { audioSource, audioContext } }) => {
const compressor = audioContext.createDynamicsCompressor();
renderer: {
onPlayerApiReady(playerApi) {
ensureAudioContextLoad(playerApi);
},
compressor.threshold.value = -50;
compressor.ratio.value = 12;
compressor.knee.value = 40;
compressor.attack.value = 0;
compressor.release.value = 0.25;
start() {
document.addEventListener('ytmd:audio-can-play', audioCanPlayHandler, {
passive: true,
});
storage.connectToCompressor(
storage.lastSource,
storage.lastContext,
storage.lastCompressor,
);
},
audioSource.connect(compressor);
compressor.connect(audioContext.destination);
},
{ once: true, passive: true },
);
stop() {
document.removeEventListener('ytmd:audio-can-play', audioCanPlayHandler);
storage.disconnectCompressor();
},
},
});

View File

@ -1,17 +1,15 @@
import net from 'net';
import { SocksClient, SocksClientOptions } from 'socks';
import * as net from 'node:net';
import { SocksClient, type SocksClientOptions } from 'socks';
import is from 'electron-is';
import { createBackend, LoggerPrefix } from '@/utils';
import { BackendType } from './types';
import * as config from '@/config';
import config from '@/config';
import { AuthProxyConfig, defaultAuthProxyConfig } from '../config';
import { type AuthProxyConfig, defaultAuthProxyConfig } from '../config';
import type { BackendType } from './types';
import type { BackendContext } from '@/types/contexts';
// Parsing the upstream authentication SOCK proxy URL

View File

@ -1,5 +1,4 @@
import net from 'net';
import type net from 'net';
import type { AuthProxyConfig } from '../config';
import type { Server } from 'http';

View File

@ -2,7 +2,10 @@ import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import backend from './back';
import renderer, { CaptionsSelectorConfig, LanguageOptions } from './renderer';
import renderer, {
type CaptionsSelectorConfig,
type LanguageOptions,
} from './renderer';
import type { YoutubePlayer } from '@/types/youtube-player';

View File

@ -9,10 +9,10 @@ export const CaptionsSettingButton = (props: CaptionsSettingsButtonProps) => (
aria-label={props.label}
class="player-captions-button style-scope ytmusic-player-bar"
icon={'yt-icons:subtitles'}
on:click={(e) => props.onClick(e)}
role={'button'}
tabindex={0}
title={props.label}
on:click={(e) => props.onClick(e)}
>
<span class="yt-icon-shape style-scope yt-icon yt-spec-icon-shape">
<div

View File

@ -1,6 +1,5 @@
import { Innertube } from 'youtubei.js';
import { BrowserWindow } from 'electron';
import prompt from 'custom-electron-prompt';
import { Howl } from 'howler';
@ -12,6 +11,7 @@ import { VolumeFader } from './fader';
import { t } from '@/i18n';
import type { BrowserWindow } from 'electron';
import type { RendererContext } from '@/types/contexts';
export type CrossfadePluginConfig = {

View File

@ -0,0 +1,54 @@
import prompt from 'custom-electron-prompt';
import { t } from '@/i18n';
import promptOptions from '@/providers/prompt-options';
import { createPlugin } from '@/utils';
import { renderer } from './renderer';
export interface CustomOutputPluginConfig {
enabled: boolean;
output: string;
devices: Record<string, string>;
}
export default createPlugin({
name: () => t('plugins.custom-output-device.name'),
description: () => t('plugins.custom-output-device.description'),
restartNeeded: true,
config: {
enabled: false,
output: 'default',
devices: {},
} as CustomOutputPluginConfig,
menu: ({ setConfig, getConfig, window }) => {
const promptDeviceSelector = async () => {
const options = await getConfig();
const response = await prompt(
{
title: t('plugins.custom-output-device.prompt.device-selector.title'),
label: t('plugins.custom-output-device.prompt.device-selector.label'),
value: options.output || 'default',
type: 'select',
selectOptions: options.devices,
width: 500,
...promptOptions(),
},
window,
).catch(console.error);
if (!response) return;
options.output = response;
setConfig(options);
};
return [
{
label: t('plugins.custom-output-device.menu.device-selector'),
click: promptDeviceSelector,
},
];
},
renderer,
});

View File

@ -0,0 +1,76 @@
import { createRenderer } from '@/utils';
import type { YoutubePlayer } from '@/types/youtube-player';
import type { RendererContext } from '@/types/contexts';
import type { CustomOutputPluginConfig } from './index';
const updateDeviceList = async (
context: RendererContext<CustomOutputPluginConfig>,
) => {
const newDevices: Record<string, string> = {};
const devices = await navigator.mediaDevices
.enumerateDevices()
.then((devices) =>
devices.filter((device) => device.kind === 'audiooutput'),
);
for (const device of devices) {
newDevices[device.deviceId] = device.label;
}
const options = await context.getConfig();
options.devices = newDevices;
context.setConfig(options);
};
const updateSinkId = async (
audioContext?: AudioContext & {
setSinkId?: (sinkId: string) => Promise<void>;
},
sinkId?: string,
) => {
if (!audioContext || !sinkId) return;
if (!('setSinkId' in audioContext)) return;
if (typeof audioContext.setSinkId === 'function') {
await audioContext.setSinkId(sinkId);
}
};
export const renderer = createRenderer<
{
options?: CustomOutputPluginConfig;
audioContext?: AudioContext;
audioCanPlayHandler: (event: CustomEvent<Compressor>) => Promise<void>;
},
CustomOutputPluginConfig
>({
async audioCanPlayHandler({ detail: { audioContext } }) {
this.audioContext = audioContext;
await updateSinkId(audioContext, this.options!.output);
},
async onPlayerApiReady(_: YoutubePlayer, context) {
this.options = await context.getConfig();
await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
navigator.mediaDevices.ondevicechange = async () =>
await updateDeviceList(context);
document.addEventListener('ytmd:audio-can-play', this.audioCanPlayHandler, {
once: true,
passive: true,
});
await updateDeviceList(context);
},
stop() {
document.removeEventListener(
'ytmd:audio-can-play',
this.audioCanPlayHandler,
);
navigator.mediaDevices.ondevicechange = null;
},
async onConfigChange(config) {
this.options = config;
await updateSinkId(this.audioContext, config.output);
},
});

View File

@ -98,8 +98,11 @@ export class DiscordService {
const activityInfo: SetActivity = {
type: ActivityType.Listening,
details: truncateString(songInfo.title, 128), // Song title
state: truncateString(songInfo.artist, 128), // Artist name
statusDisplayType: config.statusDisplayType,
details: truncateString(songInfo.alternativeTitle ?? songInfo.title, 128), // Song title
detailsUrl: songInfo.url ?? undefined,
state: truncateString(songInfo.tags?.at(0) ?? songInfo.artist, 128), // Artist name
stateUrl: songInfo.artistUrl,
largeImageKey: songInfo.imageSrc ?? undefined,
largeImageText: songInfo.album
? truncateString(songInfo.album, 128)

View File

@ -1,3 +1,5 @@
import { StatusDisplayType } from 'discord-api-types/v10';
import { createPlugin } from '@/utils';
import { backend } from './main';
import { onMenu } from './menu';
@ -33,6 +35,10 @@ export type DiscordPluginConfig = {
* Hide the "duration left" in the rich presence
*/
hideDurationLeft: boolean;
/**
* Controls which field is displayed in the Discord status text
*/
statusDisplayType: (typeof StatusDisplayType)[keyof typeof StatusDisplayType];
};
export default createPlugin({
@ -47,6 +53,7 @@ export default createPlugin({
playOnYouTubeMusic: true,
hideGitHubButton: false,
hideDurationLeft: false,
statusDisplayType: StatusDisplayType.Details,
} as DiscordPluginConfig,
menu: onMenu,
backend,

View File

@ -1,6 +1,6 @@
import { app } from 'electron';
import registerCallback, { SongInfoEvent } from '@/providers/song-info';
import { registerCallback, SongInfoEvent } from '@/providers/song-info';
import { createBackend } from '@/utils';
import { DiscordService } from './discord-service';

View File

@ -1,22 +1,30 @@
import prompt from 'custom-electron-prompt';
import { discordService } from './main';
import { StatusDisplayType } from 'discord-api-types/v10';
import { discordService } from './main';
import { singleton } from '@/providers/decorators';
import promptOptions from '@/providers/prompt-options';
import { setMenuOptions } from '@/config/plugins';
import { t } from '@/i18n';
import type { MenuContext } from '@/types/contexts';
import type { DiscordPluginConfig } from './index';
import type { MenuTemplate } from '@/menu';
const registerRefreshOnce = singleton((refreshMenu: () => void) => {
discordService?.registerRefreshCallback(refreshMenu);
});
const DiscordStatusDisplayTypeLabels: Record<StatusDisplayType, string> = {
[StatusDisplayType.Name]:
'plugins.discord.menu.set-status-display-type.submenu.youtube-music',
[StatusDisplayType.State]:
'plugins.discord.menu.set-status-display-type.submenu.artist',
[StatusDisplayType.Details]:
'plugins.discord.menu.set-status-display-type.submenu.title',
};
export const onMenu = async ({
window,
getConfig,
@ -92,6 +100,27 @@ export const onMenu = async ({
label: t('plugins.discord.menu.set-inactivity-timeout'),
click: () => setInactivityTimeout(window, config),
},
{
label: t('plugins.discord.menu.set-status-display-type.label'),
submenu: Object.values(StatusDisplayType)
.filter(
(v) => typeof StatusDisplayType[v as StatusDisplayType] !== 'number',
)
.map((statusDisplayType) => ({
label: t(
DiscordStatusDisplayTypeLabels[
statusDisplayType as StatusDisplayType
],
),
type: 'radio',
checked: config.statusDisplayType === statusDisplayType,
click() {
setConfig({
statusDisplayType: statusDisplayType as StatusDisplayType,
});
},
})),
},
];
};

View File

@ -1,4 +1,4 @@
import { TimerKey } from './constants';
import type { TimerKey } from './constants';
/**
* Manages NodeJS Timers, ensuring only one timer exists per key.

View File

@ -1,4 +1,4 @@
import { DefaultPresetList, Preset } from './types';
import { DefaultPresetList, type Preset } from './types';
import style from './style.css?inline';

View File

@ -2,16 +2,14 @@ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { randomBytes } from 'node:crypto';
import { app, BrowserWindow, dialog, ipcMain } from 'electron';
import { app, type BrowserWindow, dialog, ipcMain } from 'electron';
import { Innertube, UniversalCache, Utils, YTNodes } from 'youtubei.js';
import is from 'electron-is';
import filenamify from 'filenamify';
import { Mutex } from 'async-mutex';
import { createFFmpeg } from '@ffmpeg.wasm/main';
import NodeID3, { TagConstants } from 'node-id3';
import { Window } from 'happy-dom';
import * as NodeID3 from 'node-id3';
import { BG, type BgConfig } from 'bgutils-js';
import { lazy } from 'lazy-var';
import {
cropMaxWidth,
@ -19,7 +17,8 @@ import {
sendFeedback as sendFeedback_,
setBadge,
} from './utils';
import registerCallback, {
import {
registerCallback,
cleanupName,
getImage,
MediaType,
@ -44,11 +43,13 @@ import type {
type CustomSongInfo = SongInfo & { trackId?: string };
const ffmpeg = createFFmpeg({
log: false,
logger() {}, // Console.log,
progress() {}, // Console.log,
});
const ffmpeg = lazy(async () =>
(await import('@ffmpeg.wasm/main')).createFFmpeg({
log: false,
logger() {}, // Console.log,
progress() {}, // Console.log,
}),
);
const ffmpegMutex = new Mutex();
let yt: Innertube;
@ -142,7 +143,7 @@ export const onMainLoad = async ({
try {
const [width, height] = win.getSize();
// emulate jsdom using linkedom
const window = new Window({
const window = new (await import('happy-dom')).Window({
width,
height,
console,
@ -505,12 +506,13 @@ async function iterableStreamToProcessedUint8Array(
return await ffmpegMutex.runExclusive(async () => {
try {
if (!ffmpeg.isLoaded()) {
await ffmpeg.load();
const ffmpegInstance = await ffmpeg.get();
if (!ffmpegInstance.isLoaded()) {
await ffmpegInstance.load();
}
sendFeedback(t('plugins.downloader.backend.feedback.preparing-file'));
ffmpeg.FS(
ffmpegInstance.FS(
'writeFile',
safeVideoName,
Buffer.concat(
@ -525,7 +527,7 @@ async function iterableStreamToProcessedUint8Array(
sendFeedback(t('plugins.downloader.backend.feedback.converting'));
ffmpeg.setProgress(({ ratio }) => {
ffmpegInstance.setProgress(({ ratio }) => {
sendFeedback(
t('plugins.downloader.backend.feedback.conversion-progress', {
percent: Math.floor(ratio * 100),
@ -537,7 +539,7 @@ async function iterableStreamToProcessedUint8Array(
const safeVideoNameWithExtension = `${safeVideoName}.${extension}`;
try {
await ffmpeg.run(
await ffmpegInstance.run(
'-i',
safeVideoName,
...presetFfmpegArgs,
@ -545,15 +547,15 @@ async function iterableStreamToProcessedUint8Array(
safeVideoNameWithExtension,
);
} finally {
ffmpeg.FS('unlink', safeVideoName);
ffmpegInstance.FS('unlink', safeVideoName);
}
sendFeedback(t('plugins.downloader.backend.feedback.saving'));
try {
return ffmpeg.FS('readFile', safeVideoNameWithExtension);
return ffmpegInstance.FS('readFile', safeVideoNameWithExtension);
} finally {
ffmpeg.FS('unlink', safeVideoNameWithExtension);
ffmpegInstance.FS('unlink', safeVideoNameWithExtension);
}
} catch (error: unknown) {
sendError(error as Error, safeVideoName);
@ -589,7 +591,7 @@ async function writeID3(
tags.image = {
mime: 'image/png',
type: {
id: TagConstants.AttachedPicture.PictureType.FRONT_COVER,
id: NodeID3.TagConstants.AttachedPicture.PictureType.FRONT_COVER,
},
description: 'thumbnail',
imageBuffer: coverBuffer,
@ -847,5 +849,7 @@ const getMetadata = (info: TrackInfo): CustomSongInfo => ({
const getAndroidTvInfo = async (id: string): Promise<VideoInfo> => {
// GetInfo 404s with the bypass, so we use getBasicInfo instead
// that's fine as we only need the streaming data
return await yt.getBasicInfo(id, 'TV_EMBEDDED');
return await yt.getBasicInfo(id, {
client: 'TV_EMBEDDED',
});
};

View File

@ -1,4 +1,4 @@
import { app, BrowserWindow } from 'electron';
import { app, type BrowserWindow } from 'electron';
import is from 'electron-is';
export const getFolder = (customFolder?: string) =>

View File

@ -2,11 +2,14 @@ import { createSignal } from 'solid-js';
import { render } from 'solid-js/web';
import defaultConfig from '@/config/defaults';
import { defaultConfig } from '@/config/defaults';
import { getSongMenu } from '@/providers/dom-elements';
import { getSongInfo } from '@/providers/song-info-front';
import { t } from '@/i18n';
import { isMusicOrVideoTrack } from '@/plugins/utils/renderer/check';
import {
isAlbumOrPlaylist,
isMusicOrVideoTrack,
} from '@/plugins/utils/renderer/check';
import { DownloadButton } from './templates/download';
@ -25,7 +28,7 @@ const menuObserver = new MutationObserver(() => {
if (
!menu ||
menu.contains(buttonContainer) ||
!isMusicOrVideoTrack() ||
!(isMusicOrVideoTrack() || isAlbumOrPlaylist()) ||
!buttonContainer
) {
return;

View File

@ -5,8 +5,8 @@ export const DownloadButton = (props: {
<a
class="yt-simple-endpoint style-scope ytmusic-menu-navigation-item-renderer"
id="navigation-endpoint"
tabindex={-1}
onClick={props.onClick}
tabindex={-1}
>
<div class="icon ytmd-menu-item style-scope ytmusic-menu-navigation-item-renderer">
<svg

View File

@ -1,8 +1,15 @@
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import { MenuContext } from '@/types/contexts';
import { MenuTemplate } from '@/menu';
import { defaultPresets, presetConfigs, Preset, FilterConfig } from './presets';
import {
defaultPresets,
presetConfigs,
type Preset,
type FilterConfig,
} from './presets';
import type { MenuContext } from '@/types/contexts';
import type { MenuTemplate } from '@/menu';
export type EqualizerPluginConfig = {
enabled: boolean;

View File

@ -1,6 +1,8 @@
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import type { YoutubePlayer } from '@/types/youtube-player';
export default createPlugin({
name: () => t('plugins.exponential-volume.name'),
description: () => t('plugins.exponential-volume.description'),
@ -9,7 +11,16 @@ export default createPlugin({
enabled: false,
},
renderer: {
onPlayerApiReady() {
onPlayerApiReady(playerApi) {
const syncVolume = (playerApi: YoutubePlayer) => {
if (playerApi.getPlayerState() === 3) {
setTimeout(() => syncVolume(playerApi), 0);
return;
}
playerApi.setVolume(playerApi.getVolume());
};
// "YouTube Music fix volume ratio 0.4" by Marco Pfeiffer
// https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/
@ -48,6 +59,7 @@ export default createPlugin({
propertyDescriptor?.set?.call(this, lowVolume);
},
});
syncVolume(playerApi);
},
},
});

View File

@ -3,10 +3,10 @@ import { register } from 'electron-localshortcut';
import {
BrowserWindow,
Menu,
MenuItem,
type MenuItem,
ipcMain,
nativeImage,
WebContents,
type WebContents,
} from 'electron';
import type { BackendContext } from '@/types/contexts';

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