Compare commits

..

91 Commits

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

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

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

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

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

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

* fix: get song info on startup

* chore: also split on commas

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

* chore: remove redundant code

* chore: attempt at improving the initial videodata

* oops

* eureka!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Syntax fixes

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/es/
2024-08-02 14:09:21 +02:00
473ea78f12 synced-lyrics: fix album name? 2024-08-01 15:46:53 +03:00
e7f366b770 Update changelog for v3.5.1 2024-08-01 11:49:06 +00:00
42 changed files with 2690 additions and 917 deletions

View File

@ -21,7 +21,7 @@
</a> </a>
</div> </div>
Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸](./docs/readme/README-is.md), [🇨🇱 🇪🇸](./docs/readme/README-es.md) Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸](./docs/readme/README-is.md), [🇨🇱 🇪🇸](./docs/readme/README-es.md), [🇷🇺](./docs/readme/README-ru.md)
**Electron wrapper around YouTube Music featuring:** **Electron wrapper around YouTube Music featuring:**
@ -141,6 +141,8 @@ Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸]
- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Automatically Skips non-music parts like intro/outro or - [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Automatically Skips non-music parts like intro/outro or
parts of music videos where the song isn't playing parts of music videos where the song isn't playing
- **Synced Lyrics**: Provides synced lyrics to songs, using providers like [LRClib](https://lrclib.net).
- **Taskbar Media Control**: Control playback from - **Taskbar Media Control**: Control playback from
your [Windows taskbar](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png) your [Windows taskbar](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
@ -159,6 +161,7 @@ Read this in other languages: [🇰🇷](./docs/readme/README-ko.md), [🇮🇸]
- **Visualizer**: Different music visualizers - **Visualizer**: Different music visualizers
## Translation ## Translation
You can help with translation on [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/). You can help with translation on [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).

View File

@ -2,8 +2,25 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v3.5.1](https://github.com/th-ch/youtube-music/compare/v3.5.0...v3.5.1)
- fix(deps): update dependency youtubei.js to v10.3.0 [`#2306`](https://github.com/th-ch/youtube-music/pull/2306)
- fix: Window gets stuck offscreen in some instances [`#2303`](https://github.com/th-ch/youtube-music/pull/2303)
- fix: Incorrect window size on multi-monitor scaled displays [`#2302`](https://github.com/th-ch/youtube-music/pull/2302)
- chore(deps): update dependency rollup to v4.19.2 [`#2304`](https://github.com/th-ch/youtube-music/pull/2304)
- chore(deps): update typescript-eslint monorepo to v8 (major) [`#2297`](https://github.com/th-ch/youtube-music/pull/2297)
- fix(ambient-mode): fix ambient-mode not working for videos after restart [`#2294`](https://github.com/th-ch/youtube-music/pull/2294)
- fix(deps): update dependency @xhayper/discord-rpc to v1.2.0 [`#2291`](https://github.com/th-ch/youtube-music/pull/2291)
- fix(synced-lyrics): fix lyric load [`#2295`](https://github.com/th-ch/youtube-music/issues/2295)
- fix(ambient-mode): fix ambient-mode not working for videos after restart (#2294) [`#1641`](https://github.com/th-ch/youtube-music/issues/1641)
- fix(synced-lyrics): fix i18n [`8750b54`](https://github.com/th-ch/youtube-music/commit/8750b54f766c735ff039c6be454427f17d4737e2)
- ts-fix: disambiguate ElectronStore typings [`8775735`](https://github.com/th-ch/youtube-music/commit/877573532c1b68af861a3fdc44d093f3097d36ab)
- chore(i18n): Translated using Weblate (Hungarian) [`3537dc1`](https://github.com/th-ch/youtube-music/commit/3537dc19eecce7f7deb2478942f70d3c7b72148d)
#### [v3.5.0](https://github.com/th-ch/youtube-music/compare/v3.4.1...v3.5.0) #### [v3.5.0](https://github.com/th-ch/youtube-music/compare/v3.4.1...v3.5.0)
> 31 July 2024
- plugin: Synced Lyrics [`#2207`](https://github.com/th-ch/youtube-music/pull/2207) - plugin: Synced Lyrics [`#2207`](https://github.com/th-ch/youtube-music/pull/2207)
- chore(deps): update dependency electron to v31.3.1 [`#2290`](https://github.com/th-ch/youtube-music/pull/2290) - chore(deps): update dependency electron to v31.3.1 [`#2290`](https://github.com/th-ch/youtube-music/pull/2290)
- chore(deps): update typescript-eslint monorepo to v7.18.0 [`#2292`](https://github.com/th-ch/youtube-music/pull/2292) - chore(deps): update typescript-eslint monorepo to v7.18.0 [`#2292`](https://github.com/th-ch/youtube-music/pull/2292)

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

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

View File

@ -1,7 +1,7 @@
{ {
"name": "youtube-music", "name": "youtube-music",
"productName": "YouTube Music", "productName": "YouTube Music",
"version": "3.5.1", "version": "3.5.2",
"description": "YouTube Music Desktop App - including custom plugins", "description": "YouTube Music Desktop App - including custom plugins",
"main": "./dist/main/index.js", "main": "./dist/main/index.js",
"license": "MIT", "license": "MIT",
@ -94,6 +94,10 @@
"rpm": { "rpm": {
"depends": [ "depends": [
"/usr/lib64/libuuid.so.1" "/usr/lib64/libuuid.so.1"
],
"fpm": [
"--rpm-rpmbuild-define",
"_build_id_links none"
] ]
}, },
"snap": { "snap": {
@ -145,7 +149,7 @@
"xml2js": "0.6.2", "xml2js": "0.6.2",
"node-fetch": "3.3.2", "node-fetch": "3.3.2",
"@electron/universal": "2.0.1", "@electron/universal": "2.0.1",
"@babel/runtime": "7.25.0" "@babel/runtime": "7.25.6"
}, },
"patchedDependencies": { "patchedDependencies": {
"vudio@2.1.1": "patches/vudio@2.1.1.patch", "vudio@2.1.1": "patches/vudio@2.1.1.patch",
@ -159,7 +163,7 @@
"@electron/remote": "2.1.2", "@electron/remote": "2.1.2",
"@ffmpeg.wasm/core-mt": "0.12.0", "@ffmpeg.wasm/core-mt": "0.12.0",
"@ffmpeg.wasm/main": "0.12.0", "@ffmpeg.wasm/main": "0.12.0",
"@floating-ui/dom": "1.6.8", "@floating-ui/dom": "1.6.10",
"@foobar404/wave": "2.0.5", "@foobar404/wave": "2.0.5",
"@jellybrick/electron-better-web-request": "1.0.4", "@jellybrick/electron-better-web-request": "1.0.4",
"@jellybrick/mpris-service": "2.1.4", "@jellybrick/mpris-service": "2.1.4",
@ -173,18 +177,18 @@
"custom-electron-prompt": "1.5.8", "custom-electron-prompt": "1.5.8",
"dbus-next": "0.10.2", "dbus-next": "0.10.2",
"deepmerge-ts": "7.1.0", "deepmerge-ts": "7.1.0",
"electron-debug": "4.0.0", "electron-debug": "4.0.1",
"electron-is": "3.0.0", "electron-is": "3.0.0",
"electron-localshortcut": "3.2.1", "electron-localshortcut": "3.2.1",
"electron-store": "10.0.0", "electron-store": "10.0.0",
"electron-unhandled": "4.0.1", "electron-unhandled": "4.0.1",
"electron-updater": "6.3.2", "electron-updater": "6.3.4",
"fast-average-color": "9.4.0", "fast-average-color": "9.4.0",
"fast-equals": "5.0.1", "fast-equals": "5.0.1",
"filenamify": "6.0.0", "filenamify": "6.0.0",
"howler": "2.2.4", "howler": "2.2.4",
"html-to-text": "9.0.5", "html-to-text": "9.0.5",
"i18next": "23.12.2", "i18next": "23.14.0",
"keyboardevent-from-electron-accelerator": "2.0.0", "keyboardevent-from-electron-accelerator": "2.0.0",
"keyboardevents-areequal": "0.2.2", "keyboardevents-areequal": "0.2.2",
"node-html-parser": "6.1.13", "node-html-parser": "6.1.13",
@ -194,47 +198,47 @@
"serve": "14.2.3", "serve": "14.2.3",
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9", "simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
"solid-floating-ui": "0.3.1", "solid-floating-ui": "0.3.1",
"solid-js": "1.8.19", "solid-js": "1.8.22",
"solid-styled-components": "0.28.5", "solid-styled-components": "0.28.5",
"solid-transition-group": "0.2.3", "solid-transition-group": "0.2.3",
"ts-morph": "23.0.0", "ts-morph": "23.0.0",
"vudio": "2.1.1", "vudio": "2.1.1",
"x11": "2.3.0", "x11": "2.3.0",
"youtubei.js": "10.3.0" "youtubei.js": "10.4.0"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "1.45.3", "@playwright/test": "1.47.0",
"@total-typescript/ts-reset": "0.5.1", "@total-typescript/ts-reset": "0.6.1",
"@types/color": "3.0.6", "@types/color": "3.0.6",
"@types/electron-localshortcut": "3.1.3", "@types/electron-localshortcut": "3.1.3",
"@types/howler": "2.2.11", "@types/howler": "2.2.11",
"@types/html-to-text": "9.0.4", "@types/html-to-text": "9.0.4",
"@types/semver": "7.5.8", "@types/semver": "7.5.8",
"@typescript-eslint/eslint-plugin": "8.0.0", "@typescript-eslint/eslint-plugin": "8.4.0",
"@typescript-eslint/parser": "8.0.0", "@typescript-eslint/parser": "8.4.0",
"bufferutil": "4.0.8", "bufferutil": "4.0.8",
"builtin-modules": "4.0.0", "builtin-modules": "4.0.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"del-cli": "5.1.0", "del-cli": "5.1.0",
"discord-api-types": "0.37.93", "discord-api-types": "0.37.100",
"electron": "31.3.1", "electron": "32.0.2",
"electron-builder": "24.13.3", "electron-builder": "24.13.3",
"electron-devtools-installer": "3.2.0", "electron-devtools-installer": "3.2.0",
"electron-vite": "2.3.0", "electron-vite": "2.3.0",
"esbuild": "0.23.0", "esbuild": "0.23.1",
"eslint": "8.57.0", "eslint": "8.57.0",
"eslint-import-resolver-exports": "1.0.0-beta.5", "eslint-import-resolver-exports": "1.0.0-beta.5",
"eslint-import-resolver-typescript": "3.6.1", "eslint-import-resolver-typescript": "3.6.3",
"eslint-plugin-import": "2.29.1", "eslint-plugin-import": "2.30.0",
"eslint-plugin-prettier": "5.2.1", "eslint-plugin-prettier": "5.2.1",
"glob": "11.0.0", "glob": "11.0.0",
"node-gyp": "10.2.0", "node-gyp": "10.2.0",
"playwright": "1.45.3", "playwright": "1.47.0",
"rollup": "4.19.2", "rollup": "4.21.2",
"typescript": "5.5.4", "typescript": "5.5.4",
"utf-8-validate": "6.0.4", "utf-8-validate": "6.0.4",
"vite": "5.3.5", "vite": "5.4.3",
"vite-plugin-inspect": "0.8.5", "vite-plugin-inspect": "0.8.7",
"vite-plugin-resolve": "2.5.2", "vite-plugin-resolve": "2.5.2",
"vite-plugin-solid": "2.10.2", "vite-plugin-solid": "2.10.2",
"ws": "8.18.0" "ws": "8.18.0"

1496
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -668,6 +668,54 @@
"description": "Überspringt automatisch nicht-musikalische Teile wie Intro/Outro oder Teile von Musikvideos, in denen der Song nicht gespielt wird", "description": "Überspringt automatisch nicht-musikalische Teile wie Intro/Outro oder Teile von Musikvideos, in denen der Song nicht gespielt wird",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "Bietet synchronisierte Liedtexte zu Songs, verwendet Anbieter wie LRClib.",
"errors": {
"fetch": "⚠️ - Beim Abrufen des Liedtexts ist ein Fehler aufgetreten. Bitte versuchen Sie es später nochmal.",
"not-found": "⚠️ - Kein Text für diesen Song gefunden."
},
"menu": {
"default-text-string": {
"label": "Standardzeichen zwischen Texten",
"tooltip": "Standardzeichen für die Lücke zwischen Songtexten auswählen"
},
"line-effect": {
"label": "Zeileneffekt",
"submenu": {
"focus": {
"label": "Fokussieren",
"tooltip": "Nur aktive Zeile weiß darstellen"
},
"offset": {
"label": "Versatz"
},
"scale": {
"label": "Skalieren",
"tooltip": "Aktuelle Zeile skalieren"
}
},
"tooltip": "Effekt für aktive Zeile auswählen"
},
"precise-timing": {
"label": "Den Songtext perfekt synchronisieren",
"tooltip": "Auf die Millisekunde genau berechnen, wann die nächste Zeile angezeigt werden soll (Kann Einfluss auf die Leistung haben)"
},
"show-time-codes": {
"label": "Zeitkodierungen anzeigen",
"tooltip": "Zeitkodierungen neben Songtext anzeigen"
}
},
"name": "Synchronisierte Texte",
"refetch-btn": {
"fetching": "Hole Songtext...",
"normal": "Songtext neu holen"
},
"warnings": {
"duration-mismatch": "⚠️ - Es kann sein, dass die Synchronization nicht stimmt, da die Songdauer nicht übereinstimmt.",
"inexact": "⚠️ - Es ist Möglich, dass der Songtext für diesen Song nicht übereinstimmt.",
"instrumental": "⚠️ - Das ist ein instrumentales Lied"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Wiedergabe aus der Windows Taskleiste kontrollieren", "description": "Wiedergabe aus der Windows Taskleiste kontrollieren",
"name": "Mediensteuerung in der Taskleiste" "name": "Mediensteuerung in der Taskleiste"

View File

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

View File

@ -668,6 +668,59 @@
"description": "Salta automáticamente las partes no musicales como la introducción/final o secciones de videos musicales donde la canción no está sonando", "description": "Salta automáticamente las partes no musicales como la introducción/final o secciones de videos musicales donde la canción no está sonando",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "Proporciona letras de canciones sincronizadas, utilizando proveedores como LRClib.",
"errors": {
"fetch": "⚠️ - Se ha producido un error al descargar la letra. Por favor, vuelve a intentarlo más tarde.",
"not-found": "⚠️ - No se ha encontrado ninguna letra para esta canción."
},
"menu": {
"default-text-string": {
"label": "Carácter predeterminado entre letras",
"tooltip": "Elige el carácter predeterminado que se utilizará para el espacio entre letras"
},
"line-effect": {
"label": "Efecto de la línea",
"submenu": {
"focus": {
"label": "Enfoque",
"tooltip": "Mostrar solo la línea actual en blanco"
},
"offset": {
"label": "Desplazamiento",
"tooltip": "Desplazamiento a la derecha de la línea actual"
},
"scale": {
"label": "Escala",
"tooltip": "Escala de la línea actual"
}
},
"tooltip": "Elige el efecto que deseas aplicar a la línea actual"
},
"precise-timing": {
"label": "Haz que la letra esté perfectamente sincronizada",
"tooltip": "Calcular al milisegundo la visualización de la línea siguiente (puede tener un pequeño impacto en el rendimiento)"
},
"show-lyrics-even-if-inexact": {
"label": "Mostrar la letra aunque sea inexacta",
"tooltip": "Si no se encuentra la canción, el complemento vuelve a intentarlo con una búsqueda diferente.\nEl resultado del segundo intento puede no ser exacto."
},
"show-time-codes": {
"label": "Visualización del código de tiempo",
"tooltip": "Mostrar los códigos de tiempo junto a la letra"
}
},
"name": "Letras sincronizadas",
"refetch-btn": {
"fetching": "Recuperando...",
"normal": "Volver a buscar letras"
},
"warnings": {
"duration-mismatch": "⚠️ - La letra puede estar desincronizada debido a un desajuste en la duración.",
"inexact": "⚠️ - La letra de esta canción puede no ser exacta",
"instrumental": "⚠️ - Se trata de una canción instrumental"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Controla la reproducción desde la barra de tareas de Windows", "description": "Controla la reproducción desde la barra de tareas de Windows",
"name": "Control de medios de la barra de tareas" "name": "Control de medios de la barra de tareas"

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

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

View File

@ -207,10 +207,12 @@
}, },
"plugins": { "plugins": {
"ad-speedup": { "ad-speedup": {
"description": "Pag mag-play ng ad, I-mute ang audio at i-set ang bilis ng playback ng 16x" "description": "Pag mag-play ng ad, I-mute ang audio at i-set ang bilis ng playback ng 16x",
"name": "Pagbilis ng Ad"
}, },
"adblocker": { "adblocker": {
"description": "I-block ang lahat ng ad at tracking" "description": "I-block ang lahat ng ad at tracking",
"name": "Pag-block ng Ad"
}, },
"album-actions": { "album-actions": {
"description": "Idadagdag ang Undislike, Dislike, Like, at Unlike na button para ilapat ito sa lahat ng kanta sa isang playlist o album", "description": "Idadagdag ang Undislike, Dislike, Like, at Unlike na button para ilapat ito sa lahat ng kanta sa isang playlist o album",
@ -392,6 +394,8 @@
"download-finish-settings": { "download-finish-settings": {
"label": "Kung natapos ang download", "label": "Kung natapos ang download",
"prompt": { "prompt": {
"last-percent": "Tapos ng x na porsyento",
"last-seconds": "Huling x na segundo",
"title": "I-configure kung kailan magda-download" "title": "I-configure kung kailan magda-download"
}, },
"submenu": { "submenu": {
@ -406,6 +410,9 @@
}, },
"renderer": { "renderer": {
"can-not-update-progress": "Hindi ma-update ang progress" "can-not-update-progress": "Hindi ma-update ang progress"
},
"templates": {
"button": "Mag download"
} }
}, },
"exponential-volume": { "exponential-volume": {
@ -475,7 +482,8 @@
"name": "Nabigasyon" "name": "Nabigasyon"
}, },
"no-google-login": { "no-google-login": {
"description": "Tanggalin ang mga Google login na button at mga link mula sa interface" "description": "Tanggalin ang mga Google login na button at mga link mula sa interface",
"name": "Walang Google na Login"
}, },
"notifications": { "notifications": {
"description": "Magpakita ng notification kapag nagsimulang tumugtog ang kanta (magagamit ang mga interactive na notification sa Windows)", "description": "Magpakita ng notification kapag nagsimulang tumugtog ang kanta (magagamit ang mga interactive na notification sa Windows)",
@ -491,7 +499,8 @@
}, },
"priority": "Prioridad ng Notification", "priority": "Prioridad ng Notification",
"unpause-notification": "Ipakita ang notification sa pag-unpause" "unpause-notification": "Ipakita ang notification sa pag-unpause"
} },
"name": "Mga Abiso"
}, },
"picture-in-picture": { "picture-in-picture": {
"description": "Payagan ang pag-palit ng app sa picture-in-picture mode", "description": "Payagan ang pag-palit ng app sa picture-in-picture mode",
@ -580,6 +589,7 @@
"shortcuts": { "shortcuts": {
"description": "Nagbibigay-daan sa pagtatakda ng mga global hotkey para sa playback (play/pause/susunod/nakaraan) at pag-off ng media OSD sa pamamagitan ng pag-override sa mga media key, pag-on sa Ctrl/CMD + F para maghanap, pag-on sa suporta ng Linux MPRIS para sa mga media key, at mga custom na hotkey para sa mga advanced na user", "description": "Nagbibigay-daan sa pagtatakda ng mga global hotkey para sa playback (play/pause/susunod/nakaraan) at pag-off ng media OSD sa pamamagitan ng pag-override sa mga media key, pag-on sa Ctrl/CMD + F para maghanap, pag-on sa suporta ng Linux MPRIS para sa mga media key, at mga custom na hotkey para sa mga advanced na user",
"menu": { "menu": {
"override-media-keys": "I-override ang mga Media Key",
"set-keybinds": "I-set ang Global Song Control" "set-keybinds": "I-set ang Global Song Control"
}, },
"name": "Mga shortcut (at MPRIS)", "name": "Mga shortcut (at MPRIS)",
@ -587,6 +597,7 @@
"keybind": { "keybind": {
"keybind-options": { "keybind-options": {
"next": "Susunod", "next": "Susunod",
"play-pause": "Mag-play / Mag-pause",
"previous": "Nakaraan" "previous": "Nakaraan"
}, },
"label": "Pumili ng Global na Keybind para sa Songs Control:" "label": "Pumili ng Global na Keybind para sa Songs Control:"
@ -594,14 +605,65 @@
} }
}, },
"skip-disliked-songs": { "skip-disliked-songs": {
"description": "Laktawan ang na-dislike na kanta" "description": "Laktawan ang na-dislike na kanta",
"name": "I-skip ang mga Na-dislike na Kanta"
}, },
"skip-silences": { "skip-silences": {
"description": "Automatikong laktawan ang mga tahimik na mga seksyon sa kanta" "description": "Automatikong laktawan ang mga tahimik na mga seksyon sa kanta",
"name": "I-skip ang mga Katahimikan"
}, },
"sponsorblock": { "sponsorblock": {
"description": "Automatikong Laktawan ang di part ng kanta tulad ng intro/outro o part ng mga music video na ang kanta ay di nagple-play" "description": "Automatikong Laktawan ang di part ng kanta tulad ng intro/outro o part ng mga music video na ang kanta ay di nagple-play"
}, },
"synced-lyrics": {
"description": "Nagbibigay ng naka-sync na lyrics sa mga kanta, gamit ang mga provider tulad ng LRClib.",
"errors": {
"fetch": "⚠️ - Nagkaroon ng error habang kinukuha ang lyrics. Subukang muli mamaya.",
"not-found": "⚠️ - Walang nakitang lyrics para sa kantang ito."
},
"menu": {
"default-text-string": {
"label": "Default na character sa pagitan ng lyrics",
"tooltip": "Pumili ng default na character na gagamitin sa pagitan ng lyrics"
},
"line-effect": {
"label": "Effect ng Linya",
"submenu": {
"focus": {
"tooltip": "Gawing puti lamang ang kasalukuyang linya"
},
"offset": {
"tooltip": "I-offset sa kanan ang kasalukuyang linya"
},
"scale": {
"tooltip": "I-scale ang kasalukuyang linya"
}
},
"tooltip": "Pumili ng effect na ilalapat sa kasalukuyang linya"
},
"precise-timing": {
"label": "Gawing perpektong naka-sync ang lyrics",
"tooltip": "Kalkulahin sa millisecond ang pagpapakita ng susunod na linya (maaaring magkaroon ng maliit na epekto sa performance)"
},
"show-lyrics-even-if-inexact": {
"label": "Ipakita ang lyrics kahit di-eksakto",
"tooltip": "Kung hindi matagpuan ang kanta, susubukan muli ng plugin gamit ang ibang query sa paghahanap.\nAng resulta mula sa pangalawang pagsubok ay maaaring hindi eksakto."
},
"show-time-codes": {
"label": "Ipakita ang mga time code",
"tooltip": "Ipakita ang mga time code kasunod sa lyrics"
}
},
"refetch-btn": {
"fetching": "Nag-fe-fetch...",
"normal": "I-fetch muli ang lyrics"
},
"warnings": {
"duration-mismatch": "⚠️ - Maaaring hindi naka-sync ang lyrics dahil sa hindi pagkakatugma ng duration.",
"inexact": "⚠️ - Maaaring hindi eksakto ang lyrics para sa kantang ito",
"instrumental": "⚠️ - Ito ay isang instrumental na kanta"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Kontrolin ang pag-play mula sa iyong taskbar ng Windows" "description": "Kontrolin ang pag-play mula sa iyong taskbar ng Windows"
}, },

View File

@ -668,6 +668,59 @@
"description": "Saute automatiquement les parties non musicales comme l'intro/outro ou les parties de clips vidéo où la chanson n'est pas lue", "description": "Saute automatiquement les parties non musicales comme l'intro/outro ou les parties de clips vidéo où la chanson n'est pas lue",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "Ajoute des paroles synchronisées aux chansons, grâce à LRClib par exemple.",
"errors": {
"fetch": "⚠️ - Une erreur s'est produite en allant chercher les paroles. Merci de réessayer plus tard.",
"not-found": "⚠️ - Aucune paroles trouvées pour cette musique."
},
"menu": {
"default-text-string": {
"label": "Caractère par défaut entre les paroles",
"tooltip": "Choisi le caractère par défaut à utiliser pour l'espace entre les paroles"
},
"line-effect": {
"label": "Effet de ligne",
"submenu": {
"focus": {
"label": "Focus",
"tooltip": "Rend seulement la ligne actuelle blanche"
},
"offset": {
"label": "Décalage",
"tooltip": "Décale sur la droite la ligne actuelle"
},
"scale": {
"label": "Grossissement",
"tooltip": "Agrandis la ligne actuelle"
}
},
"tooltip": "Choisi l'effet à appliquer sur la ligne actuelle"
},
"precise-timing": {
"label": "Rend les paroles parfaitement synchronisées",
"tooltip": "Calcul à la milliseconde près l'affichage de la ligne suivante (peut avoir un faible impact sur les performances)"
},
"show-lyrics-even-if-inexact": {
"label": "Afficher les paroles même si inexactes",
"tooltip": "Si la musique n'est pas trouvé, le plugin essaye à nouveau avec une différence requête.\nLe résultat du deuxième essais peut ne pas être exacte."
},
"show-time-codes": {
"label": "Afficher les timecodes",
"tooltip": "Affiche à côté de chaque paroles son timecode"
}
},
"name": "Paroles Synchronisées",
"refetch-btn": {
"fetching": "Chargement...",
"normal": "Rafraîchir les paroles"
},
"warnings": {
"duration-mismatch": "⚠️ - Les paroles peuvent ne pas être synchronisées à cause d'une différence de durée.",
"inexact": "⚠️ - Les paroles de cette chanson peuvent ne pas être exactes",
"instrumental": "⚠️ - Cette musique n'a pas de paroles"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Contrôlez la lecture depuis votre barre des tâches Windows", "description": "Contrôlez la lecture depuis votre barre des tâches Windows",
"name": "Contrôle multimédia de la barre des tâches" "name": "Contrôle multimédia de la barre des tâches"

View File

@ -7,8 +7,8 @@
"initialize-failed": "Nem sikerült inicializálni a \"{{pluginName}}\" plugint", "initialize-failed": "Nem sikerült inicializálni a \"{{pluginName}}\" plugint",
"load-all": "Összes bővítmény betöltése", "load-all": "Összes bővítmény betöltése",
"load-failed": "Nem sikerült betölteni a \"{{pluginName}}\" plugint", "load-failed": "Nem sikerült betölteni a \"{{pluginName}}\" plugint",
"loaded": "\"{{pluginName}}\" nevű plugin betöltve", "loaded": "\"{{pluginName}}\" plugin betöltve",
"unload-failed": "Nem sikerült a \"{{pluginName}}\" bővítményt letölteni", "unload-failed": "Nem sikerült a \"{{pluginName}}\" bővítményt kikapcsolni",
"unloaded": "A \"{{pluginName}}\" bővítmény kikapcsolva" "unloaded": "A \"{{pluginName}}\" bővítmény kikapcsolva"
} }
} }
@ -567,7 +567,7 @@
"menu": { "menu": {
"arrows-shortcuts": "Helyi nyíl-billentyűkkel való vezérlés", "arrows-shortcuts": "Helyi nyíl-billentyűkkel való vezérlés",
"custom-volume-steps": "Egyedi hangerőléptetés beállítása", "custom-volume-steps": "Egyedi hangerőléptetés beállítása",
"global-shortcuts": "Globális gyorsbillentyűk" "global-shortcuts": "Globális Gyorsbillentyűk"
}, },
"name": "Precíz hangerő", "name": "Precíz hangerő",
"prompt": { "prompt": {

View File

@ -207,6 +207,10 @@
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "Jika iklan diputar, audio akan dimatikan dan kecepatan pemutaran akan diatur ke 16x",
"name": "Percepatan Iklan"
},
"adblocker": { "adblocker": {
"description": "Blokir semua iklan dan pelacakan di luar kotak", "description": "Blokir semua iklan dan pelacakan di luar kotak",
"menu": { "menu": {
@ -410,6 +414,21 @@
"description": "Unduh MP3 / sumber suara secara langsung via antarmuka", "description": "Unduh MP3 / sumber suara secara langsung via antarmuka",
"menu": { "menu": {
"choose-download-folder": "Pilih folder unduhan", "choose-download-folder": "Pilih folder unduhan",
"download-finish-settings": {
"label": "Unduh setelah selesai",
"prompt": {
"last-percent": "x persen terakhir",
"last-seconds": "x detik terakhir",
"title": "Konfigurasikan kapan akan mengunduh"
},
"submenu": {
"advanced": "Lanjutan",
"enabled": "Diaktifkan",
"mode": "Mode waktu",
"percent": "Persen",
"seconds": "Detik"
}
},
"download-playlist": "Unduh daftar putar", "download-playlist": "Unduh daftar putar",
"presets": "Prasetel", "presets": "Prasetel",
"skip-existing": "Lewati berkas yang sudah ada" "skip-existing": "Lewati berkas yang sudah ada"
@ -649,6 +668,59 @@
"description": "Otomatis Melewati bagian yang bukan musik seperti intro/outro atau bagian dari video musik di mana lagu tidak dimainkan", "description": "Otomatis Melewati bagian yang bukan musik seperti intro/outro atau bagian dari video musik di mana lagu tidak dimainkan",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "Menyediakan lirik lagu yang disinkronkan, menggunakan penyedia seperti LRClib.",
"errors": {
"fetch": "⚠️ - Terjadi kesalahan saat mengambil lirik. Coba lagi nanti.",
"not-found": "⚠️ - Tidak ada lirik yang ditemukan untuk lagu ini."
},
"menu": {
"default-text-string": {
"label": "Karakter default antara lirik",
"tooltip": "Pilih karakter default yang akan digunakan untuk celah antar lirik"
},
"line-effect": {
"label": "Efek garis",
"submenu": {
"focus": {
"label": "Fokus",
"tooltip": "Jadikan hanya baris saat ini berwarna putih"
},
"offset": {
"label": "Offset",
"tooltip": "Mengimbangi garis saat ini di sebelah kanan"
},
"scale": {
"label": "Skala",
"tooltip": "Skala garis saat ini"
}
},
"tooltip": "Pilih efek yang akan diterapkan ke baris saat ini"
},
"precise-timing": {
"label": "Buat liriknya tersinkronisasi dengan sempurna",
"tooltip": "Hitung hingga milidetik tampilan baris berikutnya (dapat berdampak kecil pada kinerja)"
},
"show-lyrics-even-if-inexact": {
"label": "Tampilkan lirik meskipun tidak tepat",
"tooltip": "Jika lagu tidak ditemukan, plugin akan mencoba lagi dengan kueri pencarian yang berbeda.\nHasil dari percobaan kedua mungkin tidak tepat."
},
"show-time-codes": {
"label": "Tampilkan kode waktu",
"tooltip": "Tampilkan kode waktu di samping lirik"
}
},
"name": "Lirik yang Disinkronkan",
"refetch-btn": {
"fetching": "Mengambil...",
"normal": "Ambil ulang lirik"
},
"warnings": {
"duration-mismatch": "⚠️ - Liriknya mungkin tidak sinkron karena ketidakcocokan durasi.",
"inexact": "⚠️ - Lirik lagu ini mungkin tidak tepat",
"instrumental": "⚠️ - Ini adalah lagu instrumental"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Kendalikan pemutaran dari bilah alat Windows", "description": "Kendalikan pemutaran dari bilah alat Windows",
"name": "Pengendali Media di Bilah Alat" "name": "Pengendali Media di Bilah Alat"

View File

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

View File

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

View File

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

View File

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

View File

@ -207,6 +207,10 @@
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "Если воспроизводится реклама, аудио заглушается и скорость воспроизведения устанавливается на 16х",
"name": "Ускоренная перемотка"
},
"adblocker": { "adblocker": {
"description": "Блокируйте всю рекламу и трекинг сразу после установки", "description": "Блокируйте всю рекламу и трекинг сразу после установки",
"menu": { "menu": {
@ -277,7 +281,7 @@
}, },
"audio-compressor": { "audio-compressor": {
"description": "Применяет компрессию к аудио (уменьшает громкость самых громких частей сигнала и повышает громкость самых тихих частей)", "description": "Применяет компрессию к аудио (уменьшает громкость самых громких частей сигнала и повышает громкость самых тихих частей)",
"name": "Аудио компрессор" "name": "Нормализация аудио"
}, },
"blur-nav-bar": { "blur-nav-bar": {
"description": "Делает панель навигации прозрачной и размытой", "description": "Делает панель навигации прозрачной и размытой",
@ -649,6 +653,58 @@
"description": "Автоматически пропускает не музыкальные фрагменты, например интро/аутро или фрагменты музыкальных клипов, в которых песня не звучит (тишина)", "description": "Автоматически пропускает не музыкальные фрагменты, например интро/аутро или фрагменты музыкальных клипов, в которых песня не звучит (тишина)",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "Предоставляет синхронизированные слова для песен из таких источников, как LRClib.",
"errors": {
"fetch": "⚠️ - Возникла ошибка во время получения слов. Повторите попытку позже.",
"not-found": "⚠️ - Для этой песни не найдено слов."
},
"menu": {
"default-text-string": {
"label": "Стандартный символ между словами",
"tooltip": "Выберите стандартный символ для заполнения пространства между словами"
},
"line-effect": {
"label": "Эффект строки",
"submenu": {
"focus": {
"label": "Фокусировка",
"tooltip": "Делает только текущую строку белой"
},
"offset": {
"label": "Сдвиг",
"tooltip": "Сдвигает текущую строку вправо"
},
"scale": {
"label": "Увеличение",
"tooltip": "Увеличивает текущую строку"
}
},
"tooltip": "Выберите эффект применяемый к текущей строке"
},
"precise-timing": {
"label": "Идеально синхронизировать слова",
"tooltip": "До миллисекунды рассчитывает отображение следующей строки(может оказать небольшое влияние на производительность)"
},
"show-lyrics-even-if-inexact": {
"label": "Показывать слова, даже если неточные",
"tooltip": "Если песня не найдена, плагин попытается снова с другим поисковым запросом.\nСо второй попытки результат может быть неточным."
},
"show-time-codes": {
"label": "Показывать временные метки",
"tooltip": "Показывает временные метки рядом со словами"
}
},
"refetch-btn": {
"fetching": "Сбор данных...",
"normal": "Обновить слова"
},
"warnings": {
"duration-mismatch": "⚠️ - Слова могут быть неточно синхронизированы из-за несовпадения длины трека.",
"inexact": "⚠️ - Слова для этой песни могут быть неточными",
"instrumental": "⚠️ - Это инструментальная музыка"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Управляйте воспроизведением с панели задач Windows", "description": "Управляйте воспроизведением с панели задач Windows",
"name": "Управление мультимедиа на панели задач" "name": "Управление мультимедиа на панели задач"
@ -692,7 +748,7 @@
"menu": { "menu": {
"visualizer-type": "Вид визуализации" "visualizer-type": "Вид визуализации"
}, },
"name": "Визуалайзер" "name": "Визуализатор"
} }
} }
} }

View File

@ -207,6 +207,10 @@
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "Bir reklam oynatılırsa sesi kapatır ve oynatma hızını 16x olarak ayarlar",
"name": "Hızlandırma"
},
"adblocker": { "adblocker": {
"description": "Tüm reklamları ve izleyicileri engelle", "description": "Tüm reklamları ve izleyicileri engelle",
"menu": { "menu": {
@ -664,6 +668,59 @@
"description": "Giriş/Çıkış gibi müzik olmayan kısımları veya müzik videolarında şarkının çalmadığı kısımları otomatik olarak atlar", "description": "Giriş/Çıkış gibi müzik olmayan kısımları veya müzik videolarında şarkının çalmadığı kısımları otomatik olarak atlar",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "LRClib gibi sağlayıcıları kullanarak şarkılara senkronize şarkı sözleri sağlar.",
"errors": {
"fetch": "⚠️ - Şarkı sözleri getirilirken bir hata oluştu. Lütfen daha sonra tekrar deneyin.",
"not-found": "⚠️ - Bu şarkı için şarkı sözü bulunamadı."
},
"menu": {
"default-text-string": {
"label": "Şarkı sözleri arasında varsayılan karakter",
"tooltip": "Şarkı sözleri arasındaki boşluk için kullanılacak varsayılan karakteri seçin"
},
"line-effect": {
"label": "Çizgi etkisi",
"submenu": {
"focus": {
"label": "odak",
"tooltip": "Yalnızca geçerli satırı beyaz yapın"
},
"offset": {
"label": "telafi etmek,ofset",
"tooltip": "Geçerli satırın sağındaki ofset"
},
"scale": {
"label": "ölçek",
"tooltip": "Geçerli satırı ölçeklendirir"
}
},
"tooltip": "Geçerli satıra uygulanacak efekti seçin"
},
"precise-timing": {
"label": "Şarkı sözlerini mükemmel şekilde senkronize edin",
"tooltip": "Bir sonraki satırın görüntülenmesini milisaniyesine kadar hesaplayın (performans üzerinde küçük bir etkisi olabilir)"
},
"show-lyrics-even-if-inexact": {
"label": "Kesin olmasa bile şarkı sözlerini gösterin",
"tooltip": "Şarkı bulunamazsa, eklenti farklı bir arama sorgusuyla tekrar dener. \nİkinci denemenin sonucu tam olmayabilir."
},
"show-time-codes": {
"label": "Zaman kodlarını göster",
"tooltip": "Şarkı sözlerinin yanında zaman kodlarını gösterin"
}
},
"name": "Senkronize Şarkı Sözleri",
"refetch-btn": {
"fetching": "Getiriliyor...",
"normal": "Refetch şarkı sözleri"
},
"warnings": {
"duration-mismatch": "⚠️ - Süre uyuşmazlığı nedeniyle şarkı sözleri senkronize olmayabilir.",
"inexact": "⚠️ - Bu şarkının sözleri tam olmayabilir",
"instrumental": "⚠️ - Bu enstrümantal bir şarkıdır"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Windows görev çubuğu üzerinden oynatmayı kontrol edebilmenize olanak sağlar", "description": "Windows görev çubuğu üzerinden oynatmayı kontrol edebilmenize olanak sağlar",
"name": "Görev Çubuğu Medya Kontrolü" "name": "Görev Çubuğu Medya Kontrolü"

View File

@ -674,6 +674,38 @@
"fetch": "⚠️ - Đã xảy ra lỗi khi tìm nạp lời bài hát, Vui lòng thử lại sau.", "fetch": "⚠️ - Đã xảy ra lỗi khi tìm nạp lời bài hát, Vui lòng thử lại sau.",
"not-found": "⚠️ - Không tìm thấy lời cho bài hát này." "not-found": "⚠️ - Không tìm thấy lời cho bài hát này."
}, },
"menu": {
"default-text-string": {
"label": "Kí tự mặc định giữa các lời bài hát",
"tooltip": "Chọn kí tự mặc định cho khoảng trống giữa các lời bài hát"
},
"line-effect": {
"label": "Kiểu đường thẳng",
"submenu": {
"focus": {
"label": "Tập trung",
"tooltip": "Chỉ làm cho dòng hiện tại có màu trắng"
},
"scale": {
"label": "Tỉ lệ",
"tooltip": "Áp dụng tỉ lệ cho dòng hiện tại"
}
},
"tooltip": "Chọn kiểu để áp dụng cho dòng hiện tại"
},
"precise-timing": {
"label": "Làm cho lời bài hát được đồng bộ hoàn hảo",
"tooltip": "Tính toán chính xác đến mili giây thời gian hiển thị dòng tiếp theo (có thể có tác động nhỏ đến hiệu suất)"
},
"show-lyrics-even-if-inexact": {
"label": "Hiển thị lời bài hát ngay cả khi không chính xác",
"tooltip": "Nếu không tìm thấy bài hát, plugin sẽ thử lại bằng truy vấn tìm kiếm khác.\nKết quả từ lần thử thứ hai có thể không chính xác."
},
"show-time-codes": {
"label": "Hiện mốc thời gian",
"tooltip": "Hiện mốc thời gian bên cạnh lời bài hát"
}
},
"name": "Lời bài hát được đồng bộ hoá", "name": "Lời bài hát được đồng bộ hoá",
"refetch-btn": { "refetch-btn": {
"fetching": "Đang tìm nạp...", "fetching": "Đang tìm nạp...",

View File

@ -207,6 +207,10 @@
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "使用静音以及 16 倍速播放跳过广告片段",
"name": "广告加速跳过"
},
"adblocker": { "adblocker": {
"description": "屏蔽所有广告与跟踪器", "description": "屏蔽所有广告与跟踪器",
"menu": { "menu": {
@ -664,6 +668,59 @@
"description": "自动跳过非音乐部分,如 MV 的介绍/结语以及歌曲未开始的部分", "description": "自动跳过非音乐部分,如 MV 的介绍/结语以及歌曲未开始的部分",
"name": "SponsorBlock" "name": "SponsorBlock"
}, },
"synced-lyrics": {
"description": "透过 LRClib 等服务提供滚动歌词显示。",
"errors": {
"fetch": "⚠️ - 获取歌词时发生错误。请稍后再试。",
"not-found": "⚠️ - 未找到此歌曲的歌词。"
},
"menu": {
"default-text-string": {
"label": "默认的歌词行间字符",
"tooltip": "选择在歌词间隙期间默认显示的字符"
},
"line-effect": {
"label": "歌词行特效",
"submenu": {
"focus": {
"label": "高亮",
"tooltip": "仅将当前歌词行显示为白色"
},
"offset": {
"label": "偏移",
"tooltip": "将当前歌词行向右偏移"
},
"scale": {
"label": "放大",
"tooltip": "放大当前歌词行"
}
},
"tooltip": "选择当前歌词行应用的特效"
},
"precise-timing": {
"label": "让滚动歌词完全同步",
"tooltip": "以毫秒精度估算下句歌词的显示时间(可能对性能有小幅影响)"
},
"show-lyrics-even-if-inexact": {
"label": "即使时值不精确依然显示歌词",
"tooltip": "若首次搜索未找到该歌曲的歌词,插件将尝试用不同的查询方式重新获取。\n重试查询的结果可能不精确。"
},
"show-time-codes": {
"label": "显示时值",
"tooltip": "在歌词旁显示时值"
}
},
"name": "滚动歌词",
"refetch-btn": {
"fetching": "正在获取…",
"normal": "重新获取歌词"
},
"warnings": {
"duration-mismatch": "⚠️ - 由于持续时间不对应,滚动歌词可能不同步。",
"inexact": "⚠️ - 此曲目的歌词可能不准确",
"instrumental": "⚠️ - 此曲目为纯音乐"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "从 Windows 任务栏控制音乐回放", "description": "从 Windows 任务栏控制音乐回放",
"name": "任务栏媒体控件" "name": "任务栏媒体控件"

View File

@ -207,6 +207,10 @@
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "使用 16 倍速播放及靜音來跳過廣告片段",
"name": "加速略過"
},
"adblocker": { "adblocker": {
"description": "阻擋所有廣告", "description": "阻擋所有廣告",
"menu": { "menu": {
@ -341,10 +345,10 @@
"discord": { "discord": {
"backend": { "backend": {
"already-connected": "已嘗試可用連接", "already-connected": "已嘗試可用連接",
"connected": "已連接至Discord", "connected": "已連接至 Discord",
"disconnected": "與Discord斷開連接" "disconnected": "與 Discord 斷開連接"
}, },
"description": "使用Discord狀態與你的好友分享你正在收聽的音樂", "description": "使用 Discord 狀態與你的好友分享你正在收聽的音樂",
"menu": { "menu": {
"auto-reconnect": "自動重新連接", "auto-reconnect": "自動重新連接",
"clear-activity": "清除狀態", "clear-activity": "清除狀態",
@ -352,11 +356,11 @@
"connected": "已連接", "connected": "已連接",
"disconnected": "已斷開連接", "disconnected": "已斷開連接",
"hide-duration-left": "隱藏音樂剩餘時間狀態", "hide-duration-left": "隱藏音樂剩餘時間狀態",
"hide-github-button": "隱藏Github頁面按鈕", "hide-github-button": "隱藏 Github 頁面按鈕",
"play-on-youtube-music": "顯示Play on YouTube Music按鈕", "play-on-youtube-music": "顯示 Play on YouTube Music 按鈕",
"set-inactivity-timeout": "設定閒置狀態時長" "set-inactivity-timeout": "設定閒置狀態時長"
}, },
"name": "Discord狀態", "name": "Discord 狀態",
"prompt": { "prompt": {
"set-inactivity-timeout": { "set-inactivity-timeout": {
"label": "設定多少秒後清除狀態:", "label": "設定多少秒後清除狀態:",
@ -513,8 +517,8 @@
"name": "導覽列" "name": "導覽列"
}, },
"no-google-login": { "no-google-login": {
"description": "移除Google登入按鈕及連結", "description": "移除 Google 登入按鈕及連結",
"name": "停用Google登入" "name": "停用 Google 登入"
}, },
"notifications": { "notifications": {
"description": "在歌曲播放時發送一個系統通知 (可互動通知僅限Windows)", "description": "在歌曲播放時發送一個系統通知 (可互動通知僅限Windows)",
@ -664,6 +668,59 @@
"description": "自動跳過贊助片段", "description": "自動跳過贊助片段",
"name": "贊助阻擋" "name": "贊助阻擋"
}, },
"synced-lyrics": {
"description": "使用 LRClib 等管道提供歌詞同步顯示。",
"errors": {
"fetch": "⚠️擷取歌詞時發生錯誤。請稍後再試。",
"not-found": "⚠️未找到該首歌曲的歌詞。"
},
"menu": {
"default-text-string": {
"label": "預設歌詞中間隔的符號",
"tooltip": "選擇歌詞中間隔要使用的符號"
},
"line-effect": {
"label": "歌詞顯示效果",
"submenu": {
"focus": {
"label": "高亮",
"tooltip": "高亮當前的歌詞"
},
"offset": {
"label": "凸行",
"tooltip": "凸行當前的歌詞"
},
"scale": {
"label": "放大",
"tooltip": "放大當前的歌詞"
}
},
"tooltip": "選擇要使用的歌詞顯示效果"
},
"precise-timing": {
"label": "使歌詞完美同步",
"tooltip": "更精確的計算下一行歌詞的顯示(將會降低些許效能)"
},
"show-lyrics-even-if-inexact": {
"label": "即使不精確依然強制顯示歌詞",
"tooltip": "當找不到符合該歌曲的歌詞時,該功能會嘗試不同的搜尋方式\n使用不同的搜尋方式會導致不精確的結果。"
},
"show-time-codes": {
"label": "顯示時間線",
"tooltip": "在歌詞旁顯示時間線"
}
},
"name": "歌詞同步",
"refetch-btn": {
"fetching": "擷取中...",
"normal": "重新擷取歌詞"
},
"warnings": {
"duration-mismatch": "⚠️歌詞可能會出現不同步的情況。",
"inexact": "⚠️該歌曲的歌詞可能並不精確",
"instrumental": "⚠️該首歌曲並無人聲"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "允許工作列應用程式預覽介面顯示媒體控制相關按鈕", "description": "允許工作列應用程式預覽介面顯示媒體控制相關按鈕",
"name": "工作列媒體控制" "name": "工作列媒體控制"

View File

@ -56,6 +56,7 @@ import { loadI18n, setLanguage, t } from '@/i18n';
import ErrorHtmlAsset from '@assets/error.html?asset'; import ErrorHtmlAsset from '@assets/error.html?asset';
import type { PluginConfig } from '@/types/plugins'; import type { PluginConfig } from '@/types/plugins';
import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions;
if (!is.macOS()) { if (!is.macOS()) {
delete allPlugins['touchbar']; delete allPlugins['touchbar'];
@ -286,6 +287,23 @@ async function createMainWindow() {
height: 32, height: 32,
}; };
const decorations: Partial<BrowserWindowConstructorOptions> = {
frame: !is.macOS() && !useInlineMenu,
titleBarOverlay: defaultTitleBarOverlayOptions,
titleBarStyle: useInlineMenu
? 'hidden'
: is.macOS()
? 'hiddenInset'
: 'default',
autoHideMenuBar: config.get('options.hideMenu'),
};
// Note: on linux, for some weird reason, having these extra properties with 'frame: false' does not work
if (is.linux() && useInlineMenu) {
delete decorations.titleBarOverlay;
delete decorations.titleBarStyle;
}
const win = new BrowserWindow({ const win = new BrowserWindow({
icon, icon,
width: windowSize.width, width: windowSize.width,
@ -303,14 +321,7 @@ async function createMainWindow() {
sandbox: false, sandbox: false,
}), }),
}, },
frame: !is.macOS() && !useInlineMenu, ...decorations,
titleBarOverlay: defaultTitleBarOverlayOptions,
titleBarStyle: useInlineMenu
? 'hidden'
: is.macOS()
? 'hiddenInset'
: 'default',
autoHideMenuBar: config.get('options.hideMenu'),
}); });
initHook(win); initHook(win);
initTheme(win); initTheme(win);

View File

@ -10,11 +10,11 @@ import {
import injectCliqzPreload from './injectors/inject-cliqz-preload'; import injectCliqzPreload from './injectors/inject-cliqz-preload';
import { inject, isInjected } from './injectors/inject'; import { inject, isInjected } from './injectors/inject';
import { loadAdSpeedup } from './adSpeedup';
import { t } from '@/i18n'; import { t } from '@/i18n';
import type { BrowserWindow } from 'electron'; import type { BrowserWindow } from 'electron';
import { loadAdSpeedup } from './adSpeedup';
interface AdblockerConfig { interface AdblockerConfig {
/** /**
@ -74,7 +74,7 @@ export default createPlugin({
]; ];
}, },
renderer: { renderer: {
async onPlayerApiReady(_, {getConfig}) { async onPlayerApiReady(_, { getConfig }) {
const config = await getConfig(); const config = await getConfig();
if (config.blocker === blockers.AdSpeedup) { if (config.blocker === blockers.AdSpeedup) {
await loadAdSpeedup(); await loadAdSpeedup();
@ -118,7 +118,19 @@ export default createPlugin({
}, },
}, },
preload: { preload: {
script: 'window.JSON.parse = window._proxyJsonParse; window._proxyJsonParse = undefined; window.Response.prototype.json = window._proxyResponseJson; window._proxyResponseJson = undefined; 0', // see #1478
script: `const _prunerFn = window._pruner;
window._pruner = undefined;
JSON.parse = new Proxy(JSON.parse, {
apply() {
return _prunerFn(Reflect.apply(...arguments));
},
});
Response.prototype.json = new Proxy(Response.prototype.json, {
apply() {
return Reflect.apply(...arguments).then((o) => _prunerFn(o));
},
}); 0`,
async start({ getConfig }) { async start({ getConfig }) {
const config = await getConfig(); const config = await getConfig();

View File

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

View File

@ -261,12 +261,12 @@ async function downloadSongUnsafe(
let playabilityStatus = info.playability_status; let playabilityStatus = info.playability_status;
let bypassedResult = null; let bypassedResult = null;
if (playabilityStatus.status === 'LOGIN_REQUIRED') { if (playabilityStatus?.status === 'LOGIN_REQUIRED') {
// Try to bypass the age restriction // Try to bypass the age restriction
bypassedResult = await getAndroidTvInfo(id); bypassedResult = await getAndroidTvInfo(id);
playabilityStatus = bypassedResult.playability_status; playabilityStatus = bypassedResult.playability_status;
if (playabilityStatus.status === 'LOGIN_REQUIRED') { if (playabilityStatus?.status === 'LOGIN_REQUIRED') {
throw new Error( throw new Error(
`[${playabilityStatus.status}] ${playabilityStatus.reason}`, `[${playabilityStatus.status}] ${playabilityStatus.reason}`,
); );
@ -275,7 +275,7 @@ async function downloadSongUnsafe(
info = bypassedResult; info = bypassedResult;
} }
if (playabilityStatus.status === 'UNPLAYABLE') { if (playabilityStatus?.status === 'UNPLAYABLE') {
const errorScreen = const errorScreen =
playabilityStatus.error_screen as PlayerErrorMessage | null; playabilityStatus.error_screen as PlayerErrorMessage | null;
throw new Error( throw new Error(

View File

@ -1,9 +1,9 @@
import { JSX } from 'solid-js'; import { JSX } from 'solid-js';
import { css } from 'solid-styled-components'; import { css } from 'solid-styled-components';
import { cache } from '@/providers/decorators'; import { cacheNoArgs } from '@/providers/decorators';
const iconButton = cache(() => css` const iconButton = cacheNoArgs(() => css`
-webkit-app-region: none; -webkit-app-region: none;
background: transparent; background: transparent;

View File

@ -1,9 +1,9 @@
import { JSX, splitProps } from 'solid-js'; import { JSX, splitProps } from 'solid-js';
import { css } from 'solid-styled-components'; import { css } from 'solid-styled-components';
import { cache } from '@/providers/decorators'; import { cacheNoArgs } from '@/providers/decorators';
const menuStyle = cache(() => css` const menuStyle = cacheNoArgs(() => css`
-webkit-app-region: none; -webkit-app-region: none;
display: flex; display: flex;

View File

@ -5,9 +5,9 @@ import { Transition } from 'solid-transition-group';
import { autoUpdate, flip, offset, OffsetOptions, size } from '@floating-ui/dom'; import { autoUpdate, flip, offset, OffsetOptions, size } from '@floating-ui/dom';
import { useFloating } from 'solid-floating-ui'; import { useFloating } from 'solid-floating-ui';
import { cache } from '@/providers/decorators'; import { cacheNoArgs } from '@/providers/decorators';
const panelStyle = cache(() => css` const panelStyle = cacheNoArgs(() => css`
position: fixed; position: fixed;
top: var(--offset-y, 0); top: var(--offset-y, 0);
left: var(--offset-x, 0); left: var(--offset-x, 0);
@ -36,7 +36,7 @@ const panelStyle = cache(() => css`
transform-origin: var(--origin-x, 50%) var(--origin-y, 50%); transform-origin: var(--origin-x, 50%) var(--origin-y, 50%);
`); `);
const animationStyle = cache(() => ({ const animationStyle = cacheNoArgs(() => ({
enter: css` enter: css`
opacity: 0; opacity: 0;
transform: scale(0.9); transform: scale(0.9);

View File

@ -8,9 +8,9 @@ import { useFloating } from 'solid-floating-ui';
import { autoUpdate, offset, size } from '@floating-ui/dom'; import { autoUpdate, offset, size } from '@floating-ui/dom';
import { Panel } from './Panel'; import { Panel } from './Panel';
import { cache } from '@/providers/decorators'; import { cacheNoArgs } from '@/providers/decorators';
const itemStyle = cache(() => css` const itemStyle = cacheNoArgs(() => css`
position: relative; position: relative;
-webkit-app-region: none; -webkit-app-region: none;
@ -47,18 +47,18 @@ const itemStyle = cache(() => css`
} }
`); `);
const itemIconStyle = cache(() => css` const itemIconStyle = cacheNoArgs(() => css`
height: 32px; height: 32px;
padding: 4px; padding: 4px;
color: white; color: white;
`); `);
const itemLabelStyle = cache(() => css` const itemLabelStyle = cacheNoArgs(() => css`
font-size: 12px; font-size: 12px;
color: white; color: white;
`); `);
const itemChipStyle = cache(() => css` const itemChipStyle = cacheNoArgs(() => css`
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -76,7 +76,7 @@ const itemChipStyle = cache(() => css`
line-height: 1; line-height: 1;
`); `);
const toolTipStyle = cache(() => css` const toolTipStyle = cacheNoArgs(() => css`
min-width: 32px; min-width: 32px;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -92,7 +92,7 @@ const toolTipStyle = cache(() => css`
font-size: 10px; font-size: 10px;
`); `);
const popupStyle = cache(() => css` const popupStyle = cacheNoArgs(() => css`
position: fixed; position: fixed;
top: var(--offset-y, 0); top: var(--offset-y, 0);
left: var(--offset-x, 0); left: var(--offset-x, 0);
@ -105,7 +105,7 @@ const popupStyle = cache(() => css`
`); `);
const animationStyle = cache(() => ({ const animationStyle = cacheNoArgs(() => ({
enter: css` enter: css`
opacity: 0; opacity: 0;
transform: scale(0.9); transform: scale(0.9);

View File

@ -9,12 +9,12 @@ import { PanelItem } from './PanelItem';
import { IconButton } from './IconButton'; import { IconButton } from './IconButton';
import { WindowController } from './WindowController'; import { WindowController } from './WindowController';
import { cache } from '@/providers/decorators'; import { cacheNoArgs } from '@/providers/decorators';
import type { RendererContext } from '@/types/contexts'; import type { RendererContext } from '@/types/contexts';
import type { InAppMenuConfig } from '../constants'; import type { InAppMenuConfig } from '../constants';
const titleStyle = cache(() => css` const titleStyle = cacheNoArgs(() => css`
-webkit-app-region: drag; -webkit-app-region: drag;
box-sizing: border-box; box-sizing: border-box;
@ -50,7 +50,7 @@ const titleStyle = cache(() => css`
} }
`); `);
const separatorStyle = cache(() => css` const separatorStyle = cacheNoArgs(() => css`
min-height: 1px; min-height: 1px;
height: 1px; height: 1px;
margin: 4px 0; margin: 4px 0;
@ -58,7 +58,7 @@ const separatorStyle = cache(() => css`
background-color: rgba(255, 255, 255, 0.2); background-color: rgba(255, 255, 255, 0.2);
`); `);
const animationStyle = cache(() => ({ const animationStyle = cacheNoArgs(() => ({
enter: css` enter: css`
opacity: 0; opacity: 0;
transform: translateX(-50%) scale(0.8); transform: translateX(-50%) scale(0.8);
@ -271,16 +271,15 @@ export const TitleBar = (props: TitleBarProps) => {
// tracking mouse position // tracking mouse position
window.addEventListener('mousemove', listener); window.addEventListener('mousemove', listener);
const ytmusicAppLayout = document.querySelector<HTMLElement>('#layout'); const ytmusicAppLayout = document.querySelector<HTMLElement>('#layout');
ytmusicAppLayout?.addEventListener("scroll",()=>{ ytmusicAppLayout?.addEventListener('scroll', () => {
const scrollValue = ytmusicAppLayout.scrollTop; const scrollValue = ytmusicAppLayout.scrollTop;
if (scrollValue > 20){ if (scrollValue > 20){
ytmusicAppLayout.classList.add("content-scrolled"); ytmusicAppLayout.classList.add('content-scrolled');
} }
else{ else{
ytmusicAppLayout.classList.remove("content-scrolled"); ytmusicAppLayout.classList.remove('content-scrolled');
} }
}) });
}); });

View File

@ -2,9 +2,9 @@ import { css } from 'solid-styled-components';
import { Show } from 'solid-js'; import { Show } from 'solid-js';
import { IconButton } from './IconButton'; import { IconButton } from './IconButton';
import { cache } from '@/providers/decorators'; import { cacheNoArgs } from '@/providers/decorators';
const containerStyle = cache(() => css` const containerStyle = cacheNoArgs(() => css`
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;

View File

@ -1,4 +1,4 @@
import { BrowserWindow, ipcMain, globalShortcut } from 'electron'; import { BrowserWindow, globalShortcut } from 'electron';
import is from 'electron-is'; import is from 'electron-is';
import { register as registerElectronLocalShortcut } from 'electron-localshortcut'; import { register as registerElectronLocalShortcut } from 'electron-localshortcut';
@ -48,9 +48,7 @@ export const onMainLoad = async ({
_registerLocalShortcut(window, 'CommandOrControl+L', search); _registerLocalShortcut(window, 'CommandOrControl+L', search);
if (is.linux()) { if (is.linux()) {
ipcMain.once('ytmd:video-src-changed', (_) => { registerMPRIS(window);
registerMPRIS(window);
});
} }
const { global, local } = config; const { global, local } = config;

View File

@ -16,10 +16,9 @@ export let _ytAPI: YoutubePlayer | null = null;
export const renderer = createRenderer<{ export const renderer = createRenderer<{
observerCallback: MutationCallback; observerCallback: MutationCallback;
hasAddedEvents: boolean;
observer?: MutationObserver; observer?: MutationObserver;
videoDataChange: () => Promise<void>; videoDataChange: () => Promise<void>;
progressCallback: (evt: Event) => void; updateTimestampInterval?: NodeJS.Timeout | string | number;
}, SyncedLyricsPluginConfig>({ }, SyncedLyricsPluginConfig>({
onConfigChange(newConfig) { onConfigChange(newConfig) {
setConfig(newConfig); setConfig(newConfig);
@ -50,15 +49,12 @@ export const renderer = createRenderer<{
await this.videoDataChange(); await this.videoDataChange();
}, },
hasAddedEvents: false,
async videoDataChange() { async videoDataChange() {
if (!this.hasAddedEvents) { if (!this.updateTimestampInterval) {
const video = document.querySelector('video'); this.updateTimestampInterval = setInterval(
() => setCurrentTime((_ytAPI?.getCurrentTime() ?? 0) * 1000),
video?.addEventListener('timeupdate', this.progressCallback); 100,
);
if (video) this.hasAddedEvents = true;
} }
this.observer ??= new MutationObserver( this.observer ??= new MutationObserver(
@ -73,16 +69,6 @@ export const renderer = createRenderer<{
header.removeAttribute('disabled'); header.removeAttribute('disabled');
}, },
progressCallback(evt: Event) {
switch (evt.type) {
case 'timeupdate': {
const video = evt.target as HTMLVideoElement;
setCurrentTime(video.currentTime * 1000);
break;
}
}
},
async start(ctx: RendererContext<SyncedLyricsPluginConfig>) { async start(ctx: RendererContext<SyncedLyricsPluginConfig>) {
setConfig(await ctx.getConfig()); setConfig(await ctx.getConfig());

View File

@ -17,14 +17,6 @@ export const [hadSecondAttempt, setHadSecondAttempt] = createSignal(false);
// prettier-ignore // prettier-ignore
export const [differentDuration, setDifferentDuration] = createSignal(false); export const [differentDuration, setDifferentDuration] = createSignal(false);
// eslint-disable-next-line prefer-const // eslint-disable-next-line prefer-const
export let foundPlainTextLyrics = false;
export type SongData = {
title: string;
artist: string;
album: string;
songDuration: number;
};
export const extractTimeAndText = ( export const extractTimeAndText = (
line: string, line: string,
@ -33,7 +25,7 @@ export const extractTimeAndText = (
const groups = /\[(\d+):(\d+)\.(\d+)\](.+)/.exec(line); const groups = /\[(\d+):(\d+)\.(\d+)\](.+)/.exec(line);
if (!groups) return null; if (!groups) return null;
const [_, rMinutes, rSeconds, rMillis, text] = groups; const [, rMinutes, rSeconds, rMillis, text] = groups;
const [minutes, seconds, millis] = [ const [minutes, seconds, millis] = [
parseInt(rMinutes), parseInt(rMinutes),
parseInt(rSeconds), parseInt(rSeconds),
@ -46,7 +38,7 @@ export const extractTimeAndText = (
return { return {
index, index,
timeInMs, timeInMs,
time: `${minutes}:${seconds}:${millis}`, time: `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${millis}`,
text: text?.trim() ?? config()!.defaultTextString, text: text?.trim() ?? config()!.defaultTextString,
status: 'upcoming', status: 'upcoming',
duration: 0, duration: 0,
@ -54,22 +46,31 @@ export const extractTimeAndText = (
}; };
export const makeLyricsRequest = async (extractedSongInfo: SongInfo) => { export const makeLyricsRequest = async (extractedSongInfo: SongInfo) => {
setIsFetching(true);
setLineLyrics([]); setLineLyrics([]);
const songData: SongData = {
const songData: Parameters<typeof getLyricsList>[0] = {
title: `${extractedSongInfo.title}`, title: `${extractedSongInfo.title}`,
artist: `${extractedSongInfo.artist}`, artist: `${extractedSongInfo.artist}`,
album: `${extractedSongInfo.album}`,
songDuration: extractedSongInfo.songDuration, songDuration: extractedSongInfo.songDuration,
}; };
const lyrics = await getLyricsList(songData); if (extractedSongInfo.album) {
songData.album = extractedSongInfo.album;
}
let lyrics;
try {
lyrics = await getLyricsList(songData);
} catch {}
setLineLyrics(lyrics ?? []); setLineLyrics(lyrics ?? []);
setIsFetching(false);
}; };
export const getLyricsList = async ( export const getLyricsList = async (
songData: SongData, songData: Pick<SongInfo, 'title' | 'artist' | 'album' | 'songDuration'>,
): Promise<LineLyrics[] | null> => { ): Promise<LineLyrics[] | null> => {
setIsFetching(true);
setIsInstrumental(false); setIsInstrumental(false);
setHadSecondAttempt(false); setHadSecondAttempt(false);
setDifferentDuration(false); setDifferentDuration(false);
@ -80,6 +81,7 @@ export const getLyricsList = async (
track_name: songData.title, track_name: songData.title,
}); });
if (songData.album) { if (songData.album) {
query.set('album_name', songData.album); query.set('album_name', songData.album);
} }
@ -88,18 +90,12 @@ export const getLyricsList = async (
let response = await fetch(url); let response = await fetch(url);
if (!response.ok) { if (!response.ok) {
setIsFetching(false);
setDebugInfo('Got non-OK response from server.'); setDebugInfo('Got non-OK response from server.');
return null; return null;
} }
let data = (await response.json().catch((e: Error) => { let data = await response.json() as LRCLIBSearchResponse;
setDebugInfo(`Error: ${e.message}\n\n${e.stack}`);
return null;
})) as LRCLIBSearchResponse | null;
if (!data || !Array.isArray(data)) { if (!data || !Array.isArray(data)) {
setIsFetching(false);
setDebugInfo('Unexpected server response.'); setDebugInfo('Unexpected server response.');
return null; return null;
} }
@ -115,14 +111,12 @@ export const getLyricsList = async (
response = await fetch(url); response = await fetch(url);
if (!response.ok) { if (!response.ok) {
setIsFetching(false);
setDebugInfo('Got non-OK response from server. (2)'); setDebugInfo('Got non-OK response from server. (2)');
return null; return null;
} }
data = (await response.json()) as LRCLIBSearchResponse; data = (await response.json()) as LRCLIBSearchResponse;
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
setIsFetching(false);
setDebugInfo('Unexpected server response. (2)'); setDebugInfo('Unexpected server response. (2)');
return null; return null;
} }
@ -132,15 +126,18 @@ export const getLyricsList = async (
const filteredResults = []; const filteredResults = [];
for (const item of data) { for (const item of data) {
if (!item.syncedLyrics) continue;
const { artist } = songData; const { artist } = songData;
const { artistName } = item; const { artistName } = item;
const ratio = jaroWinkler(artist.toLowerCase(), artistName.toLowerCase()); const artists = artist.split(/[&,]/g).map((i) => i.trim());
const itemArtists = artistName.split(/[&,]/g).map((i) => i.trim());
if (ratio <= 0.9) continue; const permutations = artists.flatMap((artistA) =>
filteredResults.push(item); itemArtists.map((artistB) => [artistA.toLowerCase(), artistB.toLowerCase()])
);
const ratio = Math.max(...permutations.map(([x, y]) => jaroWinkler(x, y)));
if (ratio > 0.9) filteredResults.push(item);
} }
const duration = songData.songDuration; const duration = songData.songDuration;
@ -153,35 +150,43 @@ export const getLyricsList = async (
const closestResult = filteredResults[0]; const closestResult = filteredResults[0];
if (!closestResult) { if (!closestResult) {
setIsFetching(false);
setDebugInfo('No search result matched the criteria.'); setDebugInfo('No search result matched the criteria.');
return null; return null;
} }
// setDebugInfo(JSON.stringify(closestResult, null, 4)); setDebugInfo(JSON.stringify(closestResult, null, 4));
if (Math.abs(closestResult.duration - duration) > 15) {
return null;
}
if (Math.abs(closestResult.duration - duration) > 15) return null;
if (Math.abs(closestResult.duration - duration) > 5) { if (Math.abs(closestResult.duration - duration) > 5) {
// show message that the timings may be wrong // show message that the timings may be wrong
setDifferentDuration(true); setDifferentDuration(true);
} }
setIsInstrumental(closestResult.instrumental); setIsInstrumental(closestResult.instrumental);
if (closestResult.instrumental) {
return null;
}
// Separate the lyrics into lines // Separate the lyrics into lines
const raw = closestResult.syncedLyrics.split('\n'); const raw = closestResult.syncedLyrics?.split('\n') ?? [];
if (!raw.length) {
return null;
}
// Add a blank line at the beginning // Add a blank line at the beginning
raw.unshift('[0:0.0] '); raw.unshift('[0:0.0] ');
const syncedLyricList = []; const syncedLyricList = raw.reduce<LineLyrics[]>((acc, line, index) => {
const syncedLine = extractTimeAndText(line, index);
for (let idx = 0; idx < raw.length; idx++) {
const syncedLine = extractTimeAndText(raw[idx], idx);
if (syncedLine) { if (syncedLine) {
syncedLyricList.push(syncedLine); acc.push(syncedLine);
} }
}
return acc;
}, []);
for (const line of syncedLyricList) { for (const line of syncedLyricList) {
const next = syncedLyricList[line.index + 1]; const next = syncedLyricList[line.index + 1];
@ -193,6 +198,5 @@ export const getLyricsList = async (
line.duration = next.timeInMs - line.timeInMs; line.duration = next.timeInMs - line.timeInMs;
} }
setIsFetching(false);
return syncedLyricList; return syncedLyricList;
}; };

View File

@ -40,6 +40,16 @@ export function cache<T extends (...params: P) => R, P extends never[], R>(
}) as T; }) as T;
} }
export function cacheNoArgs<R>(fn: () => R): () => R {
let cached: R;
return () => {
if (cached === undefined) {
cached = fn();
}
return cached;
};
}
/* /*
The following are currently unused, but potentially useful in the future The following are currently unused, but potentially useful in the future
*/ */

View File

@ -200,6 +200,26 @@ export default (api: YoutubePlayer) => {
for (const status of ['playing', 'pause'] as const) { for (const status of ['playing', 'pause'] as const) {
video.addEventListener(status, playPausedHandlers[status]); video.addEventListener(status, playPausedHandlers[status]);
} }
if (!isNaN(video.duration)) {
const {
title, author,
video_id: videoId,
list: playlistId
} = api.getVideoData();
const { playerOverlays } = api.getWatchNextResponse();
sendSongInfo(<VideoDataChangeValue>{
title, author, videoId, playlistId,
isUpcoming: false,
lengthSeconds: video.duration,
loading: true,
uhhh: { playerOverlays }
});
}
} }
function sendSongInfo(videoData: VideoDataChangeValue) { function sendSongInfo(videoData: VideoDataChangeValue) {

View File

@ -214,14 +214,14 @@ const suffixesToRemove = [
/\s*vevo$/i, /\s*vevo$/i,
// Video titles // Video titles
/\s*[(|\[]official(.*?)[)|\]]/i, // (Official Music Video), [Official Visualizer], etc... /\s*[(|[]official(.*?)[)|\]]/i, // (Official Music Video), [Official Visualizer], etc...
/\s*[(|\[]((lyrics?|visualizer|audio)\s*(video)?)[)|\]]/i, /\s*[(|[]((lyrics?|visualizer|audio)\s*(video)?)[)|\]]/i,
/\s*[(|\[](performance video)[)|\]]/i, /\s*[(|[](performance video)[)|\]]/i,
/\s*[(|\[](clip official)[)|\]]/i, /\s*[(|[](clip official)[)|\]]/i,
/\s*[(|\[](video version)[)|\]]/i, /\s*[(|[](video version)[)|\]]/i,
/\s*[(|\[](HD|HQ)\s*?(?:audio)?[)|\]]$/i, /\s*[(|[](HD|HQ)\s*?(?:audio)?[)|\]]$/i,
/\s*[(|\[](live)[)|\]]$/i, /\s*[(|[](live)[)|\]]$/i,
/\s*[(|\[]4K\s*?(?:upgrade)?[)|\]]$/i, /\s*[(|[]4K\s*?(?:upgrade)?[)|\]]$/i,
]; ];
export function cleanupName(name: string): string { export function cleanupName(name: string): string {

View File

@ -172,10 +172,19 @@ async function onApiLoaded() {
// Remove upgrade button // Remove upgrade button
if (window.mainConfig.get('options.removeUpgradeButton')) { if (window.mainConfig.get('options.removeUpgradeButton')) {
const itemsSelector = 'ytmusic-guide-section-renderer #items';
let selector = 'ytmusic-guide-entry-renderer:last-child';
const upgradeBtnIcon = document.querySelector<SVGGElement>('iron-iconset-svg[name="yt-sys-icons"] #youtube_music_monochrome');
if (upgradeBtnIcon) {
const path = upgradeBtnIcon.firstChild as SVGPathElement;
const data = path.getAttribute('d')!.substring(0, 15);
selector = `ytmusic-guide-entry-renderer:has(> tp-yt-paper-item > yt-icon path[d^="${data}"])`;
}
const styles = document.createElement('style'); const styles = document.createElement('style');
styles.innerHTML = `ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer:last-child { styles.textContent = `${itemsSelector} ${selector} { display: none; }`;
display: none;
}`;
document.head.appendChild(styles); document.head.appendChild(styles);
} }

View File

@ -5,3 +5,17 @@ export interface QueueResponse {
autoPlaying?: boolean; autoPlaying?: boolean;
continuation?: string; continuation?: string;
} }
export interface WatchNextResponse {
playerOverlays: {
playerOverlayRenderer: {
browserMediaSession: {
browserMediaSessionRenderer: {
album: {
runs: { text: string; }[]
}
}
}
}
};
}

View File

@ -3,6 +3,7 @@
import { VideoDetails } from './video-details'; import { VideoDetails } from './video-details';
import { GetPlayerResponse } from './get-player-response'; import { GetPlayerResponse } from './get-player-response';
import { PlayerAPIEvents } from './player-api-events'; import { PlayerAPIEvents } from './player-api-events';
import { WatchNextResponse } from '@/types/youtube-music-desktop-internal';
export interface YoutubePlayer { export interface YoutubePlayer {
getInternalApiInterface: <Parameters extends unknown[], Return>( getInternalApiInterface: <Parameters extends unknown[], Return>(
@ -427,4 +428,6 @@ export interface YoutubePlayer {
addEmbedsConversionTrackingParams: <Parameters extends unknown[], Return>( addEmbedsConversionTrackingParams: <Parameters extends unknown[], Return>(
...params: Parameters ...params: Parameters
) => Return; ) => Return;
getWatchNextResponse(): WatchNextResponse;
} }