Compare commits

...

93 Commits

Author SHA1 Message Date
semantic-release-bot
3e796eb7c2 chore(release): 4.14.2-dev.1 [skip ci]
## [4.14.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.1...v4.14.2-dev.1) (2024-09-21)

### Bug Fixes

* **TikTok - Playback speed:** Prevent crash by fixing invalid patch ([ff8fe46](ff8fe46685))
* **TikTok - Settings:** Prevent crash by fixing invalid patch ([0ab7344](0ab7344295))
* **Twitter - Open links with app chooser:** Constrain patch to last working version `10.48.0-release` ([303d2de](303d2de81d))
2024-09-21 23:20:21 +00:00
oSumAtrIX
303d2de81d fix(Twitter - Open links with app chooser): Constrain patch to last working version 10.48.0-release 2024-09-22 01:18:04 +02:00
oSumAtrIX
0ab7344295 fix(TikTok - Settings): Prevent crash by fixing invalid patch 2024-09-22 01:17:53 +02:00
oSumAtrIX
ff8fe46685 fix(TikTok - Playback speed): Prevent crash by fixing invalid patch 2024-09-22 01:17:47 +02:00
semantic-release-bot
18b09168cc chore(release): 4.14.1 [skip ci]
## [4.14.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.0...v4.14.1) (2024-09-18)

### Bug Fixes

* **YouTube - Check environment:** Only use fields available since Android 8 ([#3655](https://github.com/ReVanced/revanced-patches/issues/3655)) ([e03c14c](e03c14cc01))
2024-09-18 23:02:35 +00:00
oSumAtrIX
f7209f0a53 chore: Merge branch dev to main (#3656) 2024-09-19 01:00:28 +02:00
semantic-release-bot
1fb3fc4857 chore(release): 4.14.1-dev.1 [skip ci]
## [4.14.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.0...v4.14.1-dev.1) (2024-09-18)

### Bug Fixes

* **YouTube - Check environment:** Only use fields available since Android 8 ([#3655](https://github.com/ReVanced/revanced-patches/issues/3655)) ([e03c14c](e03c14cc01))
2024-09-18 22:59:56 +00:00
oSumAtrIX
e03c14cc01 fix(YouTube - Check environment): Only use fields available since Android 8 (#3655) 2024-09-19 00:57:54 +02:00
semantic-release-bot
bed29d00dc chore(release): 4.14.0 [skip ci]
# [4.14.0](https://github.com/ReVanced/revanced-patches/compare/v4.13.3...v4.14.0) (2024-09-18)

### Bug Fixes

* **Pixiv - Hide ads:** Fix for latest version ([#3616](https://github.com/ReVanced/revanced-patches/issues/3616)) ([ff2c456](ff2c4564a0))
* **Soundcloud - Hide ads:** Support latest version ([#3628](https://github.com/ReVanced/revanced-patches/issues/3628)) ([2f7d751](2f7d751f9f))
* **SwissID:** Rename `Remove Google Play Integrity Integrity check` to `Remove Google Play Integrity check` ([#3558](https://github.com/ReVanced/revanced-patches/issues/3558)) ([bdd2f7c](bdd2f7cb0f))
* **YouTube - ReturnYouTubeDislike:** Show estimated like count for videos with hidden likes ([#3601](https://github.com/ReVanced/revanced-patches/issues/3601)) ([70470a9](70470a9162))
* **YouTube - SponsorBlock:** Add summary text to 'view my segments' button ([a642705](a64270514f))
* **YouTube - SponsorBlock:** Handle if the user enters an invalid number into any SB settings ([a276425](a276425d83))
* **YouTube:** Fix issues related to playback by replace streaming data ([#3582](https://github.com/ReVanced/revanced-patches/issues/3582)) ([5b1e07d](5b1e07d861))

### Features

* Add `Change data directory location` patch ([#3602](https://github.com/ReVanced/revanced-patches/issues/3602)) ([96e6f43](96e6f43ca0))
* Add `Check environment` patch ([#3610](https://github.com/ReVanced/revanced-patches/issues/3610)) ([4c2ec28](4c2ec2870c))
* **Duolingo:** Add `Disable ads` and `Enable debug menu` patch ([#3422](https://github.com/ReVanced/revanced-patches/issues/3422)) ([4e323aa](4e323aa206))
* **Sync for Reddit:** Add `Fix /user/ endpoint` patch ([16217f0](16217f012e))
* **Sync for Reddit:** Rename patch to `Use /user/ endpoint` ([5871923](58719239cf))
* **YouTube - Hide Shorts components:** Hide 'Use this sound' button ([#3647](https://github.com/ReVanced/revanced-patches/issues/3647)) ([395e18d](395e18d830))
* **YouTube - Keyword filter:** Add syntax to match whole keywords and not substrings ([#3592](https://github.com/ReVanced/revanced-patches/issues/3592)) ([ed532eb](ed532eb528))
* **YouTube - Spoof client:** Allow forcing AVC codec with iOS ([#3570](https://github.com/ReVanced/revanced-patches/issues/3570)) ([6bb848b](6bb848b991))
* **YouTube Music:** Make working patches compatible with latest versions ([#3556](https://github.com/ReVanced/revanced-patches/issues/3556)) ([f83e314](f83e314dff))
* **YouTube:** Add donation link to settings about screen ([#3626](https://github.com/ReVanced/revanced-patches/issues/3626)) ([bccd62e](bccd62e593))
2024-09-18 22:19:44 +00:00
LisoUseInAIKyrios
d36982e245 chore: Merge branch dev to main (#3559) 2024-09-18 18:17:22 -04:00
ReVanced Bot
13031f0534 chore: Sync translations (#3653) 2024-09-18 17:48:02 -04:00
semantic-release-bot
b5b6ef5d6f chore(release): 4.14.0-dev.15 [skip ci]
# [4.14.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.14...v4.14.0-dev.15) (2024-09-17)

### Bug Fixes

* **YouTube:** Fix issues related to playback by replace streaming data ([#3582](https://github.com/ReVanced/revanced-patches/issues/3582)) ([5b1e07d](5b1e07d861))
2024-09-17 22:47:28 +00:00
Zain
5b1e07d861 fix(YouTube): Fix issues related to playback by replace streaming data (#3582)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-09-18 00:45:02 +02:00
ReVanced Bot
e3220cc10a chore: Sync translations (#3649) 2024-09-17 12:37:00 -04:00
semantic-release-bot
02db9378ea chore(release): 4.14.0-dev.14 [skip ci]
# [4.14.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.13...v4.14.0-dev.14) (2024-09-17)

### Features

* **YouTube Music:** Make working patches compatible with latest versions ([#3556](https://github.com/ReVanced/revanced-patches/issues/3556)) ([f83e314](f83e314dff))
2024-09-17 13:58:02 +00:00
Pun Butrach
f83e314dff feat(YouTube Music): Make working patches compatible with latest versions (#3556) 2024-09-17 15:56:00 +02:00
semantic-release-bot
d5e383b78a chore(release): 4.14.0-dev.13 [skip ci]
# [4.14.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.12...v4.14.0-dev.13) (2024-09-17)

### Features

* **YouTube - Hide Shorts components:** Hide 'Use this sound' button ([#3647](https://github.com/ReVanced/revanced-patches/issues/3647)) ([395e18d](395e18d830))
2024-09-17 13:36:53 +00:00
MarcaD
395e18d830 feat(YouTube - Hide Shorts components): Hide 'Use this sound' button (#3647) 2024-09-17 15:34:31 +02:00
semantic-release-bot
887684e7c7 chore(release): 4.14.0-dev.12 [skip ci]
# [4.14.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.11...v4.14.0-dev.12) (2024-09-14)

### Bug Fixes

* **Soundcloud - Hide ads:** Support latest version ([#3628](https://github.com/ReVanced/revanced-patches/issues/3628)) ([2f7d751](2f7d751f9f))
2024-09-14 15:09:54 +00:00
FullerBread2032
2f7d751f9f fix(Soundcloud - Hide ads): Support latest version (#3628)
Co-authored-by: FullerBread2032 <admin@fullerbread2032.tk>
2024-09-14 17:07:27 +02:00
semantic-release-bot
4886a95713 chore(release): 4.14.0-dev.11 [skip ci]
# [4.14.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.10...v4.14.0-dev.11) (2024-09-12)

### Features

* **Sync for Reddit:** Rename patch to `Use /user/ endpoint` ([5871923](58719239cf))
2024-09-12 20:11:21 +00:00
oSumAtrIX
58719239cf feat(Sync for Reddit): Rename patch to Use /user/ endpoint
The bug it was used to fix does not occur anymore. This name is more correct on what the patch actually does.
2024-09-12 22:09:09 +02:00
semantic-release-bot
fcb68cc65e chore(release): 4.14.0-dev.10 [skip ci]
# [4.14.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.9...v4.14.0-dev.10) (2024-09-12)

### Features

* **Sync for Reddit:** Add `Fix /user/ endpoint` patch ([16217f0](16217f012e))
2024-09-12 18:30:19 +00:00
oSumAtrIX
16217f012e feat(Sync for Reddit): Add Fix /user/ endpoint patch 2024-09-12 20:18:22 +02:00
semantic-release-bot
d6f20ee67d chore(release): 4.14.0-dev.9 [skip ci]
# [4.14.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.8...v4.14.0-dev.9) (2024-09-09)

### Features

* **YouTube:** Add donation link to settings about screen ([#3626](https://github.com/ReVanced/revanced-patches/issues/3626)) ([bccd62e](bccd62e593))
2024-09-09 07:23:22 +00:00
LisoUseInAIKyrios
bccd62e593 feat(YouTube): Add donation link to settings about screen (#3626) 2024-09-09 03:21:22 -04:00
semantic-release-bot
1322403698 chore(release): 4.14.0-dev.8 [skip ci]
# [4.14.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.7...v4.14.0-dev.8) (2024-09-09)

### Bug Fixes

* **YouTube - SponsorBlock:** Add summary text to 'view my segments' button ([a642705](a64270514f))
2024-09-09 07:19:55 +00:00
LisoUseInAIKyrios
a64270514f fix(YouTube - SponsorBlock): Add summary text to 'view my segments' button 2024-09-09 03:17:43 -04:00
semantic-release-bot
f5de555adf chore(release): 4.14.0-dev.7 [skip ci]
# [4.14.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.6...v4.14.0-dev.7) (2024-09-06)

### Features

* Add `Check environment` patch ([#3610](https://github.com/ReVanced/revanced-patches/issues/3610)) ([4c2ec28](4c2ec2870c))
2024-09-06 08:29:07 +00:00
oSumAtrIX
4c2ec2870c feat: Add Check environment patch (#3610)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>
2024-09-06 10:26:53 +02:00
semantic-release-bot
a73e2458e9 chore(release): 4.14.0-dev.6 [skip ci]
# [4.14.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.5...v4.14.0-dev.6) (2024-09-06)

### Features

* Add `Change data directory location` patch ([#3602](https://github.com/ReVanced/revanced-patches/issues/3602)) ([96e6f43](96e6f43ca0))
2024-09-06 07:47:45 +00:00
KrystianQur
96e6f43ca0 feat: Add Change data directory location patch (#3602)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-09-06 09:45:40 +02:00
semantic-release-bot
f667d5a238 chore(release): 4.14.0-dev.5 [skip ci]
# [4.14.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.4...v4.14.0-dev.5) (2024-09-06)

### Bug Fixes

* **Pixiv - Hide ads:** Fix for latest version ([#3616](https://github.com/ReVanced/revanced-patches/issues/3616)) ([ff2c456](ff2c4564a0))
2024-09-06 07:16:05 +00:00
Itroublve
ff2c4564a0 fix(Pixiv - Hide ads): Fix for latest version (#3616)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-09-06 09:13:57 +02:00
semantic-release-bot
b568207e49 chore(release): 4.14.0-dev.4 [skip ci]
# [4.14.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.3...v4.14.0-dev.4) (2024-09-01)

### Bug Fixes

* **YouTube - ReturnYouTubeDislike:** Show estimated like count for videos with hidden likes ([#3601](https://github.com/ReVanced/revanced-patches/issues/3601)) ([70470a9](70470a9162))
2024-09-01 21:51:42 +00:00
LisoUseInAIKyrios
70470a9162 fix(YouTube - ReturnYouTubeDislike): Show estimated like count for videos with hidden likes (#3601) 2024-09-01 17:49:42 -04:00
semantic-release-bot
9922f47a49 chore(release): 4.14.0-dev.3 [skip ci]
# [4.14.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.2...v4.14.0-dev.3) (2024-08-30)

### Features

* **YouTube - Keyword filter:** Add syntax to match whole keywords and not substrings ([#3592](https://github.com/ReVanced/revanced-patches/issues/3592)) ([ed532eb](ed532eb528))
2024-08-30 21:40:57 +00:00
LisoUseInAIKyrios
ed532eb528 feat(YouTube - Keyword filter): Add syntax to match whole keywords and not substrings (#3592) 2024-08-30 17:38:59 -04:00
ReVanced Bot
74f3f82927 chore: Sync translations (#3593) 2024-08-28 22:33:49 -04:00
semantic-release-bot
6544cd5fc6 chore(release): 4.14.0-dev.2 [skip ci]
# [4.14.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.1...v4.14.0-dev.2) (2024-08-24)

### Features

* **Duolingo:** Add `Disable ads` and `Enable debug menu` patch ([#3422](https://github.com/ReVanced/revanced-patches/issues/3422)) ([4e323aa](4e323aa206))
2024-08-24 12:46:50 +00:00
Joshua May
4e323aa206 feat(Duolingo): Add Disable ads and Enable debug menu patch (#3422)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2024-08-24 14:44:35 +02:00
ReVanced Bot
c1cee281ff chore: Sync translations (#3574) 2024-08-23 00:37:22 -04:00
ReVanced Bot
0779f9fc5e chore: Sync translations (#3573) 2024-08-23 00:13:52 -04:00
semantic-release-bot
0ee5cf98ab chore(release): 4.14.0-dev.1 [skip ci]
# [4.14.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.4-dev.2...v4.14.0-dev.1) (2024-08-22)

### Features

* **YouTube - Spoof client:** Allow forcing AVC codec with iOS ([#3570](https://github.com/ReVanced/revanced-patches/issues/3570)) ([6bb848b](6bb848b991))
2024-08-22 17:51:00 +00:00
LisoUseInAIKyrios
6bb848b991 feat(YouTube - Spoof client): Allow forcing AVC codec with iOS (#3570) 2024-08-22 13:48:49 -04:00
semantic-release-bot
188b66ffe7 chore(release): 4.13.4-dev.2 [skip ci]
## [4.13.4-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.4-dev.1...v4.13.4-dev.2) (2024-08-20)

### Bug Fixes

* **YouTube - SponsorBlock:** Handle if the user enters an invalid number into any SB settings ([a276425](a276425d83))
2024-08-20 04:19:14 +00:00
LisoUseInAIKyrios
a276425d83 fix(YouTube - SponsorBlock): Handle if the user enters an invalid number into any SB settings 2024-08-20 00:17:11 -04:00
LisoUseInAIKyrios
e556c3f692 chore: Sync translations (#3564) 2024-08-20 00:16:08 -04:00
revanced-bot
cb30248eab chore: Sync translations 2024-08-20 04:15:01 +00:00
semantic-release-bot
c5ce742ab4 chore(release): 4.13.4-dev.1 [skip ci]
## [4.13.4-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.3...v4.13.4-dev.1) (2024-08-18)

### Bug Fixes

* **SwissID:** Rename `Remove Google Play Integrity Integrity check` to `Remove Google Play Integrity check` ([#3558](https://github.com/ReVanced/revanced-patches/issues/3558)) ([bdd2f7c](bdd2f7cb0f))
2024-08-18 13:22:20 +00:00
Pun Butrach
bdd2f7cb0f fix(SwissID): Rename Remove Google Play Integrity Integrity check to Remove Google Play Integrity check (#3558) 2024-08-18 17:20:23 +04:00
semantic-release-bot
b7600f448d chore(release): 4.13.3 [skip ci]
## [4.13.3](https://github.com/ReVanced/revanced-patches/compare/v4.13.2...v4.13.3) (2024-08-15)

### Bug Fixes

* **YouTube:** Remove translated string that breaks patching ([aa3487a](aa3487aa92))
2024-08-15 20:40:18 +00:00
LisoUseInAIKyrios
5c4bf7676d chore: Merge branch dev to main (#3552) 2024-08-15 16:38:21 -04:00
semantic-release-bot
fcd2f9b4c4 chore(release): 4.13.3-dev.1 [skip ci]
## [4.13.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.2...v4.13.3-dev.1) (2024-08-15)

### Bug Fixes

* **YouTube:** Remove translated string that breaks patching ([aa3487a](aa3487aa92))
2024-08-15 20:36:50 +00:00
LisoUseInAIKyrios
aa3487aa92 fix(YouTube): Remove translated string that breaks patching 2024-08-15 16:34:52 -04:00
LisoUseInAIKyrios
ada642f4a7 chore: Merge branch dev to main (#3551) 2024-08-15 16:29:00 -04:00
LisoUseInAIKyrios
eac758588a chore: Remove non breaking space from German translation 2024-08-15 16:14:36 -04:00
ReVanced Bot
5d047eae77 chore: Sync translations (#3550) 2024-08-15 15:58:52 -04:00
semantic-release-bot
ed92bf1be6 chore(release): 4.13.2 [skip ci]
## [4.13.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.1...v4.13.2) (2024-08-15)

### Bug Fixes

* **YouTube - GmsCore Support:** Fix patch exception by using correct patch offset ([#3543](https://github.com/ReVanced/revanced-patches/issues/3543)) ([3d0d94b](3d0d94b6c8))
2024-08-15 18:39:08 +00:00
oSumAtrIX
c6318e890f chore: Merge branch dev to main (#3544) 2024-08-15 22:37:04 +04:00
semantic-release-bot
7f3b1c54da chore(release): 4.13.2-dev.1 [skip ci]
## [4.13.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.1...v4.13.2-dev.1) (2024-08-15)

### Bug Fixes

* **YouTube - GmsCore Support:** Fix patch exception by using correct patch offset ([#3543](https://github.com/ReVanced/revanced-patches/issues/3543)) ([3d0d94b](3d0d94b6c8))
2024-08-15 18:35:56 +00:00
LisoUseInAIKyrios
3d0d94b6c8 fix(YouTube - GmsCore Support): Fix patch exception by using correct patch offset (#3543) 2024-08-15 22:33:53 +04:00
semantic-release-bot
b84e6afebd chore(release): 4.13.1 [skip ci]
## [4.13.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.0...v4.13.1) (2024-08-15)

### Bug Fixes

* **YouTube - Check watch history domain name resolution:** Add compatibility field ([d7be94a](d7be94a193))
2024-08-15 17:58:11 +00:00
oSumAtrIX
3eab130276 chore: Merge branch dev to main (#3541) 2024-08-15 21:55:53 +04:00
semantic-release-bot
95f8e9b3a9 chore(release): 4.13.1-dev.1 [skip ci]
## [4.13.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.0...v4.13.1-dev.1) (2024-08-15)

### Bug Fixes

* **YouTube - Check watch history domain name resolution:** Add compatibility field ([d7be94a](d7be94a193))
2024-08-15 17:53:15 +00:00
LisoUseInAIKyrios
d7be94a193 fix(YouTube - Check watch history domain name resolution): Add compatibility field 2024-08-15 13:51:02 -04:00
semantic-release-bot
e4e20bec6c chore(release): 4.13.0 [skip ci]
# [4.13.0](https://github.com/ReVanced/revanced-patches/compare/v4.12.0...v4.13.0) (2024-08-15)

### Bug Fixes

* **YouTube - GmsCore support:** Fix notifications not working by using the correct permissions ([c64757f](c64757f80a))

### Features

* **Google Photos:** Add `Spoof features` patch ([#3459](https://github.com/ReVanced/revanced-patches/issues/3459)) ([f814d87](f814d87c17))
* **SCB Easy:** Remove broken `Remove debugging detection` patch ([#3518](https://github.com/ReVanced/revanced-patches/issues/3518)) ([45e4f70](45e4f70137))
* **YouTube:** Add `Check watch history domain name resolution` patch ([#3537](https://github.com/ReVanced/revanced-patches/issues/3537)) ([87eb836](87eb83607c))
2024-08-15 17:29:30 +00:00
oSumAtrIX
b8bd63a34c chore: Merge branch dev to main (#3533) 2024-08-15 21:26:59 +04:00
semantic-release-bot
8b602ca6be chore(release): 4.13.0-dev.2 [skip ci]
# [4.13.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.0-dev.1...v4.13.0-dev.2) (2024-08-15)

### Features

* **YouTube:** Add `Check watch history domain name resolution` patch ([#3537](https://github.com/ReVanced/revanced-patches/issues/3537)) ([87eb836](87eb83607c))
2024-08-15 16:08:55 +00:00
LisoUseInAIKyrios
87eb83607c feat(YouTube): Add Check watch history domain name resolution patch (#3537)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-08-15 12:06:19 -04:00
semantic-release-bot
567121d641 chore(release): 4.13.0-dev.1 [skip ci]
# [4.13.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.12.1-dev.1...v4.13.0-dev.1) (2024-08-15)

### Features

* **Google Photos:** Add `Spoof features` patch ([#3459](https://github.com/ReVanced/revanced-patches/issues/3459)) ([f814d87](f814d87c17))
* **SCB Easy:** Remove broken `Remove debugging detection` patch ([#3518](https://github.com/ReVanced/revanced-patches/issues/3518)) ([45e4f70](45e4f70137))
2024-08-15 05:47:21 +00:00
Pun Butrach
45e4f70137 feat(SCB Easy): Remove broken Remove debugging detection patch (#3518)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-08-15 07:45:00 +02:00
oSumAtrIX
f814d87c17 feat(Google Photos): Add Spoof features patch (#3459) 2024-08-15 07:43:01 +02:00
semantic-release-bot
d0e92b225e chore(release): 4.12.1-dev.1 [skip ci]
## [4.12.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.12.0...v4.12.1-dev.1) (2024-08-15)

### Bug Fixes

* **YouTube - GmsCore support:** Fix notifications not working by using the correct permissions ([c64757f](c64757f80a))
2024-08-15 05:41:06 +00:00
oSumAtrIX
c64757f80a fix(YouTube - GmsCore support): Fix notifications not working by using the correct permissions
Regression had been introduced in 1af65de1f6. This commit reverts this.
2024-08-15 07:39:00 +02:00
ReVanced Bot
58b6f1fba0 chore: Sync translations (#3532) 2024-08-13 01:13:23 -04:00
semantic-release-bot
630857ba16 chore(release): 4.12.0 [skip ci]
# [4.12.0](https://github.com/ReVanced/revanced-patches/compare/v4.11.0...v4.12.0) (2024-08-06)

### Bug Fixes

* **Google Photos - GmsCore support:** Fix by checking first if a method exists before trying to patch it ([26449cf](26449cf7c6))
* **Instagram - Hide ads:**  Restore compatibility with latest version by fixing fingerprint ([#3455](https://github.com/ReVanced/revanced-patches/issues/3455)) ([f2bf2da](f2bf2da9a5))
* **Messenger - Disable switching emoji to sticker:** Constrain to last working version `439.0.0.29.119` ([1cf25f9](1cf25f9dc9))
* **SoundCloud - Enable offline sync:** Stop crashing by reversing order of patching instructions from last to first to retain indices ([98f9bba](98f9bba7ed))
* **YouTube - Bypass image region restrictions:** Move setting to `Misc` menu ([7acb6cd](7acb6cdc96))
* **YouTube - Client Spoof:** Restore missing high qualities by spoofing the iOS client user agent ([#3468](https://github.com/ReVanced/revanced-patches/issues/3468)) ([a4b0e76](a4b0e76755))
* **YouTube - Hide keyword content:** Do not hide flyout menu ([cfbc4aa](cfbc4aa6b2))
* **YouTube - SponsorBlock:** Correctly show minute timestamp when creating a new segment ([8886fc4](8886fc4f54))
* **YouTube - SponsorBlock:** Improve create segment manual seek accuracy ([#3491](https://github.com/ReVanced/revanced-patches/issues/3491)) ([2e8d5c6](2e8d5c61f8))
* **YouTube - Spoof client:** Fix tracking history on brand accounts ([#3480](https://github.com/ReVanced/revanced-patches/issues/3480)) ([eed856d](eed856d64c))
* **YouTube - Spoof client:** Restore livestream audio only playback with iOS spoofing ([#3504](https://github.com/ReVanced/revanced-patches/issues/3504)) ([eadbf5f](eadbf5f459))

### Features

* Add `Hide mock location` patch ([#3417](https://github.com/ReVanced/revanced-patches/issues/3417)) ([250cc7c](250cc7cbde))
* Add `Spoof build info` patch ([d87f36e](d87f36e7e2))
* **Boost for Reddit:** Add `Disable ads` patch ([#3474](https://github.com/ReVanced/revanced-patches/issues/3474)) ([d2afc53](d2afc53c2b))
* **CandyLink:** Remove non-functional `Unlock pro` patch ([1e81d0c](1e81d0c9f8))
* **Expense Manager:** Remove non-functional `Unlock pro` patch ([e4232b6](e4232b6c74))
* **Google News:** Add `Enable CustomTabs` and `GmsCore support` patch ([#3111](https://github.com/ReVanced/revanced-patches/issues/3111)) ([273af26](273af26274))
* **Google Photos:** Add `GmsCore support` patch ([#3414](https://github.com/ReVanced/revanced-patches/issues/3414)) ([1af65de](1af65de1f6))
* **Instagram:** Remove unnecessary `Hide timeline ads` patch ([8038bd2](8038bd2e98))
* **SoundCloud:** Add `Enable offline sync` patch ([#3407](https://github.com/ReVanced/revanced-patches/issues/3407)) ([b944fb7](b944fb7bf1))
* **SwissID:** Add `Remove Google Play Integrity Integrity check` patch ([#3478](https://github.com/ReVanced/revanced-patches/issues/3478)) ([3380080](33800801a3))
* **YouTube - Description components:** Add `Hide 'Key concepts' section` option ([#3495](https://github.com/ReVanced/revanced-patches/issues/3495)) ([337bdc3](337bdc3d39))
* **YouTube:** Add `Bypass image region restrictions` patch ([#3442](https://github.com/ReVanced/revanced-patches/issues/3442)) ([9ef51ab](9ef51abde7))
2024-08-06 00:08:03 +00:00
oSumAtrIX
82ae367946 chore: Merge branch dev to main (#3438) 2024-08-06 02:05:44 +02:00
semantic-release-bot
95a7118dcf chore(release): 4.12.0-dev.17 [skip ci]
# [4.12.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.16...v4.12.0-dev.17) (2024-08-06)

### Bug Fixes

* **Google Photos - GmsCore support:** Fix by checking first if a method exists before trying to patch it ([26449cf](26449cf7c6))
* **Messenger - Disable switching emoji to sticker:** Constrain to last working version `439.0.0.29.119` ([1cf25f9](1cf25f9dc9))

### Features

* **CandyLink:** Remove non-functional `Unlock pro` patch ([1e81d0c](1e81d0c9f8))
* **Expense Manager:** Remove non-functional `Unlock pro` patch ([e4232b6](e4232b6c74))
* **Instagram:** Remove unnecessary `Hide timeline ads` patch ([8038bd2](8038bd2e98))
2024-08-06 00:04:26 +00:00
oSumAtrIX
26449cf7c6 fix(Google Photos - GmsCore support): Fix by checking first if a method exists before trying to patch it 2024-08-06 02:01:44 +02:00
oSumAtrIX
e4232b6c74 feat(Expense Manager): Remove non-functional Unlock pro patch 2024-08-06 01:40:11 +02:00
oSumAtrIX
1cf25f9dc9 fix(Messenger - Disable switching emoji to sticker): Constrain to last working version 439.0.0.29.119 2024-08-06 01:31:46 +02:00
oSumAtrIX
8038bd2e98 feat(Instagram): Remove unnecessary Hide timeline ads patch
The `Hide ads` patch supersedes this patch.
2024-08-06 01:27:06 +02:00
oSumAtrIX
1e81d0c9f8 feat(CandyLink): Remove non-functional Unlock pro patch
Servers now check the purchase status.
2024-08-06 01:25:28 +02:00
ReVanced Bot
c48cedaddf chore: Sync translations (#3507) 2024-08-05 15:56:44 -04:00
semantic-release-bot
4085d1f9dc chore(release): 4.12.0-dev.16 [skip ci]
# [4.12.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.15...v4.12.0-dev.16) (2024-08-04)

### Bug Fixes

* **YouTube - Spoof client:** Restore livestream audio only playback with iOS spoofing ([#3504](https://github.com/ReVanced/revanced-patches/issues/3504)) ([eadbf5f](eadbf5f459))
2024-08-04 19:40:12 +00:00
LisoUseInAIKyrios
eadbf5f459 fix(YouTube - Spoof client): Restore livestream audio only playback with iOS spoofing (#3504) 2024-08-04 21:38:10 +02:00
ILoveOpenSourceApplications
b12b3a73a6 refactor(YouTube Music): Rename Hide music video ads to Hide video ads and add patch description (#3494)
Co-authored-by: ILoveOpenSourceApplications <ILoveOpenSourceApplications@users.noreply.github.com>
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2024-08-04 10:09:48 +02:00
semantic-release-bot
572a310589 chore(release): 4.12.0-dev.15 [skip ci]
# [4.12.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.14...v4.12.0-dev.15) (2024-08-02)

### Bug Fixes

* **YouTube - SponsorBlock:** Improve create segment manual seek accuracy ([#3491](https://github.com/ReVanced/revanced-patches/issues/3491)) ([2e8d5c6](2e8d5c61f8))
2024-08-02 13:42:52 +00:00
LisoUseInAIKyrios
2e8d5c61f8 fix(YouTube - SponsorBlock): Improve create segment manual seek accuracy (#3491) 2024-08-02 09:40:28 -04:00
ReVanced Bot
025766bb42 chore: Sync translations (#3499) 2024-08-02 09:37:23 -04:00
semantic-release-bot
e31966159a chore(release): 4.12.0-dev.14 [skip ci]
# [4.12.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.13...v4.12.0-dev.14) (2024-08-01)

### Features

* **YouTube - Description components:** Add `Hide 'Key concepts' section` option ([#3495](https://github.com/ReVanced/revanced-patches/issues/3495)) ([337bdc3](337bdc3d39))
2024-08-01 11:29:29 +00:00
ILoveOpenSourceApplications
337bdc3d39 feat(YouTube - Description components): Add Hide 'Key concepts' section option (#3495)
Co-authored-by: ILoveOpenSourceApplications <ILoveOpenSourceApplications@users.noreply.github.com>
2024-08-01 13:27:28 +02:00
180 changed files with 8003 additions and 7045 deletions

View File

@@ -1,3 +1,319 @@
## [4.14.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.1...v4.14.2-dev.1) (2024-09-21)
### Bug Fixes
* **TikTok - Playback speed:** Prevent crash by fixing invalid patch ([82d53cb](https://github.com/ReVanced/revanced-patches/commit/82d53cbc3bbfa585ba4337fdfaec9f0f19c802e6))
* **TikTok - Settings:** Prevent crash by fixing invalid patch ([8074032](https://github.com/ReVanced/revanced-patches/commit/8074032fad3eff1c03296a882d2e2820da99b592))
* **Twitter - Open links with app chooser:** Constrain patch to last working version `10.48.0-release` ([b9955d5](https://github.com/ReVanced/revanced-patches/commit/b9955d5ff6e456593b01f0f25d80ff660d02082a))
## [4.14.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.0...v4.14.1) (2024-09-18)
### Bug Fixes
* **YouTube - Check environment:** Only use fields available since Android 8 ([#3655](https://github.com/ReVanced/revanced-patches/issues/3655)) ([4413533](https://github.com/ReVanced/revanced-patches/commit/441353306572340131030e1c4fee1ab6acb63cd9))
## [4.14.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.0...v4.14.1-dev.1) (2024-09-18)
### Bug Fixes
* **YouTube - Check environment:** Only use fields available since Android 8 ([#3655](https://github.com/ReVanced/revanced-patches/issues/3655)) ([4413533](https://github.com/ReVanced/revanced-patches/commit/441353306572340131030e1c4fee1ab6acb63cd9))
# [4.14.0](https://github.com/ReVanced/revanced-patches/compare/v4.13.3...v4.14.0) (2024-09-18)
### Bug Fixes
* **Pixiv - Hide ads:** Fix for latest version ([#3616](https://github.com/ReVanced/revanced-patches/issues/3616)) ([98956e8](https://github.com/ReVanced/revanced-patches/commit/98956e8f1a41347bb435720bbf984969469a7110))
* **Soundcloud - Hide ads:** Support latest version ([#3628](https://github.com/ReVanced/revanced-patches/issues/3628)) ([66e7e33](https://github.com/ReVanced/revanced-patches/commit/66e7e33efce9b702fdfcc2b9803e9da8491c1f08))
* **SwissID:** Rename `Remove Google Play Integrity Integrity check` to `Remove Google Play Integrity check` ([#3558](https://github.com/ReVanced/revanced-patches/issues/3558)) ([0f5a771](https://github.com/ReVanced/revanced-patches/commit/0f5a771a5cff5684b4a8fd317f4938fe2cf3cbbe))
* **YouTube - ReturnYouTubeDislike:** Show estimated like count for videos with hidden likes ([#3601](https://github.com/ReVanced/revanced-patches/issues/3601)) ([005be82](https://github.com/ReVanced/revanced-patches/commit/005be82d71b2a42387b1b57035930b20f4663794))
* **YouTube - SponsorBlock:** Add summary text to 'view my segments' button ([df80b9f](https://github.com/ReVanced/revanced-patches/commit/df80b9f92f0d981b9a40b7756d74f8ccc3dcb1e9))
* **YouTube - SponsorBlock:** Handle if the user enters an invalid number into any SB settings ([37b3dd1](https://github.com/ReVanced/revanced-patches/commit/37b3dd1e789f8bb16fa1b9dd582e39c89dbe730c))
* **YouTube:** Fix issues related to playback by replace streaming data ([#3582](https://github.com/ReVanced/revanced-patches/issues/3582)) ([dfa94d7](https://github.com/ReVanced/revanced-patches/commit/dfa94d70f65150d6ef24ea6378b8e6a317055186))
### Features
* Add `Change data directory location` patch ([#3602](https://github.com/ReVanced/revanced-patches/issues/3602)) ([5998029](https://github.com/ReVanced/revanced-patches/commit/59980292809cc0626bf49a160eeb05a1523c4eda))
* Add `Check environment` patch ([#3610](https://github.com/ReVanced/revanced-patches/issues/3610)) ([fbcbdaf](https://github.com/ReVanced/revanced-patches/commit/fbcbdafa4938a35b5fdec46aae7b250a84b9c139))
* **Duolingo:** Add `Disable ads` and `Enable debug menu` patch ([#3422](https://github.com/ReVanced/revanced-patches/issues/3422)) ([d0a8599](https://github.com/ReVanced/revanced-patches/commit/d0a8599f76ce653e5d7c98069ad3c58b9ab9c5eb))
* **Sync for Reddit:** Add `Fix /user/ endpoint` patch ([46d11f3](https://github.com/ReVanced/revanced-patches/commit/46d11f3530fcdae9ed08b7e93aac235638a92dff))
* **Sync for Reddit:** Rename patch to `Use /user/ endpoint` ([98ead49](https://github.com/ReVanced/revanced-patches/commit/98ead493380932cb105530f4ba992673fd364d82))
* **YouTube - Hide Shorts components:** Hide 'Use this sound' button ([#3647](https://github.com/ReVanced/revanced-patches/issues/3647)) ([33fc090](https://github.com/ReVanced/revanced-patches/commit/33fc09061431d4aa457d743c09a0de31ec566df1))
* **YouTube - Keyword filter:** Add syntax to match whole keywords and not substrings ([#3592](https://github.com/ReVanced/revanced-patches/issues/3592)) ([f5fb351](https://github.com/ReVanced/revanced-patches/commit/f5fb3512cfafe214ba6a6d25ba0825ae1884a0ff))
* **YouTube - Spoof client:** Allow forcing AVC codec with iOS ([#3570](https://github.com/ReVanced/revanced-patches/issues/3570)) ([1a49d1f](https://github.com/ReVanced/revanced-patches/commit/1a49d1f3c2a343d05d0abc07c143add486246fd0))
* **YouTube Music:** Make working patches compatible with latest versions ([#3556](https://github.com/ReVanced/revanced-patches/issues/3556)) ([12f6f19](https://github.com/ReVanced/revanced-patches/commit/12f6f1966ad04631451940f7b64d785c3ef481a0))
* **YouTube:** Add donation link to settings about screen ([#3626](https://github.com/ReVanced/revanced-patches/issues/3626)) ([0684ab5](https://github.com/ReVanced/revanced-patches/commit/0684ab5f183631de5720352049cfd293daa58eb0))
# [4.14.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.14...v4.14.0-dev.15) (2024-09-17)
### Bug Fixes
* **YouTube:** Fix issues related to playback by replace streaming data ([#3582](https://github.com/ReVanced/revanced-patches/issues/3582)) ([dfa94d7](https://github.com/ReVanced/revanced-patches/commit/dfa94d70f65150d6ef24ea6378b8e6a317055186))
# [4.14.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.13...v4.14.0-dev.14) (2024-09-17)
### Features
* **YouTube Music:** Make working patches compatible with latest versions ([#3556](https://github.com/ReVanced/revanced-patches/issues/3556)) ([12f6f19](https://github.com/ReVanced/revanced-patches/commit/12f6f1966ad04631451940f7b64d785c3ef481a0))
# [4.14.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.12...v4.14.0-dev.13) (2024-09-17)
### Features
* **YouTube - Hide Shorts components:** Hide 'Use this sound' button ([#3647](https://github.com/ReVanced/revanced-patches/issues/3647)) ([33fc090](https://github.com/ReVanced/revanced-patches/commit/33fc09061431d4aa457d743c09a0de31ec566df1))
# [4.14.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.11...v4.14.0-dev.12) (2024-09-14)
### Bug Fixes
* **Soundcloud - Hide ads:** Support latest version ([#3628](https://github.com/ReVanced/revanced-patches/issues/3628)) ([66e7e33](https://github.com/ReVanced/revanced-patches/commit/66e7e33efce9b702fdfcc2b9803e9da8491c1f08))
# [4.14.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.10...v4.14.0-dev.11) (2024-09-12)
### Features
* **Sync for Reddit:** Rename patch to `Use /user/ endpoint` ([98ead49](https://github.com/ReVanced/revanced-patches/commit/98ead493380932cb105530f4ba992673fd364d82))
# [4.14.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.9...v4.14.0-dev.10) (2024-09-12)
### Features
* **Sync for Reddit:** Add `Fix /user/ endpoint` patch ([46d11f3](https://github.com/ReVanced/revanced-patches/commit/46d11f3530fcdae9ed08b7e93aac235638a92dff))
# [4.14.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.8...v4.14.0-dev.9) (2024-09-09)
### Features
* **YouTube:** Add donation link to settings about screen ([#3626](https://github.com/ReVanced/revanced-patches/issues/3626)) ([0684ab5](https://github.com/ReVanced/revanced-patches/commit/0684ab5f183631de5720352049cfd293daa58eb0))
# [4.14.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.7...v4.14.0-dev.8) (2024-09-09)
### Bug Fixes
* **YouTube - SponsorBlock:** Add summary text to 'view my segments' button ([df80b9f](https://github.com/ReVanced/revanced-patches/commit/df80b9f92f0d981b9a40b7756d74f8ccc3dcb1e9))
# [4.14.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.6...v4.14.0-dev.7) (2024-09-06)
### Features
* Add `Check environment` patch ([#3610](https://github.com/ReVanced/revanced-patches/issues/3610)) ([fbcbdaf](https://github.com/ReVanced/revanced-patches/commit/fbcbdafa4938a35b5fdec46aae7b250a84b9c139))
# [4.14.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.5...v4.14.0-dev.6) (2024-09-06)
### Features
* Add `Change data directory location` patch ([#3602](https://github.com/ReVanced/revanced-patches/issues/3602)) ([5998029](https://github.com/ReVanced/revanced-patches/commit/59980292809cc0626bf49a160eeb05a1523c4eda))
# [4.14.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.4...v4.14.0-dev.5) (2024-09-06)
### Bug Fixes
* **Pixiv - Hide ads:** Fix for latest version ([#3616](https://github.com/ReVanced/revanced-patches/issues/3616)) ([98956e8](https://github.com/ReVanced/revanced-patches/commit/98956e8f1a41347bb435720bbf984969469a7110))
# [4.14.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.3...v4.14.0-dev.4) (2024-09-01)
### Bug Fixes
* **YouTube - ReturnYouTubeDislike:** Show estimated like count for videos with hidden likes ([#3601](https://github.com/ReVanced/revanced-patches/issues/3601)) ([005be82](https://github.com/ReVanced/revanced-patches/commit/005be82d71b2a42387b1b57035930b20f4663794))
# [4.14.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.2...v4.14.0-dev.3) (2024-08-30)
### Features
* **YouTube - Keyword filter:** Add syntax to match whole keywords and not substrings ([#3592](https://github.com/ReVanced/revanced-patches/issues/3592)) ([f5fb351](https://github.com/ReVanced/revanced-patches/commit/f5fb3512cfafe214ba6a6d25ba0825ae1884a0ff))
# [4.14.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.1...v4.14.0-dev.2) (2024-08-24)
### Features
* **Duolingo:** Add `Disable ads` and `Enable debug menu` patch ([#3422](https://github.com/ReVanced/revanced-patches/issues/3422)) ([d0a8599](https://github.com/ReVanced/revanced-patches/commit/d0a8599f76ce653e5d7c98069ad3c58b9ab9c5eb))
# [4.14.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.4-dev.2...v4.14.0-dev.1) (2024-08-22)
### Features
* **YouTube - Spoof client:** Allow forcing AVC codec with iOS ([#3570](https://github.com/ReVanced/revanced-patches/issues/3570)) ([1a49d1f](https://github.com/ReVanced/revanced-patches/commit/1a49d1f3c2a343d05d0abc07c143add486246fd0))
## [4.13.4-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.4-dev.1...v4.13.4-dev.2) (2024-08-20)
### Bug Fixes
* **YouTube - SponsorBlock:** Handle if the user enters an invalid number into any SB settings ([37b3dd1](https://github.com/ReVanced/revanced-patches/commit/37b3dd1e789f8bb16fa1b9dd582e39c89dbe730c))
## [4.13.4-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.3...v4.13.4-dev.1) (2024-08-18)
### Bug Fixes
* **SwissID:** Rename `Remove Google Play Integrity Integrity check` to `Remove Google Play Integrity check` ([#3558](https://github.com/ReVanced/revanced-patches/issues/3558)) ([0f5a771](https://github.com/ReVanced/revanced-patches/commit/0f5a771a5cff5684b4a8fd317f4938fe2cf3cbbe))
## [4.13.3](https://github.com/ReVanced/revanced-patches/compare/v4.13.2...v4.13.3) (2024-08-15)
### Bug Fixes
* **YouTube:** Remove translated string that breaks patching ([a48c2db](https://github.com/ReVanced/revanced-patches/commit/a48c2db53d84767c8fd5d569f9ce1c46c2bfd9a1))
## [4.13.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.2...v4.13.3-dev.1) (2024-08-15)
### Bug Fixes
* **YouTube:** Remove translated string that breaks patching ([a48c2db](https://github.com/ReVanced/revanced-patches/commit/a48c2db53d84767c8fd5d569f9ce1c46c2bfd9a1))
## [4.13.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.1...v4.13.2) (2024-08-15)
### Bug Fixes
* **YouTube - GmsCore Support:** Fix patch exception by using correct patch offset ([#3543](https://github.com/ReVanced/revanced-patches/issues/3543)) ([b2b8454](https://github.com/ReVanced/revanced-patches/commit/b2b8454aa992bcb217fb03eb4de5532e0a9bd354))
## [4.13.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.1...v4.13.2-dev.1) (2024-08-15)
### Bug Fixes
* **YouTube - GmsCore Support:** Fix patch exception by using correct patch offset ([#3543](https://github.com/ReVanced/revanced-patches/issues/3543)) ([b2b8454](https://github.com/ReVanced/revanced-patches/commit/b2b8454aa992bcb217fb03eb4de5532e0a9bd354))
## [4.13.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.0...v4.13.1) (2024-08-15)
### Bug Fixes
* **YouTube - Check watch history domain name resolution:** Add compatibility field ([6c598f0](https://github.com/ReVanced/revanced-patches/commit/6c598f084ed90ee1318e4c66d8c1751c797b8e3b))
## [4.13.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.0...v4.13.1-dev.1) (2024-08-15)
### Bug Fixes
* **YouTube - Check watch history domain name resolution:** Add compatibility field ([6c598f0](https://github.com/ReVanced/revanced-patches/commit/6c598f084ed90ee1318e4c66d8c1751c797b8e3b))
# [4.13.0](https://github.com/ReVanced/revanced-patches/compare/v4.12.0...v4.13.0) (2024-08-15)
### Bug Fixes
* **YouTube - GmsCore support:** Fix notifications not working by using the correct permissions ([19ddae2](https://github.com/ReVanced/revanced-patches/commit/19ddae2d15e513e18eb1556c468cd94bd197685b))
### Features
* **Google Photos:** Add `Spoof features` patch ([#3459](https://github.com/ReVanced/revanced-patches/issues/3459)) ([7c218cd](https://github.com/ReVanced/revanced-patches/commit/7c218cd168aa72eb99bcb47d12dfa45616e8ad88))
* **SCB Easy:** Remove broken `Remove debugging detection` patch ([#3518](https://github.com/ReVanced/revanced-patches/issues/3518)) ([f4e23cb](https://github.com/ReVanced/revanced-patches/commit/f4e23cbb8a24638318d8cee20a1991c51855d9d2))
* **YouTube:** Add `Check watch history domain name resolution` patch ([#3537](https://github.com/ReVanced/revanced-patches/issues/3537)) ([2af1425](https://github.com/ReVanced/revanced-patches/commit/2af142525cda07a131335faadd4b3889979fd077))
# [4.13.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.0-dev.1...v4.13.0-dev.2) (2024-08-15)
### Features
* **YouTube:** Add `Check watch history domain name resolution` patch ([#3537](https://github.com/ReVanced/revanced-patches/issues/3537)) ([2af1425](https://github.com/ReVanced/revanced-patches/commit/2af142525cda07a131335faadd4b3889979fd077))
# [4.13.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.12.1-dev.1...v4.13.0-dev.1) (2024-08-15)
### Features
* **Google Photos:** Add `Spoof features` patch ([#3459](https://github.com/ReVanced/revanced-patches/issues/3459)) ([7c218cd](https://github.com/ReVanced/revanced-patches/commit/7c218cd168aa72eb99bcb47d12dfa45616e8ad88))
* **SCB Easy:** Remove broken `Remove debugging detection` patch ([#3518](https://github.com/ReVanced/revanced-patches/issues/3518)) ([f4e23cb](https://github.com/ReVanced/revanced-patches/commit/f4e23cbb8a24638318d8cee20a1991c51855d9d2))
## [4.12.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.12.0...v4.12.1-dev.1) (2024-08-15)
### Bug Fixes
* **YouTube - GmsCore support:** Fix notifications not working by using the correct permissions ([19ddae2](https://github.com/ReVanced/revanced-patches/commit/19ddae2d15e513e18eb1556c468cd94bd197685b))
# [4.12.0](https://github.com/ReVanced/revanced-patches/compare/v4.11.0...v4.12.0) (2024-08-06)
### Bug Fixes
* **Google Photos - GmsCore support:** Fix by checking first if a method exists before trying to patch it ([acf38ca](https://github.com/ReVanced/revanced-patches/commit/acf38cafae5eb9896b43f3a6cbd808ac273cd081))
* **Instagram - Hide ads:** Restore compatibility with latest version by fixing fingerprint ([#3455](https://github.com/ReVanced/revanced-patches/issues/3455)) ([4505fa4](https://github.com/ReVanced/revanced-patches/commit/4505fa4138bb55c8957790239c01b8dda63d6cdd))
* **Messenger - Disable switching emoji to sticker:** Constrain to last working version `439.0.0.29.119` ([6207c31](https://github.com/ReVanced/revanced-patches/commit/6207c314c657a1188d1081b0a196a61e49cad83b))
* **SoundCloud - Enable offline sync:** Stop crashing by reversing order of patching instructions from last to first to retain indices ([63b6ced](https://github.com/ReVanced/revanced-patches/commit/63b6cede5fa5bcf377ced422da4e861996a41f0d))
* **YouTube - Bypass image region restrictions:** Move setting to `Misc` menu ([094ae59](https://github.com/ReVanced/revanced-patches/commit/094ae59fc92663fff6c5d6f5cbece41822a326f9))
* **YouTube - Client Spoof:** Restore missing high qualities by spoofing the iOS client user agent ([#3468](https://github.com/ReVanced/revanced-patches/issues/3468)) ([0e6ae5f](https://github.com/ReVanced/revanced-patches/commit/0e6ae5fee752a76604cf9b95f9a76c0cbe5f7dae))
* **YouTube - Hide keyword content:** Do not hide flyout menu ([687c9f7](https://github.com/ReVanced/revanced-patches/commit/687c9f7eb03cca5f7b3486f07f2e3453ebc77faf))
* **YouTube - SponsorBlock:** Correctly show minute timestamp when creating a new segment ([d74c366](https://github.com/ReVanced/revanced-patches/commit/d74c366dbf5f25c20fbfc5a0157c3c15dda82a16))
* **YouTube - SponsorBlock:** Improve create segment manual seek accuracy ([#3491](https://github.com/ReVanced/revanced-patches/issues/3491)) ([1544981](https://github.com/ReVanced/revanced-patches/commit/15449819ff74b636fb2fa6aacd770142c51d2e5d))
* **YouTube - Spoof client:** Fix tracking history on brand accounts ([#3480](https://github.com/ReVanced/revanced-patches/issues/3480)) ([69c1f16](https://github.com/ReVanced/revanced-patches/commit/69c1f16f7eb0d5759a44f7f7a09b1757ce8f61dd))
* **YouTube - Spoof client:** Restore livestream audio only playback with iOS spoofing ([#3504](https://github.com/ReVanced/revanced-patches/issues/3504)) ([90d3288](https://github.com/ReVanced/revanced-patches/commit/90d32880906787d82c4b9a7a1099b46dff3a0870))
### Features
* Add `Hide mock location` patch ([#3417](https://github.com/ReVanced/revanced-patches/issues/3417)) ([5f81b40](https://github.com/ReVanced/revanced-patches/commit/5f81b40e7d5567fb5689d08ccc9caeaa267c3143))
* Add `Spoof build info` patch ([e7829b4](https://github.com/ReVanced/revanced-patches/commit/e7829b41e782c9feda23b9d6acf48bae277d24d9))
* **Boost for Reddit:** Add `Disable ads` patch ([#3474](https://github.com/ReVanced/revanced-patches/issues/3474)) ([b292c20](https://github.com/ReVanced/revanced-patches/commit/b292c200bf4ea5b4f71d96690ac011e7843552f0))
* **CandyLink:** Remove non-functional `Unlock pro` patch ([7ae9f8f](https://github.com/ReVanced/revanced-patches/commit/7ae9f8fa0a349b91853e9554f18e564ca6ff887c))
* **Expense Manager:** Remove non-functional `Unlock pro` patch ([ebbcac7](https://github.com/ReVanced/revanced-patches/commit/ebbcac74fd8598daebb4be0bd7c430c41333e2d4))
* **Google News:** Add `Enable CustomTabs` and `GmsCore support` patch ([#3111](https://github.com/ReVanced/revanced-patches/issues/3111)) ([ad59096](https://github.com/ReVanced/revanced-patches/commit/ad590962275f888b335252ad5bed0f34e959d3c7))
* **Google Photos:** Add `GmsCore support` patch ([#3414](https://github.com/ReVanced/revanced-patches/issues/3414)) ([24528e0](https://github.com/ReVanced/revanced-patches/commit/24528e0a6eec17ce0a3c52f8862585933615ad28))
* **Instagram:** Remove unnecessary `Hide timeline ads` patch ([5e1d001](https://github.com/ReVanced/revanced-patches/commit/5e1d001056df68e1e2b39f1365215c91bcc9e46b))
* **SoundCloud:** Add `Enable offline sync` patch ([#3407](https://github.com/ReVanced/revanced-patches/issues/3407)) ([4de86c6](https://github.com/ReVanced/revanced-patches/commit/4de86c6407376bcd3cc0513a2f0707410b8d7ccd))
* **SwissID:** Add `Remove Google Play Integrity Integrity check` patch ([#3478](https://github.com/ReVanced/revanced-patches/issues/3478)) ([60492ae](https://github.com/ReVanced/revanced-patches/commit/60492aea7863e07d8bf1af9380ae9295ca161f3c))
* **YouTube - Description components:** Add `Hide 'Key concepts' section` option ([#3495](https://github.com/ReVanced/revanced-patches/issues/3495)) ([d75b645](https://github.com/ReVanced/revanced-patches/commit/d75b64595a7ac26faca4c0ae21923b22f6783975))
* **YouTube:** Add `Bypass image region restrictions` patch ([#3442](https://github.com/ReVanced/revanced-patches/issues/3442)) ([765fab2](https://github.com/ReVanced/revanced-patches/commit/765fab2af2769349446cc0f2109343ef3bd8c621))
# [4.12.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.16...v4.12.0-dev.17) (2024-08-06)
### Bug Fixes
* **Google Photos - GmsCore support:** Fix by checking first if a method exists before trying to patch it ([acf38ca](https://github.com/ReVanced/revanced-patches/commit/acf38cafae5eb9896b43f3a6cbd808ac273cd081))
* **Messenger - Disable switching emoji to sticker:** Constrain to last working version `439.0.0.29.119` ([6207c31](https://github.com/ReVanced/revanced-patches/commit/6207c314c657a1188d1081b0a196a61e49cad83b))
### Features
* **CandyLink:** Remove non-functional `Unlock pro` patch ([7ae9f8f](https://github.com/ReVanced/revanced-patches/commit/7ae9f8fa0a349b91853e9554f18e564ca6ff887c))
* **Expense Manager:** Remove non-functional `Unlock pro` patch ([ebbcac7](https://github.com/ReVanced/revanced-patches/commit/ebbcac74fd8598daebb4be0bd7c430c41333e2d4))
* **Instagram:** Remove unnecessary `Hide timeline ads` patch ([5e1d001](https://github.com/ReVanced/revanced-patches/commit/5e1d001056df68e1e2b39f1365215c91bcc9e46b))
# [4.12.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.15...v4.12.0-dev.16) (2024-08-04)
### Bug Fixes
* **YouTube - Spoof client:** Restore livestream audio only playback with iOS spoofing ([#3504](https://github.com/ReVanced/revanced-patches/issues/3504)) ([90d3288](https://github.com/ReVanced/revanced-patches/commit/90d32880906787d82c4b9a7a1099b46dff3a0870))
# [4.12.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.14...v4.12.0-dev.15) (2024-08-02)
### Bug Fixes
* **YouTube - SponsorBlock:** Improve create segment manual seek accuracy ([#3491](https://github.com/ReVanced/revanced-patches/issues/3491)) ([1544981](https://github.com/ReVanced/revanced-patches/commit/15449819ff74b636fb2fa6aacd770142c51d2e5d))
# [4.12.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.13...v4.12.0-dev.14) (2024-08-01)
### Features
* **YouTube - Description components:** Add `Hide 'Key concepts' section` option ([#3495](https://github.com/ReVanced/revanced-patches/issues/3495)) ([d75b645](https://github.com/ReVanced/revanced-patches/commit/d75b64595a7ac26faca4c0ae21923b22f6783975))
# [4.12.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.12...v4.12.0-dev.13) (2024-07-31) # [4.12.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.12...v4.12.0-dev.13) (2024-07-31)

View File

@@ -16,6 +16,14 @@ public final class app/revanced/patches/all/connectivity/wifi/spoof/SpoofWifiPat
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Triple;)V public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Triple;)V
} }
public final class app/revanced/patches/all/directory/ChangeDataDirectoryLocationPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
public static final field INSTANCE Lapp/revanced/patches/all/directory/ChangeDataDirectoryLocationPatch;
public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Integer;
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V
}
public final class app/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch : app/revanced/patcher/patch/ResourcePatch { public final class app/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch; public static final field INSTANCE Lapp/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
@@ -243,6 +251,18 @@ public final class app/revanced/patches/cieid/restrictions/root/BypassRootChecks
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
} }
public final class app/revanced/patches/duolingo/ad/DisableAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/duolingo/ad/DisableAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/duolingo/debug/EnableDebugMenuPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/duolingo/debug/EnableDebugMenuPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/facebook/ads/story/HideStoryAdsPatch : app/revanced/patcher/patch/BytecodePatch { public final class app/revanced/patches/facebook/ads/story/HideStoryAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/facebook/ads/story/HideStoryAdsPatch; public static final field INSTANCE Lapp/revanced/patches/facebook/ads/story/HideStoryAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -279,6 +299,16 @@ public final class app/revanced/patches/googlenews/misc/integrations/Integration
public static final field INSTANCE Lapp/revanced/patches/googlenews/misc/integrations/IntegrationsPatch; public static final field INSTANCE Lapp/revanced/patches/googlenews/misc/integrations/IntegrationsPatch;
} }
public final class app/revanced/patches/googlephotos/features/SpoofFeaturesPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/googlephotos/features/SpoofFeaturesPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/googlephotos/features/fingerprints/InitializeFeaturesEnumFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint {
public static final field INSTANCE Lapp/revanced/patches/googlephotos/features/fingerprints/InitializeFeaturesEnumFingerprint;
}
public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch : app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch { public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch : app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch {
public static final field INSTANCE Lapp/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch; public static final field INSTANCE Lapp/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch;
} }
@@ -423,6 +453,12 @@ public final class app/revanced/patches/music/ad/video/HideMusicVideoAds : app/r
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
} }
public final class app/revanced/patches/music/ad/video/HideVideoAds : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/ad/video/HideVideoAds;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/music/ad/video/MusicVideoAdsPatch : app/revanced/patcher/patch/BytecodePatch { public final class app/revanced/patches/music/ad/video/MusicVideoAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/music/ad/video/MusicVideoAdsPatch; public static final field INSTANCE Lapp/revanced/patches/music/ad/video/MusicVideoAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -792,6 +828,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/s
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch; public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch;
} }
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/user/UseUserEndpointPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/user/UseUserEndpointPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch { public final class app/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch; public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch;
} }
@@ -826,6 +868,12 @@ public final class app/revanced/patches/serviceportalbund/detection/root/RootDet
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
} }
public abstract class app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch : app/revanced/patcher/patch/BytecodePatch {
public fun <init> (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Ljava/util/Set;Lapp/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch;)V
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch : app/revanced/patcher/patch/BytecodePatch { public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch; public static final field INSTANCE Lapp/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1834,6 +1882,10 @@ public final class app/revanced/patches/youtube/misc/backgroundplayback/Backgrou
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
} }
public final class app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch : app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/check/CheckEnvironmentPatch;
}
public final class app/revanced/patches/youtube/misc/debugging/DebuggingPatch : app/revanced/patcher/patch/ResourcePatch { public final class app/revanced/patches/youtube/misc/debugging/DebuggingPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/debugging/DebuggingPatch; public static final field INSTANCE Lapp/revanced/patches/youtube/misc/debugging/DebuggingPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
@@ -1864,6 +1916,12 @@ public final class app/revanced/patches/youtube/misc/fix/playback/SpoofSignature
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
} }
public final class app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch { public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch; public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch;
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object; public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
@@ -2104,6 +2162,7 @@ public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPat
} }
public final class app/revanced/util/BytecodeUtilsKt { public final class app/revanced/util/BytecodeUtilsKt {
public static final fun alsoResolve (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
public static final fun containsWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z public static final fun containsWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z
public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List; public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List;

View File

@@ -31,6 +31,8 @@ dependencies {
implementation(libs.guava) implementation(libs.guava)
// Used in JsonGenerator. // Used in JsonGenerator.
implementation(libs.gson) implementation(libs.gson)
// Android API stubs defined here.
compileOnly(project(":stub"))
} }
kotlin { kotlin {

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true org.gradle.parallel = true
org.gradle.caching = true org.gradle.caching = true
kotlin.code.style = official kotlin.code.style = official
version = 4.12.0-dev.13 version = 4.14.2-dev.1

File diff suppressed because one or more lines are too long

View File

@@ -5,3 +5,5 @@ buildCache {
isEnabled = "CI" !in System.getenv() isEnabled = "CI" !in System.getenv()
} }
} }
include(":stub")

View File

@@ -0,0 +1,73 @@
package app.revanced.patches.all.directory
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.BaseTransformInstructionsPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
@Patch(
name = "Change data directory location",
description = "Changes the data directory in the application from " +
"the app internal storage directory to /sdcard/android/data accessible by root-less devices." +
"Using this patch can cause unexpected issues with some apps.",
use = false,
)
@Suppress("unused")
object ChangeDataDirectoryLocationPatch : BaseTransformInstructionsPatch<Int>() {
override fun filterMap(
classDef: ClassDef,
method: Method,
instruction: Instruction,
instructionIndex: Int,
): Int? {
val reference = instruction.getReference<MethodReference>() ?: return null
if (!MethodUtil.methodSignaturesMatch(reference, MethodCall.GetDir.reference)) {
return null
}
return instructionIndex
}
override fun transform(
mutableMethod: MutableMethod,
entry: Int,
) = transformMethodCall(entry, mutableMethod)
private fun transformMethodCall(
instructionIndex: Int,
mutableMethod: MutableMethod,
) {
val getDirInstruction = mutableMethod.getInstruction<Instruction35c>(instructionIndex)
val contextRegister = getDirInstruction.registerC
val dataRegister = getDirInstruction.registerD
mutableMethod.replaceInstruction(
instructionIndex,
"invoke-virtual { v$contextRegister, v$dataRegister }, " +
"Landroid/content/Context;->getExternalFilesDir(Ljava/lang/String;)Ljava/io/File;",
)
}
private enum class MethodCall(
val reference: MethodReference,
) {
GetDir(
ImmutableMethodReference(
"Landroid/content/Context;",
"getDir",
listOf("Ljava/lang/String;", "I"),
"Ljava/io/File;",
),
),
}
}

View File

@@ -83,8 +83,9 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
"eu-rES" to "eu", "eu-rES" to "eu",
"fa-rIR" to "fa", "fa-rIR" to "fa",
"fi-rFI" to "fi", "fi-rFI" to "fi",
"tl-rPH" to "tl", "fil-rPH" to "tl",
"fr-rFR" to "fr", "fr-rFR" to "fr",
"ga-rIE" to "ga",
"gl-rES" to "gl", "gl-rES" to "gl",
"gu-rIN" to "gu", "gu-rIN" to "gu",
"hi-rIN" to "hi", "hi-rIN" to "hi",
@@ -125,6 +126,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
"sk-rSK" to "sk", "sk-rSK" to "sk",
"sl-rSI" to "sl", "sl-rSI" to "sl",
"sq-rAL" to "sq", "sq-rAL" to "sq",
"sr-rCS" to "b+sr+Latn",
"sr-rSP" to "sr", "sr-rSP" to "sr",
"sv-rSE" to "sv", "sv-rSE" to "sv",
"sw-rKE" to "sw", "sw-rKE" to "sw",
@@ -138,7 +140,6 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
"uz-rUZ" to "uz", "uz-rUZ" to "uz",
"vi-rVN" to "vi", "vi-rVN" to "vi",
"zh-rCN" to "zh-rCN", "zh-rCN" to "zh-rCN",
"zh-rHK" to "zh-rHK",
"zh-rTW" to "zh-rTW", "zh-rTW" to "zh-rTW",
"zu-rZA" to "zu", "zu-rZA" to "zu",
) )

View File

@@ -1,20 +1,23 @@
package app.revanced.patches.candylinkvpn package app.revanced.patches.candylinkvpn
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.candylinkvpn.fingerprints.IsPremiumPurchasedFingerprint import app.revanced.patches.candylinkvpn.fingerprints.IsPremiumPurchasedFingerprint
import app.revanced.util.exception
@Patch( @Patch(
name = "Unlock pro", compatiblePackages = [CompatiblePackage("com.candylink.openvpn")],
compatiblePackages = [CompatiblePackage("com.candylink.openvpn")] )
@Deprecated(
"This patch does not work anymore and will be removed in the future, " +
"because the servers now check the purchase status.",
) )
@Suppress("unused") @Suppress("unused")
object UnlockProPatch : BytecodePatch( object UnlockProPatch : BytecodePatch(
setOf(IsPremiumPurchasedFingerprint) setOf(IsPremiumPurchasedFingerprint),
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
IsPremiumPurchasedFingerprint.result?.mutableMethod?.addInstructions( IsPremiumPurchasedFingerprint.result?.mutableMethod?.addInstructions(
@@ -22,7 +25,7 @@ object UnlockProPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""" """,
) ?: throw IsPremiumPurchasedFingerprint.exception ) ?: throw IsPremiumPurchasedFingerprint.exception
} }
} }

View File

@@ -0,0 +1,41 @@
package app.revanced.patches.duolingo.ad
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.duolingo.ad.fingerprints.InitializeMonetizationDebugSettingsFingerprint
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Disable ads",
compatiblePackages = [CompatiblePackage("com.duolingo")]
)
@Suppress("unused")
object DisableAdsPatch : BytecodePatch(
setOf(InitializeMonetizationDebugSettingsFingerprint)
) {
override fun execute(context: BytecodeContext) {
// Couple approaches to remove ads exist:
//
// MonetizationDebugSettings has a boolean value for "disableAds".
// OnboardingState has a getter to check if the user has any "adFreeSessions".
// SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS".
//
// MonetizationDebugSettings seems to be the most general setting to work fine.
InitializeMonetizationDebugSettingsFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex,
"const/4 v$register, 0x1"
)
}
}
}
}

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.duolingo.ad.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object InitializeMonetizationDebugSettingsFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf(
"Z", // disableAds
"Z", // useDebugBilling
"Z", // showManageSubscriptions
"Z", // alwaysShowSuperAds
"Lcom/duolingo/debug/FamilyQuestOverride;",
),
opcodes = listOf(
Opcode.IPUT_BOOLEAN
)
)

View File

@@ -0,0 +1,35 @@
package app.revanced.patches.duolingo.debug
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.duolingo.debug.fingerprints.InitializeBuildConfigProviderFingerprint
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Patch(
name = "Enable debug menu",
compatiblePackages = [CompatiblePackage("com.duolingo", ["5.158.4"])],
use = false
)
@Suppress("unused")
object EnableDebugMenuPatch : BytecodePatch(
setOf(InitializeBuildConfigProviderFingerprint)
) {
override fun execute(context: BytecodeContext) {
InitializeBuildConfigProviderFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex,
"const/4 v$register, 0x1"
)
}
}
}
}

View File

@@ -0,0 +1,25 @@
package app.revanced.patches.duolingo.debug.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* The `BuildConfigProvider` class has two booleans:
*
* - `isChina`: (usually) compares "play" with "china"...except for builds in China
* - `isDebug`: compares "release" with "debug" <-- we want to force this to `true`
*/
internal object InitializeBuildConfigProviderFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf(
"debug",
"release",
"china",
),
opcodes = listOf(
Opcode.IPUT_BOOLEAN
)
)

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.googlephotos.features
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.build.BaseSpoofBuildInfoPatch
@Patch(description = "Spoof build info to Google Pixel XL.")
internal class SpoofBuildInfoPatch : BaseSpoofBuildInfoPatch() {
override val brand = "google"
override val manufacturer = "Google"
override val device = "marlin"
override val product = "marlin"
override val model = "Pixel XL"
override val fingerprint = "google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys"
}

View File

@@ -0,0 +1,87 @@
package app.revanced.patches.googlephotos.features
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringArrayPatchOption
import app.revanced.patches.googlephotos.features.fingerprints.InitializeFeaturesEnumFingerprint
import app.revanced.util.getReference
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Patch(
name = "Spoof features",
description = "Spoofs the device to enable Google Pixel exclusive features, including unlimited storage.",
dependencies = [SpoofBuildInfoPatch::class],
compatiblePackages = [CompatiblePackage("com.google.android.apps.photos")],
)
@Suppress("unused")
object SpoofFeaturesPatch : BytecodePatch(setOf(InitializeFeaturesEnumFingerprint)) {
private val featuresToEnable by stringArrayPatchOption(
"featuresToEnable",
arrayOf(
"com.google.android.apps.photos.NEXUS_PRELOAD",
"com.google.android.apps.photos.nexus_preload",
),
title = "Features to enable",
description = "Google Pixel exclusive features to enable. Features up to Pixel XL enable the unlimited storage feature.",
required = true,
)
private val featuresToDisable by stringArrayPatchOption(
"featuresToDisable",
arrayOf(
"com.google.android.apps.photos.PIXEL_2017_PRELOAD",
"com.google.android.apps.photos.PIXEL_2018_PRELOAD",
"com.google.android.apps.photos.PIXEL_2019_MIDYEAR_PRELOAD",
"com.google.android.apps.photos.PIXEL_2019_PRELOAD",
"com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE",
"com.google.android.feature.PIXEL_2020_EXPERIENCE",
"com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE",
"com.google.android.feature.PIXEL_2021_EXPERIENCE",
"com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE",
"com.google.android.feature.PIXEL_2022_EXPERIENCE",
"com.google.android.feature.PIXEL_2023_MIDYEAR_EXPERIENCE",
"com.google.android.feature.PIXEL_2023_EXPERIENCE",
"com.google.android.feature.PIXEL_2024_MIDYEAR_EXPERIENCE",
"com.google.android.feature.PIXEL_2024_EXPERIENCE",
"com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE",
),
title = "Features to disable",
description = "Google Pixel exclusive features to disable." +
"Features after Pixel XL may have to be disabled for unlimited storage depending on the device.",
required = true,
)
override fun execute(context: BytecodeContext) {
val featuresToEnable = featuresToEnable!!.toSet()
val featuresToDisable = featuresToDisable!!.toSet()
InitializeFeaturesEnumFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply {
getInstructions().filter { it.opcode == Opcode.CONST_STRING }.forEach {
val feature = it.getReference<StringReference>()!!.string
val spoofedFeature = when (feature) {
in featuresToEnable -> "android.hardware.wifi"
in featuresToDisable -> "dummy"
else -> return@forEach
}
val constStringIndex = it.location.index
val constStringRegister = (it as OneRegisterInstruction).registerA
replaceInstruction(
constStringIndex,
"const-string v$constStringRegister, \"$spoofedFeature\"",
)
}
}
}
}
}

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.googlephotos.features.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
object InitializeFeaturesEnumFingerprint : MethodFingerprint(
strings = listOf("com.google.android.apps.photos.NEXUS_PRELOAD"),
)

View File

@@ -14,9 +14,9 @@ import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch( @Patch(
name = "Hide timeline ads",
compatiblePackages = [CompatiblePackage("com.instagram.android")], compatiblePackages = [CompatiblePackage("com.instagram.android")],
) )
@Deprecated("This patch is not needed anymore.", replaceWith = ReplaceWith("HideAdsPatch"))
@Suppress("unused") @Suppress("unused")
object HideTimelineAdsPatch : BytecodePatch( object HideTimelineAdsPatch : BytecodePatch(
setOf( setOf(

View File

@@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch( @Patch(
name = "Disable switching emoji to sticker", name = "Disable switching emoji to sticker",
description = "Disables switching from emoji to sticker search mode in message input field.", description = "Disables switching from emoji to sticker search mode in message input field.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")], compatiblePackages = [CompatiblePackage("com.facebook.orca", ["439.0.0.29.119"])],
) )
@Suppress("unused") @Suppress("unused")
object DisableSwitchingEmojiToStickerPatch : BytecodePatch( object DisableSwitchingEmojiToStickerPatch : BytecodePatch(

View File

@@ -8,12 +8,12 @@ import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint
@Patch( @Patch(
name = "Unlock pro", compatiblePackages = [CompatiblePackage("com.ithebk.expensemanager")],
compatiblePackages = [CompatiblePackage("com.ithebk.expensemanager")]
) )
@Deprecated("This patch is not functional anymore and will be removed in the future.")
@Suppress("unused") @Suppress("unused")
object UnlockProPatch : BytecodePatch( object UnlockProPatch : BytecodePatch(
setOf(UnlockProFingerprint) setOf(UnlockProFingerprint),
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
UnlockProFingerprint.result!!.mutableMethod.addInstructions( UnlockProFingerprint.result!!.mutableMethod.addInstructions(
@@ -21,7 +21,7 @@ object UnlockProPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""" """,
) )
} }
} }

View File

@@ -6,40 +6,40 @@ import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsParentFingerprint import app.revanced.patches.music.ad.video.fingerprints.ShowVideoAdsParentFingerprint
import app.revanced.util.exception import app.revanced.util.exception
@Patch( @Patch(
name = "Hide music video ads", name = "Hide video ads",
description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
], ],
) )
@Suppress("unused") @Suppress("unused")
object HideMusicVideoAds : BytecodePatch( object HideVideoAds : BytecodePatch(
setOf(ShowMusicVideoAdsParentFingerprint), setOf(ShowVideoAdsParentFingerprint),
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsParentFingerprint.result?.let { ShowVideoAdsParentFingerprint.result?.let {
val showMusicVideoAdsMethod = context val showVideoAdsMethod = context
.toMethodWalker(it.mutableMethod) .toMethodWalker(it.mutableMethod)
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod .nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod
showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0") showVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
} ?: throw ShowMusicVideoAdsParentFingerprint.exception } ?: throw ShowVideoAdsParentFingerprint.exception
} }
} }
@Deprecated("This patch class has been renamed to HideMusicVideoAds.") @Deprecated("This patch class has been renamed to HideVideoAds.")
object HideMusicVideoAds : BytecodePatch(
dependencies = setOf(HideVideoAds::class)
) {
override fun execute(context: BytecodeContext) {
}
}
@Deprecated("This patch class has been renamed to HideVideoAds.")
object MusicVideoAdsPatch : BytecodePatch( object MusicVideoAdsPatch : BytecodePatch(
dependencies = setOf(HideMusicVideoAds::class), dependencies = setOf(HideMusicVideoAds::class),
) { ) {

View File

@@ -3,7 +3,7 @@ package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint( internal object ShowVideoAdsParentFingerprint : MethodFingerprint(
opcodes = listOf( opcodes = listOf(
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,

View File

@@ -12,16 +12,7 @@ import com.android.tools.smali.dexlib2.Opcode
@Patch( @Patch(
description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.", description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
] ]
) )
@Deprecated("This patch is no longer needed as the feature is now enabled by default.") @Deprecated("This patch is no longer needed as the feature is now enabled by default.")

View File

@@ -12,16 +12,7 @@ import app.revanced.util.exception
name = "Enable exclusive audio playback", name = "Enable exclusive audio playback",
description = "Enables the option to play audio without video.", description = "Enables the option to play audio without video.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
] ]
) )
@Suppress("unused") @Suppress("unused")

View File

@@ -14,16 +14,7 @@ import app.revanced.patches.music.interaction.permanentrepeat.fingerprints.Repea
name = "Permanent repeat", name = "Permanent repeat",
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.", description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
], ],
use = false use = false
) )

View File

@@ -14,16 +14,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
name = "Hide category bar", name = "Hide category bar",
description = "Hides the category bar at the top of the homepage.", description = "Hides the category bar at the top of the homepage.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
], ],
use = false, use = false,
) )

View File

@@ -17,16 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
name = "Hide 'Get Music Premium' label", name = "Hide 'Get Music Premium' label",
description = "Hides the \"Get Music Premium\" label from the account menu and settings.", description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
] ]
) )
@Suppress("unused") @Suppress("unused")

View File

@@ -23,16 +23,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
name = "Remove upgrade button", name = "Remove upgrade button",
description = "Removes the upgrade tab from the pivot bar.", description = "Removes the upgrade tab from the pivot bar.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
] ]
) )
@Suppress("unused") @Suppress("unused")

View File

@@ -13,16 +13,7 @@ import app.revanced.patches.music.misc.androidauto.fingerprints.CheckCertificate
name = "Bypass certificate checks", name = "Bypass certificate checks",
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.", description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
] ]
) )
@Suppress("unused") @Suppress("unused")

View File

@@ -14,16 +14,7 @@ import app.revanced.util.resultOrThrow
name = "Remove background playback restrictions", name = "Remove background playback restrictions",
description = "Removes restrictions on background playback, including playing kids videos in the background.", description = "Removes restrictions on background playback, including playing kids videos in the background.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music")
"com.google.android.apps.youtube.music",
[
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
]
)
] ]
) )
@Suppress("unused") @Suppress("unused")

View File

@@ -23,16 +23,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
integrationsPatchDependency = IntegrationsPatch::class, integrationsPatchDependency = IntegrationsPatch::class,
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
compatiblePackages = setOf( compatiblePackages = setOf(
CompatiblePackage( CompatiblePackage("com.google.android.apps.youtube.music"),
"com.google.android.apps.youtube.music",
setOf(
"6.45.54",
"6.51.53",
"7.01.53",
"7.02.52",
"7.03.52",
),
),
), ),
fingerprints = setOf( fingerprints = setOf(
CastDynamiteModuleV2Fingerprint, CastDynamiteModuleV2Fingerprint,

View File

@@ -1,28 +1,25 @@
package app.revanced.patches.pixiv.ads package app.revanced.patches.pixiv.ads
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.pixiv.ads.fingerprints.IsNotPremiumFingerprint import app.revanced.patches.pixiv.ads.fingerprints.ShouldShowAdsFingerprint
import app.revanced.util.exception
@Patch( @Patch(
name = "Hide ads", name = "Hide ads",
compatiblePackages = [CompatiblePackage("jp.pxv.android")] compatiblePackages = [CompatiblePackage("jp.pxv.android")],
) )
@Suppress("unused") @Suppress("unused")
object HideAdsPatch : BytecodePatch(setOf(IsNotPremiumFingerprint)) { object HideAdsPatch : BytecodePatch(setOf(ShouldShowAdsFingerprint)) {
// Always return false in the "isNotPremium" method which normally returns !this.accountManager.isPremium.
// However, this is not the method that controls the user's premium status.
// Instead, this method is used to determine whether ads should be shown.
override fun execute(context: BytecodeContext) = override fun execute(context: BytecodeContext) =
IsNotPremiumFingerprint.result?.mutableClass?.virtualMethods?.first()?.addInstructions( ShouldShowAdsFingerprint.result?.mutableMethod?.addInstructions(
0, 0,
""" """
const/4 v0, 0x0 const/4 v0, 0x0
return v0 return v0
""" """,
) ?: throw IsNotPremiumFingerprint.exception ) ?: throw ShouldShowAdsFingerprint.exception
} }

View File

@@ -1,21 +0,0 @@
package app.revanced.patches.pixiv.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object IsNotPremiumFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L"),
strings = listOf("pixivAccountManager"),
customFingerprint = custom@{ _, classDef ->
// The "isNotPremium" method is the only method in the class.
if (classDef.virtualMethods.count() != 1) return@custom false
classDef.virtualMethods.first().let { isNotPremiumMethod ->
isNotPremiumMethod.parameterTypes.size == 0 && isNotPremiumMethod.returnType == "Z"
}
}
)

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.pixiv.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object ShouldShowAdsFingerprint : MethodFingerprint(
"Z",
AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { methodDef, classDef ->
classDef.type.endsWith("AdUtils;") && methodDef.name == "shouldShowAds"
}
)

View File

@@ -0,0 +1,61 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.*
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.OAuthFriendRequestFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.OAuthSubredditInfoRequestHelperFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.OAuthUnfriendRequestFingerprint
import app.revanced.util.getReference
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Patch(
name = "Use /user/ endpoint",
description = "Replaces the deprecated endpoint for viewing user profiles /u with /user, that used to fix a bug.",
compatiblePackages = [
CompatiblePackage("com.laurencedawson.reddit_sync"),
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
CompatiblePackage("com.laurencedawson.reddit_sync.dev"),
],
use = false,
)
@Suppress("unused")
object UseUserEndpointPatch : BytecodePatch(
fingerprints = setOf(
OAuthFriendRequestFingerprint,
OAuthSubredditInfoRequestConstructorFingerprint,
OAuthSubredditInfoRequestHelperFingerprint,
OAuthUnfriendRequestFingerprint,
OAuthUserIdRequestFingerprint,
OAuthUserInfoRequestFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
arrayOf(
OAuthFriendRequestFingerprint,
OAuthSubredditInfoRequestConstructorFingerprint,
OAuthSubredditInfoRequestHelperFingerprint,
OAuthUnfriendRequestFingerprint,
OAuthUserIdRequestFingerprint,
OAuthUserInfoRequestFingerprint,
).map(MethodFingerprint::resultOrThrow).map {
it.scanResult.stringsScanResult!!.matches.first().index to it.mutableMethod
}.forEach { (userPathStringIndex, method) ->
val userPathStringInstruction = method.getInstruction<OneRegisterInstruction>(userPathStringIndex)
val userPathStringRegister = userPathStringInstruction.registerA
val fixedUserPathString = userPathStringInstruction.getReference<StringReference>()!!.string.replace("u/", "user/")
method.replaceInstruction(
userPathStringIndex,
"const-string v$userPathStringRegister, \"${fixedUserPathString}\"",
)
}
}
}

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal abstract class BaseUserEndpointFingerprint(source: String, accessFlags: Int? = null) :
MethodFingerprint(
accessFlags = accessFlags,
strings = listOf("u/"),
customFingerprint = { _, classDef -> classDef.sourceFile == source },
)

View File

@@ -0,0 +1,3 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
internal object OAuthFriendRequestFingerprint : BaseUserEndpointFingerprint("OAuthFriendRequest.java")

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
import app.revanced.patcher.extensions.or
import com.android.tools.smali.dexlib2.AccessFlags
internal object OAuthSubredditInfoRequestConstructorFingerprint :
BaseUserEndpointFingerprint(
"OAuthSubredditInfoRequest.java",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
)

View File

@@ -0,0 +1,10 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
import app.revanced.patcher.extensions.or
import com.android.tools.smali.dexlib2.AccessFlags
internal object OAuthSubredditInfoRequestHelperFingerprint :
BaseUserEndpointFingerprint(
"OAuthSubredditInfoRequest.java",
AccessFlags.PRIVATE or AccessFlags.STATIC,
)

View File

@@ -0,0 +1,3 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
internal object OAuthUnfriendRequestFingerprint : BaseUserEndpointFingerprint("OAuthUnfriendRequest.java")

View File

@@ -0,0 +1,3 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
internal object OAuthUserIdRequestFingerprint : BaseUserEndpointFingerprint("OAuthUserIdRequest.java")

View File

@@ -0,0 +1,3 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
internal object OAuthUserInfoRequestFingerprint : BaseUserEndpointFingerprint("OAuthUserInfoRequest.java")

View File

@@ -10,11 +10,13 @@ import app.revanced.patches.scbeasy.detection.debugging.fingerprints.DebuggingDe
@Patch( @Patch(
use = false, use = false,
name = "Remove debugging detection",
description = "Removes the USB and wireless debugging checks.", description = "Removes the USB and wireless debugging checks.",
compatiblePackages = [CompatiblePackage("com.scb.phone")] compatiblePackages = [CompatiblePackage("com.scb.phone")]
) )
@Suppress("unused") @Suppress("unused")
@Deprecated("This patch no longer work and will be removed in the future " +
"due to the complexity of the application.\n" +
"See https://github.com/ReVanced/revanced-patches/issues/3517 for more details.")
object RemoveDebuggingDetectionPatch : BytecodePatch( object RemoveDebuggingDetectionPatch : BytecodePatch(
setOf(DebuggingDetectionFingerprint) setOf(DebuggingDetectionFingerprint)
) { ) {

View File

@@ -0,0 +1,114 @@
package app.revanced.patches.shared.misc.checks
import android.os.Build.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableLongEncodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableStringEncodedValue
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.checks.fingerprints.PatchInfoBuildFingerprint
import app.revanced.patches.shared.misc.checks.fingerprints.PatchInfoFingerprint
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.immutable.value.ImmutableLongEncodedValue
import com.android.tools.smali.dexlib2.immutable.value.ImmutableStringEncodedValue
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
abstract class BaseCheckEnvironmentPatch(
private val mainActivityOnCreateFingerprint: MethodFingerprint,
compatiblePackages: Set<CompatiblePackage>,
integrationsPatch: BaseIntegrationsPatch,
) : BytecodePatch(
description = "Checks, if the application was patched by, otherwise warns the user.",
compatiblePackages = compatiblePackages,
dependencies = setOf(
AddResourcesPatch::class,
integrationsPatch::class,
),
fingerprints = setOf(
PatchInfoFingerprint,
PatchInfoBuildFingerprint,
mainActivityOnCreateFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(BaseCheckEnvironmentPatch::class)
setPatchInfo()
invokeCheck()
}
private fun setPatchInfo() {
PatchInfoFingerprint.setClassFields(
"PATCH_TIME" to System.currentTimeMillis().encoded,
)
fun setBuildInfo() {
PatchInfoBuildFingerprint.setClassFields(
"PATCH_BOARD" to BOARD.encodedAndHashed,
"PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed,
"PATCH_BRAND" to BRAND.encodedAndHashed,
"PATCH_CPU_ABI" to CPU_ABI.encodedAndHashed,
"PATCH_CPU_ABI2" to CPU_ABI2.encodedAndHashed,
"PATCH_DEVICE" to DEVICE.encodedAndHashed,
"PATCH_DISPLAY" to DISPLAY.encodedAndHashed,
"PATCH_FINGERPRINT" to FINGERPRINT.encodedAndHashed,
"PATCH_HARDWARE" to HARDWARE.encodedAndHashed,
"PATCH_HOST" to HOST.encodedAndHashed,
"PATCH_ID" to ID.encodedAndHashed,
"PATCH_MANUFACTURER" to MANUFACTURER.encodedAndHashed,
"PATCH_MODEL" to MODEL.encodedAndHashed,
"PATCH_PRODUCT" to PRODUCT.encodedAndHashed,
"PATCH_RADIO" to RADIO.encodedAndHashed,
"PATCH_TAGS" to TAGS.encodedAndHashed,
"PATCH_TYPE" to TYPE.encodedAndHashed,
"PATCH_USER" to USER.encodedAndHashed,
)
}
try {
Class.forName("android.os.Build")
// This only works on Android,
// because it uses Android APIs.
setBuildInfo()
} catch (_: ClassNotFoundException) { }
}
private fun invokeCheck() = mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
0,
"invoke-static/range { p0 .. p0 },$INTEGRATIONS_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
) ?: throw mainActivityOnCreateFingerprint.exception
private companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/shared/checks/CheckEnvironmentPatch;"
@OptIn(ExperimentalEncodingApi::class)
private val String.encodedAndHashed
get() = MutableStringEncodedValue(
ImmutableStringEncodedValue(
Base64.encode(
MessageDigest.getInstance("SHA-1")
.digest(this.toByteArray(StandardCharsets.UTF_8)),
),
),
)
private val Long.encoded get() = MutableLongEncodedValue(ImmutableLongEncodedValue(this))
private fun <T : MutableEncodedValue> MethodFingerprint.setClassFields(vararg fieldNameValues: Pair<String, T>) {
val fieldNameValueMap = mapOf(*fieldNameValues)
resultOrThrow().mutableClass.fields.forEach { field ->
field.initialValue = fieldNameValueMap[field.name] ?: return@forEach
}
}
}
}

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.shared.misc.checks.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object PatchInfoBuildFingerprint : MethodFingerprint(
customFingerprint = { _, classDef -> classDef.type == "Lapp/revanced/integrations/shared/checks/PatchInfo\$Build;" },
)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.shared.misc.checks.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object PatchInfoFingerprint : MethodFingerprint(
customFingerprint = { _, classDef ->
classDef.type == "Lapp/revanced/integrations/shared/checks/PatchInfo;"
},
)

View File

@@ -18,11 +18,13 @@ import app.revanced.patches.shared.misc.gms.fingerprints.GooglePlayUtilityFinger
import app.revanced.patches.shared.misc.gms.fingerprints.ServiceCheckFingerprint import app.revanced.patches.shared.misc.gms.fingerprints.ServiceCheckFingerprint
import app.revanced.util.exception import app.revanced.util.exception
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.returnEarly import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
@@ -100,17 +102,33 @@ abstract class BaseGmsCoreSupportPatch(
primeMethodFingerprint?.let { transformPrimeMethod(packageName) } primeMethodFingerprint?.let { transformPrimeMethod(packageName) }
// Return these methods early to prevent the app from crashing. // Return these methods early to prevent the app from crashing.
(earlyReturnFingerprints + ServiceCheckFingerprint + CastDynamiteModuleFingerprint).returnEarly() earlyReturnFingerprints.returnEarly()
ServiceCheckFingerprint.returnEarly()
// Not all apps have CastDynamiteModule, so we need to check if it's present.
if (CastDynamiteModuleFingerprint.result != null) {
CastDynamiteModuleFingerprint.returnEarly()
}
// Google Play Utility is not present in all apps, so we need to check if it's present.
if (GooglePlayUtilityFingerprint.result != null) { if (GooglePlayUtilityFingerprint.result != null) {
GooglePlayUtilityFingerprint.returnEarly() GooglePlayUtilityFingerprint.returnEarly()
} }
// Verify GmsCore is installed and whitelisted for power optimizations and background usage. // Verify GmsCore is installed and whitelisted for power optimizations and background usage.
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions( mainActivityOnCreateFingerprint.result?.mutableMethod?.apply {
0, // Temporary fix for patches with an integrations patch that hook the onCreate method as well.
val setContextIndex = indexOfFirstInstruction {
val reference = getReference<MethodReference>() ?: return@indexOfFirstInstruction false
reference.toString() == "Lapp/revanced/integrations/shared/Utils;->setContext(Landroid/content/Context;)V"
}
// Add after setContext call, because this patch needs the context.
addInstructions(
if (setContextIndex < 0) 0 else setContextIndex + 1,
"invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" + "invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" +
"checkGmsCore(Landroid/app/Activity;)V", "checkGmsCore(Landroid/app/Activity;)V",
) ?: throw mainActivityOnCreateFingerprint.exception )
} ?: throw mainActivityOnCreateFingerprint.exception
// Change the vendor of GmsCore in ReVanced Integrations. // Change the vendor of GmsCore in ReVanced Integrations.
GmsCoreSupportFingerprint.result?.mutableClass?.methods GmsCoreSupportFingerprint.result?.mutableClass?.methods

View File

@@ -101,8 +101,8 @@ abstract class BaseGmsCoreSupportResourcePatch(
"android:authorities=\"$fromPackageName" to "android:authorities=\"$packageName", "android:authorities=\"$fromPackageName" to "android:authorities=\"$packageName",
"$fromPackageName.permission.C2D_MESSAGE" to "$packageName.permission.C2D_MESSAGE", "$fromPackageName.permission.C2D_MESSAGE" to "$packageName.permission.C2D_MESSAGE",
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" to "$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION", "$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" to "$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
"com.google.android.c2dm" to "$packageName.android.c2dm", "com.google.android.c2dm" to "$gmsCoreVendorGroupId.android.c2dm",
"com.google.android.libraries.photos.api.mars" to "$packageName.android.apps.photos.api.mars", "com.google.android.libraries.photos.api.mars" to "$gmsCoreVendorGroupId.android.apps.photos.api.mars",
"</queries>" to "<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>", "</queries>" to "<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
) )
@@ -110,9 +110,9 @@ abstract class BaseGmsCoreSupportResourcePatch(
transformations.entries.fold(get("AndroidManifest.xml", false).readText()) { acc, (from, to) -> transformations.entries.fold(get("AndroidManifest.xml", false).readText()) { acc, (from, to) ->
acc.replace( acc.replace(
from, from,
to to,
) )
} },
) )
} }

View File

@@ -62,7 +62,7 @@ object HideAdsPatch : BytecodePatch(
// Prevent verification of an HTTP header containing the user's current plan, which would contradict the previous patch. // Prevent verification of an HTTP header containing the user's current plan, which would contradict the previous patch.
InterceptFingerprint.resultOrThrow().let { result -> InterceptFingerprint.resultOrThrow().let { result ->
val conditionIndex = result.scanResult.patternScanResult!!.endIndex val conditionIndex = result.scanResult.patternScanResult!!.endIndex + 1
result.mutableMethod.addInstruction( result.mutableMethod.addInstruction(
conditionIndex, conditionIndex,
"return-object p1", "return-object p1",

View File

@@ -9,14 +9,13 @@ internal object InterceptFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC.value, accessFlags = AccessFlags.PUBLIC.value,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT_OBJECT
Opcode.IF_EQZ,
), ),
strings = listOf("SC-Mob-UserPlan", "Configuration"), strings = listOf("SC-Mob-UserPlan", "Configuration"),
customFingerprint = { _, classDef -> customFingerprint = { _, classDef ->
classDef.sourceFile == "ApiUserPlanInterceptor.java" classDef.sourceFile == "ApiUserPlanInterceptor.java" ||
classDef.sourceFile == "ApiUserPlanInterceptor.kt"
}, },
) )

View File

@@ -9,7 +9,7 @@ import app.revanced.patches.swissid.integritycheck.fingerprints.CheckIntegrityFi
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
@Patch( @Patch(
name = "Remove Google Play Integrity Integrity check", name = "Remove Google Play Integrity check",
description = "Removes the Google Play Integrity check. With this it's possible to use SwissID on custom ROMS." + description = "Removes the Google Play Integrity check. With this it's possible to use SwissID on custom ROMS." +
"If the device is rooted, root permissions must be hidden from the app.", "If the device is rooted, root permissions must be hidden from the app.",
compatiblePackages = [CompatiblePackage("com.swisssign.swissid.mobile")], compatiblePackages = [CompatiblePackage("com.swisssign.swissid.mobile")],

View File

@@ -23,16 +23,16 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"retains the speed configurations in between videos.", "retains the speed configurations in between videos.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]), CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"]) CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"]),
] ],
) )
@Suppress("unused") @Suppress("unused")
object PlaybackSpeedPatch : BytecodePatch( object PlaybackSpeedPatch : BytecodePatch(
setOf( setOf(
GetSpeedFingerprint, GetSpeedFingerprint,
OnRenderFirstFrameFingerprint, OnRenderFirstFrameFingerprint,
SetSpeedFingerprint SetSpeedFingerprint,
) ),
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SetSpeedFingerprint.result?.let { onVideoSwiped -> SetSpeedFingerprint.result?.let { onVideoSwiped ->
@@ -44,7 +44,7 @@ object PlaybackSpeedPatch : BytecodePatch(
addInstruction( addInstruction(
injectIndex, injectIndex,
"invoke-static { v$register }," + "invoke-static { v$register }," +
" Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->rememberPlaybackSpeed(F)V" " Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->rememberPlaybackSpeed(F)V",
) )
} ?: throw GetSpeedFingerprint.exception } ?: throw GetSpeedFingerprint.exception
@@ -64,9 +64,9 @@ object PlaybackSpeedPatch : BytecodePatch(
# Desired playback speed retrieved using getPlaybackSpeed method. # Desired playback speed retrieved using getPlaybackSpeed method.
invoke-static {}, Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->getPlaybackSpeed()F invoke-static {}, Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->getPlaybackSpeed()F
move-result-object v2 move-result v2
invoke-static { v0, v1, v2 }, ${onVideoSwiped.method} invoke-static { v0, v1, v2 }, ${onVideoSwiped.method}
""" """,
) ?: throw OnRenderFirstFrameFingerprint.exception ) ?: throw OnRenderFirstFrameFingerprint.exception
// Force enable the playback speed option for all videos. // Force enable the playback speed option for all videos.
@@ -75,7 +75,7 @@ object PlaybackSpeedPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""" """,
) ?: throw PatchException("Failed to force enable the playback speed option.") ) ?: throw PatchException("Failed to force enable the playback speed option.")
} ?: throw SetSpeedFingerprint.exception } ?: throw SetSpeedFingerprint.exception
} }

View File

@@ -25,8 +25,8 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
dependencies = [IntegrationsPatch::class], dependencies = [IntegrationsPatch::class],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]), CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"]) CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"]),
] ],
) )
object SettingsPatch : BytecodePatch( object SettingsPatch : BytecodePatch(
setOf( setOf(
@@ -34,7 +34,7 @@ object SettingsPatch : BytecodePatch(
AddSettingsEntryFingerprint, AddSettingsEntryFingerprint,
SettingsEntryFingerprint, SettingsEntryFingerprint,
SettingsEntryInfoFingerprint, SettingsEntryInfoFingerprint,
) ),
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/tiktok/settings/AdPersonalizationActivityHook;" "Lapp/revanced/integrations/tiktok/settings/AdPersonalizationActivityHook;"
@@ -70,8 +70,8 @@ object SettingsPatch : BytecodePatch(
markIndex + 2, markIndex + 2,
listOf( listOf(
getUnitManager, getUnitManager,
addEntry addEntry,
) ),
) )
addInstructions( addInstructions(
@@ -81,7 +81,8 @@ object SettingsPatch : BytecodePatch(
const-string v1, "$settingsButtonInfoClass" const-string v1, "$settingsButtonInfoClass"
invoke-static {v0, v1}, $CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR invoke-static {v0, v1}, $CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR
move-result-object v0 move-result-object v0
""" check-cast v0, ${SettingsEntryFingerprint.result!!.classDef}
""",
) )
} ?: throw AddSettingsEntryFingerprint.exception } ?: throw AddSettingsEntryFingerprint.exception
@@ -102,12 +103,10 @@ object SettingsPatch : BytecodePatch(
if-eqz v$usableRegister, :do_not_open if-eqz v$usableRegister, :do_not_open
return-void return-void
""", """,
ExternalLabel("do_not_open", getInstruction(initializeSettingsIndex)) ExternalLabel("do_not_open", getInstruction(initializeSettingsIndex)),
) )
} ?: throw AdPersonalizationActivityOnCreateFingerprint.exception } ?: throw AdPersonalizationActivityOnCreateFingerprint.exception
} }
private fun String.toClassName(): String { private fun String.toClassName(): String = substring(1, this.length - 1).replace("/", ".")
return substring(1, this.length - 1).replace("/", ".")
}
} }

View File

@@ -12,7 +12,7 @@ import app.revanced.util.exception
name = "Open links with app chooser", name = "Open links with app chooser",
description = "Instead of opening links directly, open them with an app chooser. " + description = "Instead of opening links directly, open them with an app chooser. " +
"As a result you can select a browser to open the link with.", "As a result you can select a browser to open the link with.",
compatiblePackages = [CompatiblePackage("com.twitter.android")], compatiblePackages = [CompatiblePackage("com.twitter.android", ["10.48.0-release"])],
use = false, use = false,
) )
@Suppress("unused") @Suppress("unused")

View File

@@ -97,6 +97,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_attributes_section"), SwitchPreference("revanced_hide_attributes_section"),
SwitchPreference("revanced_hide_chapters_section"), SwitchPreference("revanced_hide_chapters_section"),
SwitchPreference("revanced_hide_info_cards_section"), SwitchPreference("revanced_hide_info_cards_section"),
SwitchPreference("revanced_hide_key_concepts_section"),
SwitchPreference("revanced_hide_podcast_section"), SwitchPreference("revanced_hide_podcast_section"),
SwitchPreference("revanced_hide_transcript_section"), SwitchPreference("revanced_hide_transcript_section"),
), ),
@@ -137,8 +138,10 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_keyword_content_search"), SwitchPreference("revanced_hide_keyword_content_search"),
TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE), TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE),
NonInteractivePreference("revanced_hide_keyword_content_about"), NonInteractivePreference("revanced_hide_keyword_content_about"),
), NonInteractivePreference(key = "revanced_hide_keyword_content_about_whole_words",
), tag = "app.revanced.integrations.youtube.settings.preference.HtmlPreference")
)
)
) )
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences( SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(

View File

@@ -38,6 +38,7 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
SwitchPreference("revanced_hide_shorts_subscribe_button"), SwitchPreference("revanced_hide_shorts_subscribe_button"),
SwitchPreference("revanced_hide_shorts_paused_overlay_buttons"), SwitchPreference("revanced_hide_shorts_paused_overlay_buttons"),
SwitchPreference("revanced_hide_shorts_save_sound_button"), SwitchPreference("revanced_hide_shorts_save_sound_button"),
SwitchPreference("revanced_hide_shorts_use_this_sound_button"),
SwitchPreference("revanced_hide_shorts_shop_button"), SwitchPreference("revanced_hide_shorts_shop_button"),
SwitchPreference("revanced_hide_shorts_tagged_products"), SwitchPreference("revanced_hide_shorts_tagged_products"),
SwitchPreference("revanced_hide_shorts_search_suggestions"), SwitchPreference("revanced_hide_shorts_search_suggestions"),

View File

@@ -12,7 +12,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch( @Patch(
name = "Bypass image region restrictions", name = "Bypass image region restrictions",
description = "Adds an option to use a different host for user avatar and channel images," + description = "Adds an option to use a different host for user avatar and channel images " +
"and can fix missing images that are blocked in some countries.", "and can fix missing images that are blocked in some countries.",
dependencies = [ dependencies = [
IntegrationsPatch::class, IntegrationsPatch::class,

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.misc.check
import app.revanced.patches.shared.misc.checks.BaseCheckEnvironmentPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint
@Suppress("unused")
object CheckEnvironmentPatch :
BaseCheckEnvironmentPatch(
mainActivityOnCreateFingerprint = MainActivityOnCreateFingerprint,
integrationsPatch = IntegrationsPatch,
compatiblePackages = setOf(CompatiblePackage("com.google.android.youtube")),
)

View File

@@ -0,0 +1,69 @@
package app.revanced.patches.youtube.misc.dns
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint
import app.revanced.util.resultOrThrow
@Patch(
name = "Check watch history domain name resolution",
description = "Checks if the device DNS server is preventing user watch history from being saved.",
dependencies = [IntegrationsPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.32.39",
"18.37.36",
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.43",
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],
)
@Suppress("unused")
internal object CheckWatchHistoryDomainNameResolutionPatch : BytecodePatch(
setOf(MainActivityOnCreateFingerprint),
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/CheckWatchHistoryDomainNameResolutionPatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
MainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions(
// FIXME: Insert index must be greater than the insert index used by GmsCoreSupport,
// as both patch the same method and GmsCoreSupport check should be first,
// but the patch does not depend on GmsCoreSupport, so it should not be possible to enforce this
// unless a third patch is added that this patch and GmsCoreSupport depend on to manage
// the order of the patches.
1,
"invoke-static/range { p0 .. p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
)
}
}

View File

@@ -1,385 +1,11 @@
package app.revanced.patches.youtube.misc.fix.playback package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
@Patch( @Deprecated("This patch is obsolete.", replaceWith = ReplaceWith("SpoofVideoStreamsPatch"))
name = "Spoof client",
description = "Spoofs the client to allow video playback.",
dependencies = [
SettingsPatch::class,
AddResourcesPatch::class,
UserAgentClientSpoofPatch::class,
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.37.36",
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.43",
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],
)
object SpoofClientPatch : BytecodePatch( object SpoofClientPatch : BytecodePatch(
setOf( dependencies = setOf(SpoofVideoStreamsPatch::class),
// Client type spoof.
BuildInitPlaybackRequestFingerprint,
BuildPlayerRequestURIFingerprint,
SetPlayerRequestClientTypeFingerprint,
CreatePlayerRequestBodyFingerprint,
CreatePlayerRequestBodyWithModelFingerprint,
CreatePlayerRequestBodyWithVersionReleaseFingerprint,
// Player gesture config.
PlayerGestureConfigSyntheticFingerprint,
// Player speed menu item.
CreatePlaybackSpeedMenuItemFingerprint,
// Video qualities missing.
BuildRequestFingerprint,
// Watch history.
GetTrackingUriFingerprint,
),
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = override fun execute(context: BytecodeContext) {}
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofClientPatch;"
private const val CLIENT_INFO_CLASS_DESCRIPTOR =
"Lcom/google/protos/youtube/api/innertube/InnertubeContext\$ClientInfo;"
private const val REQUEST_CLASS_DESCRIPTOR =
"Lorg/chromium/net/ExperimentalUrlRequest;"
private const val REQUEST_BUILDER_CLASS_DESCRIPTOR =
"Lorg/chromium/net/ExperimentalUrlRequest\$Builder;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.MISC.addPreferences(
PreferenceScreen(
key = "revanced_spoof_client_screen",
sorting = PreferenceScreen.Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_spoof_client"),
SwitchPreference("revanced_spoof_client_use_ios"),
),
),
)
// region Block /initplayback requests to fall back to /get_watch requests.
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
it.mutableMethod.apply {
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
addInstructions(
moveUriStringIndex + 1,
"""
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
""",
)
}
}
// endregion
// region Block /get_watch requests to fall back to /player requests.
BuildPlayerRequestURIFingerprint.resultOrThrow().let {
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
it.mutableMethod.apply {
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
addInstructions(
invokeToStringIndex,
"""
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
move-result-object v$uriRegister
""",
)
}
}
// endregion
// region Get field references to be used below.
val (clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) =
SetPlayerRequestClientTypeFingerprint.resultOrThrow().let { result ->
// Field in the player request object that holds the client info object.
val clientInfoField = result.mutableMethod
.getInstructions().find { instruction ->
// requestMessage.clientInfo = clientInfoBuilder.build();
instruction.opcode == Opcode.IPUT_OBJECT &&
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR
}?.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoField")
// Client info object's client type field.
val clientInfoClientTypeField = result.mutableMethod
.getInstruction(result.scanResult.patternScanResult!!.endIndex)
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientTypeField")
// Client info object's client version field.
val clientInfoClientVersionField = result.mutableMethod
.getInstruction(result.scanResult.stringsScanResult!!.matches.first().index + 1)
.getReference<FieldReference>()
?: throw PatchException("Could not find clientInfoClientVersionField")
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
}
val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().let {
val getClientModelIndex =
CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction(it.method)
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
val index = it.mutableMethod.indexOfFirstInstructionOrThrow(getClientModelIndex) {
opcode == Opcode.IPUT_OBJECT
}
it.mutableMethod.getInstruction(index).getReference<FieldReference>()
?: throw PatchException("Could not find clientInfoClientModelField")
}
val clientInfoOsVersionField = CreatePlayerRequestBodyWithVersionReleaseFingerprint.resultOrThrow().let {
val getOsVersionIndex =
CreatePlayerRequestBodyWithVersionReleaseFingerprint.indexOfBuildVersionReleaseInstruction(it.method)
// The next IPUT_OBJECT instruction after getting the client os version is setting the client os version field.
val index = it.mutableMethod.indexOfFirstInstructionOrThrow(getOsVersionIndex) {
opcode == Opcode.IPUT_OBJECT
}
it.mutableMethod.getInstruction(index).getReference<FieldReference>()
?: throw PatchException("Could not find clientInfoOsVersionField")
}
// endregion
// region Spoof client type for /player requests.
CreatePlayerRequestBodyFingerprint.resultOrThrow().let { result ->
val setClientInfoMethodName = "patch_setClientInfo"
val checkCastIndex = result.scanResult.patternScanResult!!.startIndex
var clientInfoContainerClassName: String
result.mutableMethod.apply {
val checkCastInstruction = getInstruction<OneRegisterInstruction>(checkCastIndex)
val requestMessageInstanceRegister = checkCastInstruction.registerA
clientInfoContainerClassName = checkCastInstruction.getReference<TypeReference>()!!.type
addInstruction(
checkCastIndex + 1,
"invoke-static { v$requestMessageInstanceRegister }," +
" ${result.classDef.type}->$setClientInfoMethodName($clientInfoContainerClassName)V",
)
}
// Change client info to use the spoofed values.
// Do this in a helper method, to remove the need of picking out multiple free registers from the hooked code.
result.mutableClass.methods.add(
ImmutableMethod(
result.mutableClass.type,
setClientInfoMethodName,
listOf(ImmutableMethodParameter(clientInfoContainerClassName, null, "clientInfoContainer")),
"V",
AccessFlags.PRIVATE or AccessFlags.STATIC,
null,
null,
MutableMethodImplementation(3),
).toMutable().apply {
addInstructions(
"""
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isClientSpoofingEnabled()Z
move-result v0
if-eqz v0, :disabled
iget-object v0, p0, $clientInfoField
# Set client type to the spoofed value.
iget v1, v0, $clientInfoClientTypeField
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientTypeId(I)I
move-result v1
iput v1, v0, $clientInfoClientTypeField
# Set client model to the spoofed value.
iget-object v1, v0, $clientInfoClientModelField
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientModel(Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientInfoClientModelField
# Set client version to the spoofed value.
iget-object v1, v0, $clientInfoClientVersionField
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientVersion(Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientInfoClientVersionField
# Set client os version to the spoofed value.
iget-object v1, v0, $clientInfoOsVersionField
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getOsVersion(Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
iput-object v1, v0, $clientInfoOsVersionField
:disabled
return-void
""",
)
},
)
}
// endregion
// region Fix player gesture if spoofing to iOS.
PlayerGestureConfigSyntheticFingerprint.resultOrThrow().let {
val endIndex = it.scanResult.patternScanResult!!.endIndex
val downAndOutLandscapeAllowedIndex = endIndex - 3
val downAndOutPortraitAllowedIndex = endIndex - 9
arrayOf(
downAndOutLandscapeAllowedIndex,
downAndOutPortraitAllowedIndex,
).forEach { index ->
val gestureAllowedMethod = context.toMethodWalker(it.mutableMethod)
.nextMethod(index, true)
.getMethod() as MutableMethod
gestureAllowedMethod.apply {
val isAllowedIndex = getInstructions().lastIndex
val isAllowed = getInstruction<OneRegisterInstruction>(isAllowedIndex).registerA
addInstructions(
isAllowedIndex,
"""
invoke-static { v$isAllowed }, $INTEGRATIONS_CLASS_DESCRIPTOR->enablePlayerGesture(Z)Z
move-result v$isAllowed
""",
)
}
}
}
// endregion
// Fix playback speed menu item if spoofing to iOS.
CreatePlaybackSpeedMenuItemFingerprint.resultOrThrow().let {
val scanResult = it.scanResult.patternScanResult!!
if (scanResult.startIndex != 0) throw PatchException("Unexpected start index: ${scanResult.startIndex}")
it.mutableMethod.apply {
// Find the conditional check if the playback speed menu item is not created.
val shouldCreateMenuIndex =
indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ }
val shouldCreateMenuRegister = getInstruction<OneRegisterInstruction>(shouldCreateMenuIndex).registerA
addInstructions(
shouldCreateMenuIndex,
"""
invoke-static { v$shouldCreateMenuRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->forceCreatePlaybackSpeedMenu(Z)Z
move-result v$shouldCreateMenuRegister
""",
)
}
}
// endregion
// Fix watch history if spoofing to iOS.
GetTrackingUriFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val returnUrlIndex = it.scanResult.patternScanResult!!.endIndex
val urlRegister = getInstruction<OneRegisterInstruction>(returnUrlIndex).registerA
addInstructions(
returnUrlIndex,
"""
invoke-static { v$urlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;
move-result-object v$urlRegister
"""
)
}
}
// endregion
// region Fix video qualities missing, if spoofing to iOS by overriding the user agent.
BuildRequestFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply {
val buildRequestIndex = getInstructions().lastIndex - 2
val requestBuilderRegister = getInstruction<FiveRegisterInstruction>(buildRequestIndex).registerC
val newRequestBuilderIndex = result.scanResult.patternScanResult!!.endIndex
val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
// Replace "requestBuilder.build(): Request" with "overrideUserAgent(requestBuilder, url): Request".
replaceInstruction(
buildRequestIndex,
"invoke-static { v$requestBuilderRegister, v$urlRegister }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->" +
"overrideUserAgent(${REQUEST_BUILDER_CLASS_DESCRIPTOR}Ljava/lang/String;)" +
REQUEST_CLASS_DESCRIPTOR
)
}
}
// endregion
}
} }

View File

@@ -1,239 +1,12 @@
package app.revanced.patches.youtube.misc.fix.playback package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.video.information.VideoInformationPatch
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Patch( @Deprecated("This patch is obsolete.", replaceWith = ReplaceWith("SpoofVideoStreamsPatch"))
description = "Spoofs the signature to prevent playback issues.",
dependencies = [
SettingsPatch::class,
PlayerTypeHookPatch::class,
PlayerResponseMethodHookPatch::class,
VideoInformationPatch::class,
SpoofSignatureResourcePatch::class,
AddResourcesPatch::class,
],
)
@Deprecated("This patch will be removed in the future.")
object SpoofSignaturePatch : BytecodePatch( object SpoofSignaturePatch : BytecodePatch(
setOf( dependencies = setOf(SpoofVideoStreamsPatch::class),
PlayerResponseModelImplGeneralFingerprint,
PlayerResponseModelImplLiveStreamFingerprint,
PlayerResponseModelImplRecommendedLevelFingerprint,
StoryboardRendererSpecFingerprint,
StoryboardRendererDecoderSpecFingerprint,
StoryboardRendererDecoderRecommendedLevelFingerprint,
StoryboardThumbnailParentFingerprint,
SpoofSignaturePatchScrubbedPreviewLayoutFingerprint,
StatsQueryParameterFingerprint,
ParamsMapPutFingerprint,
),
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = override fun execute(context: BytecodeContext) {}
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofSignaturePatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.MISC.addPreferences(
PreferenceScreen(
key = "revanced_spoof_signature_verification_screen",
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_spoof_signature_verification_enabled"),
SwitchPreference("revanced_spoof_signature_in_feed_enabled"),
SwitchPreference("revanced_spoof_storyboard"),
),
),
)
// Hook the player parameters.
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.ProtoBufferParameter(
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
)
// Force the seekbar time and chapters to always show up.
// This is used if the storyboard spec fetch fails, for viewing paid videos,
// or if storyboard spoofing is turned off.
StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef ->
StoryboardThumbnailFingerprint.also {
it.resolve(
context,
classDef,
)
}.result?.let {
val endIndex = it.scanResult.patternScanResult!!.endIndex
// Replace existing instruction to preserve control flow label.
// The replaced return instruction always returns false
// (it is the 'no thumbnails found' control path),
// so there is no need to pass the existing return value to integrations.
it.mutableMethod.replaceInstruction(
endIndex,
"""
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarThumbnailOverrideValue()Z
""",
)
// Since this is end of the method must replace one line then add the rest.
it.mutableMethod.addInstructions(
endIndex + 1,
"""
move-result v0
return v0
""",
)
} ?: throw StoryboardThumbnailFingerprint.exception
} }
// If storyboard spoofing is turned off, then hide the empty seekbar thumbnail view.
SpoofSignaturePatchScrubbedPreviewLayoutFingerprint.result?.apply {
val endIndex = scanResult.patternScanResult!!.endIndex
mutableMethod.apply {
val imageViewFieldName = getInstruction<ReferenceInstruction>(endIndex).reference
addInstructions(
implementation!!.instructions.lastIndex,
"""
iget-object v0, p0, $imageViewFieldName # copy imageview field to a register
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->seekbarImageViewCreated(Landroid/widget/ImageView;)V
""",
)
}
} ?: throw SpoofSignaturePatchScrubbedPreviewLayoutFingerprint.exception
/**
* Hook StoryBoard renderer url
*/
arrayOf(
PlayerResponseModelImplGeneralFingerprint,
PlayerResponseModelImplLiveStreamFingerprint,
).forEach { fingerprint ->
fingerprint.result?.let {
it.mutableMethod.apply {
val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex
val getStoryBoardRegister =
getInstruction<OneRegisterInstruction>(getStoryBoardIndex).registerA
addInstructions(
getStoryBoardIndex,
"""
invoke-static { v$getStoryBoardRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$getStoryBoardRegister
""",
)
}
} ?: throw fingerprint.exception
}
// Hook recommended seekbar thumbnails quality level.
StoryboardRendererDecoderRecommendedLevelFingerprint.result?.let {
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
val originalValueRegister = it.mutableMethod
.getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
it.mutableMethod.addInstructions(
moveOriginalRecommendedValueIndex + 1,
"""
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
move-result v$originalValueRegister
""",
)
} ?: throw StoryboardRendererDecoderRecommendedLevelFingerprint.exception
// Hook the recommended precise seeking thumbnails quality level.
PlayerResponseModelImplRecommendedLevelFingerprint.result?.let {
it.mutableMethod.apply {
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
val originalValueRegister =
getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
addInstructions(
moveOriginalRecommendedValueIndex,
"""
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
move-result v$originalValueRegister
""",
)
}
} ?: throw PlayerResponseModelImplRecommendedLevelFingerprint.exception
StoryboardRendererSpecFingerprint.result?.let {
it.mutableMethod.apply {
val storyBoardUrlParams = 0
addInstructionsWithLabels(
0,
"""
if-nez p$storyBoardUrlParams, :ignore
invoke-static { p$storyBoardUrlParams }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
move-result-object p$storyBoardUrlParams
""",
ExternalLabel("ignore", getInstruction(0)),
)
}
} ?: throw StoryboardRendererSpecFingerprint.exception
// Hook the seekbar thumbnail decoder and use a NULL spec for live streams.
StoryboardRendererDecoderSpecFingerprint.result?.let {
val storyBoardUrlIndex = it.scanResult.patternScanResult!!.startIndex + 1
val storyboardUrlRegister =
it.mutableMethod.getInstruction<OneRegisterInstruction>(storyBoardUrlIndex).registerA
it.mutableMethod.addInstructions(
storyBoardUrlIndex + 1,
"""
invoke-static { v$storyboardUrlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardDecoderRendererSpec(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$storyboardUrlRegister
""",
)
} ?: throw StoryboardRendererDecoderSpecFingerprint.exception
// Fix stats not being tracked.
// Due to signature spoofing "adformat" is present in query parameters made for /stats requests,
// even though, for regular videos, it should not be.
// This breaks stats tracking.
// Replace the ad parameter with the video parameter in the query parameters.
StatsQueryParameterFingerprint.result?.let {
val putMethod = ParamsMapPutFingerprint.result?.method?.toString()
?: throw ParamsMapPutFingerprint.exception
it.mutableMethod.apply {
val adParamIndex = it.scanResult.stringsScanResult!!.matches.first().index
val videoParamIndex = adParamIndex + 3
// Replace the ad parameter with the video parameter.
replaceInstruction(adParamIndex, getInstruction(videoParamIndex))
// Call paramsMap.put instead of paramsMap.putIfNotExist
// because the key is already present in the map.
val putAdParamIndex = adParamIndex + 1
val putIfKeyNotExistsInstruction = getInstruction<FiveRegisterInstruction>(putAdParamIndex)
replaceInstruction(
putAdParamIndex,
"invoke-virtual { " +
"v${putIfKeyNotExistsInstruction.registerC}, " +
"v${putIfKeyNotExistsInstruction.registerD}, " +
"v${putIfKeyNotExistsInstruction.registerE} }, " +
putMethod,
)
}
} ?: throw StatsQueryParameterFingerprint.exception
}
}

View File

@@ -2,18 +2,8 @@ package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
@Patch(dependencies = [ResourceMappingPatch::class])
@Deprecated("This patch will be removed in the future.") @Deprecated("This patch will be removed in the future.")
object SpoofSignatureResourcePatch : ResourcePatch() { object SpoofSignatureResourcePatch : ResourcePatch() {
internal var scrubbedPreviewThumbnailResourceId: Long = -1 override fun execute(context: ResourceContext) {}
override fun execute(context: ResourceContext) {
scrubbedPreviewThumbnailResourceId = ResourceMappingPatch[
"id",
"thumbnail",
]
}
} }

View File

@@ -0,0 +1,287 @@
package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.ListPreference
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildInitPlaybackRequestFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildMediaDataSourceFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildPlayerRequestURIFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildRequestFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.CreateStreamingDataFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ProtobufClassParseByteBufferFingerprint
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
@Patch(
name = "Spoof video streams",
description = "Spoofs the client video streams to allow video playback.",
dependencies = [
SettingsPatch::class,
AddResourcesPatch::class,
UserAgentClientSpoofPatch::class,
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.37.36",
"18.38.44",
"18.43.45",
"18.44.41",
"18.45.43",
"18.48.39",
"18.49.37",
"19.01.34",
"19.02.39",
"19.03.36",
"19.04.38",
"19.05.36",
"19.06.39",
"19.07.40",
"19.08.36",
"19.09.38",
"19.10.39",
"19.11.43",
"19.12.41",
"19.13.37",
"19.14.43",
"19.15.36",
"19.16.39",
],
),
],
)
object SpoofVideoStreamsPatch : BytecodePatch(
setOf(
BuildInitPlaybackRequestFingerprint,
BuildPlayerRequestURIFingerprint,
CreateStreamingDataFingerprint,
BuildMediaDataSourceFingerprint,
BuildRequestFingerprint,
ProtobufClassParseByteBufferFingerprint,
),
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofVideoStreamsPatch;"
override fun execute(context: BytecodeContext) {
AddResourcesPatch(this::class)
SettingsPatch.PreferenceScreen.MISC.addPreferences(
PreferenceScreen(
key = "revanced_spoof_video_streams_screen",
sorting = PreferenceScreen.Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_spoof_video_streams"),
ListPreference(
"revanced_spoof_video_streams_client_type",
summaryKey = null,
entriesKey = "revanced_spoof_video_streams_client_type_entries",
entryValuesKey = "revanced_spoof_video_streams_client_type_entry_values",
),
SwitchPreference(
"revanced_spoof_video_streams_ios_force_avc",
tag = "app.revanced.integrations.youtube.settings.preference.ForceAVCSpoofingPreference",
),
NonInteractivePreference("revanced_spoof_video_streams_about_ios"),
NonInteractivePreference("revanced_spoof_video_streams_about_android_vr"),
),
),
)
// region Block /initplayback requests to fall back to /get_watch requests.
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
it.mutableMethod.apply {
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
addInstructions(
moveUriStringIndex + 1,
"""
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
""",
)
}
}
// endregion
// region Block /get_watch requests to fall back to /player requests.
BuildPlayerRequestURIFingerprint.resultOrThrow().let {
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
it.mutableMethod.apply {
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
addInstructions(
invokeToStringIndex,
"""
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
move-result-object v$uriRegister
""",
)
}
}
// endregion
// region Get replacement streams at player requests.
BuildRequestFingerprint.resultOrThrow().mutableMethod.apply {
val newRequestBuilderIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "newUrlRequestBuilder"
}
val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
val freeRegister = getInstruction<OneRegisterInstruction>(newRequestBuilderIndex + 1).registerA
addInstructions(
newRequestBuilderIndex,
"""
move-object v$freeRegister, p1
invoke-static { v$urlRegister, v$freeRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;Ljava/util/Map;)V
""",
)
}
// endregion
// region Replace the streaming data with the replacement streams.
CreateStreamingDataFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply {
val setStreamDataMethodName = "patch_setStreamingData"
val resultMethodType = result.mutableClass.type
val videoDetailsIndex = result.scanResult.patternScanResult!!.endIndex
val videoDetailsRegister = getInstruction<TwoRegisterInstruction>(videoDetailsIndex).registerA
val videoDetailsClass = getInstruction(videoDetailsIndex).getReference<FieldReference>()!!.type
addInstruction(
videoDetailsIndex + 1,
"invoke-direct { p0, v$videoDetailsRegister }, " +
"$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V",
)
val protobufClass = ProtobufClassParseByteBufferFingerprint.resultOrThrow().mutableMethod.definingClass
val setStreamingDataIndex = result.scanResult.patternScanResult!!.startIndex
val playerProtoClass = getInstruction(setStreamingDataIndex + 1)
.getReference<FieldReference>()!!.definingClass
val setStreamingDataField = getInstruction(setStreamingDataIndex).getReference<FieldReference>()
val getStreamingDataField = getInstruction(
indexOfFirstInstructionOrThrow {
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.definingClass == playerProtoClass
}
).getReference<FieldReference>()
// Use a helper method to avoid the need of picking out multiple free registers from the hooked code.
result.mutableClass.methods.add(
ImmutableMethod(
resultMethodType,
setStreamDataMethodName,
listOf(ImmutableMethodParameter(videoDetailsClass, null, "videoDetails")),
"V",
AccessFlags.PRIVATE or AccessFlags.FINAL,
null,
null,
MutableMethodImplementation(9),
).toMutable().apply {
addInstructionsWithLabels(
0,
"""
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSpoofingEnabled()Z
move-result v0
if-eqz v0, :disabled
# Get video id.
iget-object v2, p1, $videoDetailsClass->c:Ljava/lang/String;
if-eqz v2, :disabled
# Get streaming data.
invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStreamingData(Ljava/lang/String;)Ljava/nio/ByteBuffer;
move-result-object v3
if-eqz v3, :disabled
# Parse streaming data.
sget-object v4, $playerProtoClass->a:$playerProtoClass
invoke-static { v4, v3 }, $protobufClass->parseFrom(${protobufClass}Ljava/nio/ByteBuffer;)$protobufClass
move-result-object v5
check-cast v5, $playerProtoClass
# Set streaming data.
iget-object v6, v5, $getStreamingDataField
if-eqz v6, :disabled
iput-object v6, p0, $setStreamingDataField
:disabled
return-void
""",
)
},
)
}
}
// endregion
// region Remove /videoplayback request body to fix playback.
// This is needed when using iOS client as streaming data source.
BuildMediaDataSourceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getInstructions().lastIndex
// Instructions are added just before the method returns,
// so there's no concern of clobbering in-use registers.
addInstructions(
targetIndex,
"""
# Field a: Stream uri.
# Field c: Http method.
# Field d: Post data.
move-object v0, p0 # method has over 15 registers and must copy p0 to a lower register.
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
iget v2, v0, $definingClass->c:I
iget-object v3, v0, $definingClass->d:[B
invoke-static { v1, v2, v3 }, $INTEGRATIONS_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
move-result-object v1
iput-object v1, v0, $definingClass->d:[B
""",
)
}
}
// endregion
}
}

View File

@@ -0,0 +1,22 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object BuildMediaDataSourceFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
returnType = "V",
parameters = listOf(
"Landroid/net/Uri;",
"J",
"I",
"[B",
"Ljava/util/Map;",
"J",
"J",
"Ljava/lang/String;",
"I",
"Ljava/lang/Object;"
)
)

View File

@@ -3,13 +3,34 @@ package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object BuildRequestFingerprint : MethodFingerprint( internal object BuildRequestFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
returnType = "Lorg/chromium/net/UrlRequest;", returnType = "Lorg/chromium/net/UrlRequest;",
opcodes = listOf( customFingerprint = { methodDef, _ ->
Opcode.INVOKE_DIRECT, // Different targets have slightly different parameters
Opcode.INVOKE_VIRTUAL
) // Earlier targets have parameters:
//L
//Ljava/util/Map;
//[B
//L
//L
//L
//Lorg/chromium/net/UrlRequest$Callback;
// Later targets have parameters:
//L
//Ljava/util/Map;
//[B
//L
//L
//L
//Lorg/chromium/net/UrlRequest\$Callback;
//L
val parameterTypes = methodDef.parameterTypes
(parameterTypes.size == 7 || parameterTypes.size == 8)
&& parameterTypes[1] == "Ljava/util/Map;" // URL headers.
}
) )

View File

@@ -1,34 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object CreatePlaybackSpeedMenuItemFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
opcodes = listOf(
Opcode.IGET_OBJECT, // First instruction of the method
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
null // MOVE_RESULT or MOVE_RESULT_OBJECT, Return value controls the creation of the playback speed menu item.
),
// 19.01 and earlier is missing the second parameter.
// Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures.
customFingerprint = custom@{ methodDef, _ ->
// 19.01 and earlier parameters are: "[L"
// 19.02+ parameters are "[L", "F"
val parameterTypes = methodDef.parameterTypes
val firstParameter = parameterTypes.firstOrNull()
if (firstParameter == null || !firstParameter.startsWith("[L")) {
return@custom false
}
parameterTypes.size == 1 || (parameterTypes.size == 2 && parameterTypes[1] == "F")
}
)

View File

@@ -1,15 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object CreatePlayerRequestBodyFingerprint : MethodFingerprint(
returnType = "V",
parameters = listOf("L"),
opcodes = listOf(
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.AND_INT_LIT16,
),
strings = listOf("ms"),
)

View File

@@ -1,31 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction
import app.revanced.util.containsWideLiteralInstructionValue
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
internal object CreatePlayerRequestBodyWithModelFingerprint : MethodFingerprint(
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
customFingerprint = { methodDef, _ ->
methodDef.containsWideLiteralInstructionValue(1073741824) &&
indexOfBuildModelInstruction(methodDef) >= 0
},
) {
fun indexOfBuildModelInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
val reference = getReference<FieldReference>()
reference?.definingClass == "Landroid/os/Build;" &&
reference.name == "MODEL" &&
reference.type == "Ljava/lang/String;"
}
}

View File

@@ -1,31 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.CreatePlayerRequestBodyWithVersionReleaseFingerprint.indexOfBuildVersionReleaseInstruction
import app.revanced.util.containsWideLiteralInstructionValue
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
internal object CreatePlayerRequestBodyWithVersionReleaseFingerprint : MethodFingerprint(
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(),
customFingerprint = { methodDef, _ ->
methodDef.containsWideLiteralInstructionValue(1073741824) &&
indexOfBuildVersionReleaseInstruction(methodDef) >= 0
},
) {
fun indexOfBuildVersionReleaseInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
val reference = getReference<FieldReference>()
reference?.definingClass == "Landroid/os/Build\$VERSION;" &&
reference.name == "RELEASE" &&
reference.type == "Ljava/lang/String;"
}
}

View File

@@ -0,0 +1,24 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object CreateStreamingDataFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
returnType = "V",
parameters = listOf("L"),
opcodes = listOf(
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IPUT_OBJECT
),
customFingerprint = { methodDef, classDef ->
classDef.fields.any { field ->
field.name == "a" && field.type.endsWith("/StreamingDataOuterClass\$StreamingData;")
}
},
)

View File

@@ -1,25 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object ParamsMapPutFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(
"Ljava/lang/String;",
"Ljava/lang/String;",
),
opcodes = listOf(
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.MOVE_OBJECT,
Opcode.MOVE_OBJECT,
Opcode.MOVE_OBJECT,
Opcode.INVOKE_DIRECT_RANGE,
),
)

View File

@@ -1,49 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object PlayerGestureConfigSyntheticFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Ljava/lang/Object;"),
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL, // playerGestureConfig.downAndOutLandscapeAllowed.
Opcode.MOVE_RESULT,
Opcode.CHECK_CAST,
Opcode.IPUT_BOOLEAN,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL, // playerGestureConfig.downAndOutPortraitAllowed.
Opcode.MOVE_RESULT,
Opcode.IPUT_BOOLEAN,
Opcode.RETURN_VOID,
),
customFingerprint = { methodDef, classDef ->
fun indexOfDownAndOutAllowedInstruction(methodDef: Method) =
methodDef.indexOfFirstInstruction {
val reference = getReference<MethodReference>()
reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;" &&
reference.parameterTypes.isEmpty() &&
reference.returnType == "Z"
}
// This method is always called "a" because this kind of class always has a single method.
methodDef.name == "a" && classDef.methods.count() == 2 &&
indexOfDownAndOutAllowedInstruction(methodDef) >= 0
},
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.containsWideLiteralInstructionValue
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object PlayerResponseModelImplGeneralFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.RETURN_OBJECT,
Opcode.CONST_4,
Opcode.RETURN_OBJECT,
),
customFingerprint = handler@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;")) return@handler false
methodDef.containsWideLiteralInstructionValue(55735497)
},
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.containsWideLiteralInstructionValue
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object PlayerResponseModelImplLiveStreamFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.RETURN_OBJECT,
Opcode.CONST_4,
Opcode.RETURN_OBJECT,
),
customFingerprint = handler@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;")) return@handler false
methodDef.containsWideLiteralInstructionValue(70276274)
},
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.containsWideLiteralInstructionValue
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object PlayerResponseModelImplRecommendedLevelFingerprint : MethodFingerprint(
returnType = "I",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.RETURN,
),
customFingerprint = handler@{ methodDef, _ ->
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;")) return@handler false
methodDef.containsWideLiteralInstructionValue(55735497)
},
)

View File

@@ -5,17 +5,15 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal object GetTrackingUriFingerprint : MethodFingerprint( internal object ProtobufClassParseByteBufferFingerprint : MethodFingerprint(
returnType = "Landroid/net/Uri;", accessFlags = AccessFlags.PROTECTED or AccessFlags.STATIC,
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("L", "Ljava/nio/ByteBuffer;"),
parameters = emptyList(), returnType = "L",
opcodes = listOf( opcodes = listOf(
Opcode.IGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT Opcode.RETURN_OBJECT,
), ),
customFingerprint = { _, classDef -> customFingerprint = { methodDef, _ -> methodDef.name == "parseFrom" },
classDef.endsWith("TrackingUrlModel;")
}
) )

View File

@@ -1,13 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object SetPlayerRequestClientTypeFingerprint : LiteralValueFingerprint(
opcodes = listOf(
Opcode.IGET,
Opcode.IPUT, // Sets ClientInfo.clientId.
),
strings = listOf("10.29"),
literalSupplier = { 134217728 }
)

View File

@@ -1,28 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.misc.fix.playback.SpoofSignatureResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object SpoofSignaturePatchScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("Landroid/content/Context;", "Landroid/util/AttributeSet;", "I", "I"),
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT, // preview imageview
),
// This resource is used in ~ 40 different locations, but this method has a distinct list of parameters to match to.
literalSupplier = { SpoofSignatureResourcePatch.scrubbedPreviewThumbnailResourceId },
)

View File

@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object StatsQueryParameterFingerprint : MethodFingerprint(
strings = listOf("adunit"),
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves to the same method as [StoryboardRendererDecoderSpecFingerprint].
*/
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object StoryboardRendererDecoderRecommendedLevelFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
),
strings = listOf("#-1#"),
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves to the same method as [StoryboardRendererDecoderRecommendedLevelFingerprint].
*/
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object StoryboardRendererDecoderSpecFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
opcodes = listOf(
Opcode.INVOKE_INTERFACE, // First instruction of the method.
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.IF_NEZ,
),
strings = listOf("#-1#"),
)

View File

@@ -1,13 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object StoryboardRendererSpecFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
returnType = "L",
parameters = listOf("Ljava/lang/String;", "J"),
strings = listOf("\\|"),
)

View File

@@ -1,24 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves using the class found in [StoryboardThumbnailParentFingerprint].
*/
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object StoryboardThumbnailFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z",
parameters = listOf(),
opcodes = listOf(
Opcode.MOVE_RESULT,
Opcode.IF_GTZ,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.RETURN,
Opcode.RETURN, // Last instruction of method.
),
)

View File

@@ -1,18 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Here lies code that creates the seekbar thumbnails.
*
* An additional change here might force the thumbnails to be created,
* or possibly a change somewhere else (maybe involving YouTube 18.23.35 class `hte`)
*/
@Deprecated("Fingerprint is obsolete and will be deleted soon")
internal object StoryboardThumbnailParentFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Landroid/graphics/Bitmap;",
strings = listOf("Storyboard regionDecoder.decodeRegion exception - "),
)

View File

@@ -16,6 +16,7 @@ import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.reques
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnResponseStartedFingerprint import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnSucceededFingerprint import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnSucceededFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.util.alsoResolve
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@@ -84,17 +85,14 @@ object CronetImageUrlHook : BytecodePatch(
} }
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
loadImageUrlMethod = MessageDigestImageUrlFingerprint loadImageUrlMethod = MessageDigestImageUrlFingerprint
.alsoResolve(MessageDigestImageUrlParentFingerprint).mutableMethod .alsoResolve(context, MessageDigestImageUrlParentFingerprint).mutableMethod
loadImageSuccessCallbackMethod = OnSucceededFingerprint loadImageSuccessCallbackMethod = OnSucceededFingerprint
.alsoResolve(OnResponseStartedFingerprint).mutableMethod .alsoResolve(context, OnResponseStartedFingerprint).mutableMethod
loadImageErrorCallbackMethod = OnFailureFingerprint loadImageErrorCallbackMethod = OnFailureFingerprint
.alsoResolve(OnResponseStartedFingerprint).mutableMethod .alsoResolve(context, OnResponseStartedFingerprint).mutableMethod
// The URL is required for the failure callback hook, but the URL field is obfuscated. // The URL is required for the failure callback hook, but the URL field is obfuscated.
// Add a helper get method that returns the URL field. // Add a helper get method that returns the URL field.

View File

@@ -15,6 +15,7 @@ import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.TextPreference import app.revanced.patches.shared.misc.settings.preference.TextPreference
import app.revanced.patches.youtube.misc.check.CheckEnvironmentPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.fingerprints.LicenseActivityOnCreateFingerprint import app.revanced.patches.youtube.misc.settings.fingerprints.LicenseActivityOnCreateFingerprint
import app.revanced.patches.youtube.misc.settings.fingerprints.SetThemeFingerprint import app.revanced.patches.youtube.misc.settings.fingerprints.SetThemeFingerprint
@@ -30,6 +31,9 @@ import java.io.Closeable
IntegrationsPatch::class, IntegrationsPatch::class,
SettingsResourcePatch::class, SettingsResourcePatch::class,
AddResourcesPatch::class, AddResourcesPatch::class,
// Currently there is no easy way to make a mandatory patch,
// so for now this is a dependent of this patch.
CheckEnvironmentPatch::class,
], ],
) )
object SettingsPatch : object SettingsPatch :

View File

@@ -28,8 +28,6 @@ object SettingsResourcePatch : BaseSettingsResourcePatch(
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
super.execute(context) super.execute(context)
AddResourcesPatch(this::class)
// Used for a fingerprint from SettingsPatch. // Used for a fingerprint from SettingsPatch.
appearanceStringId = ResourceMappingPatch["string", "app_theme_appearance_dark"] appearanceStringId = ResourceMappingPatch["string", "app_theme_appearance_dark"]

View File

@@ -7,12 +7,14 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.video.information.fingerprints.* import app.revanced.patches.youtube.video.information.fingerprints.*
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import app.revanced.util.alsoResolve
import app.revanced.util.exception import app.revanced.util.exception
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
@@ -45,9 +47,11 @@ object VideoInformationPatch : BytecodePatch(
) )
) { ) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/VideoInformation;" private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/VideoInformation;"
private const val INTEGRATIONS_PLAYER_INTERFACE = "Lapp/revanced/integrations/youtube/patches/VideoInformation${'$'}PlaybackController;"
private lateinit var playerInitMethod: MutableMethod private lateinit var playerInitMethod: MutableMethod
private var playerInitInsertIndex = 4 private var playerInitInsertIndex = -1
private var playerInitInsertRegister = -1
private lateinit var mdxInitMethod: MutableMethod private lateinit var mdxInitMethod: MutableMethod
private var mdxInitInsertIndex = -1 private var mdxInitInsertIndex = -1
@@ -70,42 +74,43 @@ object VideoInformationPatch : BytecodePatch(
with(PlayerInitFingerprint.resultOrThrow()) { with(PlayerInitFingerprint.resultOrThrow()) {
playerInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) } playerInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) }
// hook the player controller for use through integrations // find the location of the first invoke-direct call and extract the register storing the 'this' object reference.
val initThisIndex = playerInitMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
}
playerInitInsertRegister = playerInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
playerInitInsertIndex = initThisIndex + 1
// Hook the player controller for use through integrations.
onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "initialize") onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "initialize")
// seek method
val seekFingerprintResultMethod = val seekFingerprintResultMethod =
SeekFingerprint.also { it.resolve(context, classDef) }.resultOrThrow().method SeekFingerprint.alsoResolve(context, PlayerInitFingerprint).method
val seekRelativeFingerprintResultMethod =
SeekRelativeFingerprint.alsoResolve(context, PlayerInitFingerprint).method
// create helper method // Create integrations interface methods.
val seekHelperMethod = generateSeekMethodHelper(seekFingerprintResultMethod) addSeekInterfaceMethods(mutableClass, seekFingerprintResultMethod, seekRelativeFingerprintResultMethod)
// add the seekTo method to the class for the integrations to call
mutableClass.methods.add(seekHelperMethod)
} }
with(MdxPlayerDirectorSetVideoStageFingerprint.resultOrThrow()) { with(MdxPlayerDirectorSetVideoStageFingerprint.resultOrThrow()) {
mdxInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) } mdxInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) }
// find the location of the first invoke-direct call and extract the register storing the 'this' object reference
val initThisIndex = mdxInitMethod.indexOfFirstInstructionOrThrow { val initThisIndex = mdxInitMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>" opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
} }
mdxInitInsertRegister = mdxInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC mdxInitInsertRegister = mdxInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
mdxInitInsertIndex = initThisIndex + 1 mdxInitInsertIndex = initThisIndex + 1
// hook the MDX director for use through integrations // Hook the MDX director for use through integrations.
onCreateHookMdx(INTEGRATIONS_CLASS_DESCRIPTOR, "initializeMdx") onCreateHookMdx(INTEGRATIONS_CLASS_DESCRIPTOR, "initializeMdx")
// MDX seek method
val mdxSeekFingerprintResultMethod = val mdxSeekFingerprintResultMethod =
MdxSeekFingerprint.apply { resolve(context, classDef) }.resultOrThrow().method MdxSeekFingerprint.alsoResolve(context, MdxPlayerDirectorSetVideoStageFingerprint).method
val mdxSeekRelativeFingerprintResultMethod =
MdxSeekRelativeFingerprint.alsoResolve(context, MdxPlayerDirectorSetVideoStageFingerprint).method
// create helper method addSeekInterfaceMethods(mutableClass, mdxSeekFingerprintResultMethod, mdxSeekRelativeFingerprintResultMethod)
val mdxSeekHelperMethod = generateSeekMethodHelper(mdxSeekFingerprintResultMethod)
// add the seekTo method to the class for the integrations to call
mutableClass.methods.add(mdxSeekHelperMethod)
} }
with(CreateVideoPlayerSeekbarFingerprint.result!!) { with(CreateVideoPlayerSeekbarFingerprint.result!!) {
@@ -173,12 +178,21 @@ object VideoInformationPatch : BytecodePatch(
userSelectedPlaybackSpeedHook(INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed") userSelectedPlaybackSpeedHook(INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed")
} }
private fun generateSeekMethodHelper(seekMethod: Method): MutableMethod { private fun addSeekInterfaceMethods(targetClass: MutableClass, seekToMethod: Method, seekToRelativeMethod: Method) {
// Add the interface and methods that integrations calls.
targetClass.interfaces.add(INTEGRATIONS_PLAYER_INTERFACE)
// create helper method arrayOf(
val generatedMethod = ImmutableMethod( seekToMethod to "seekTo",
seekMethod.definingClass, seekToRelativeMethod to "seekToRelative"
"seekTo", ).forEach { (method, name) ->
// Add interface method.
// Get enum type for the seek helper method.
val seekSourceEnumType = method.parameterTypes[1].toString()
val interfaceImplementation = ImmutableMethod(
targetClass.type,
name,
listOf(ImmutableMethodParameter("J", null, "time")), listOf(ImmutableMethodParameter("J", null, "time")),
"Z", "Z",
AccessFlags.PUBLIC or AccessFlags.FINAL, AccessFlags.PUBLIC or AccessFlags.FINAL,
@@ -186,20 +200,20 @@ object VideoInformationPatch : BytecodePatch(
MutableMethodImplementation(4) MutableMethodImplementation(4)
).toMutable() ).toMutable()
// get enum type for the seek helper method // Insert helper method instructions.
val seekSourceEnumType = seekMethod.parameterTypes[1].toString() interfaceImplementation.addInstructions(
// insert helper method instructions
generatedMethod.addInstructions(
0, 0,
""" """
# first enum (field a) is SEEK_SOURCE_UNKNOWN
sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType
invoke-virtual { p0, p1, p2, v0 }, $seekMethod invoke-virtual { p0, p1, p2, v0 }, $method
move-result p1 move-result p1
return p1 return p1
""" """
) )
return generatedMethod
targetClass.methods.add(interfaceImplementation)
}
} }
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) = private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
@@ -220,8 +234,8 @@ object VideoInformationPatch : BytecodePatch(
internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) = internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
playerInitMethod.insert( playerInitMethod.insert(
playerInitInsertIndex++, playerInitInsertIndex++,
"v0", "v$playerInitInsertRegister",
"$targetMethodClass->$targetMethodName(Ljava/lang/Object;)V" "$targetMethodClass->$targetMethodName($INTEGRATIONS_PLAYER_INTERFACE)V"
) )
/** /**
@@ -234,7 +248,7 @@ object VideoInformationPatch : BytecodePatch(
mdxInitMethod.insert( mdxInitMethod.insert(
mdxInitInsertIndex++, mdxInitInsertIndex++,
"v$mdxInitInsertRegister", "v$mdxInitInsertRegister",
"$targetMethodClass->$targetMethodName(Ljava/lang/Object;)V" "$targetMethodClass->$targetMethodName($INTEGRATIONS_PLAYER_INTERFACE)V"
) )
/** /**

View File

@@ -5,6 +5,9 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves using class found in [MdxPlayerDirectorSetVideoStageFingerprint].
*/
internal object MdxSeekFingerprint : MethodFingerprint( internal object MdxSeekFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z", returnType = "Z",

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves using class found in [MdxPlayerDirectorSetVideoStageFingerprint].
*/
internal object MdxSeekRelativeFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z",
parameters = listOf("J", "L"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE
)
)

View File

@@ -3,6 +3,9 @@ package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
/**
* Resolves using class found in [PlayerInitFingerprint].
*/
internal object SeekFingerprint : MethodFingerprint( internal object SeekFingerprint : MethodFingerprint(
strings = listOf("Attempting to seek during an ad") strings = listOf("Attempting to seek during an ad")
) )

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.youtube.video.information.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* Resolves using class found in [PlayerInitFingerprint].
*/
internal object SeekRelativeFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z",
parameters = listOf("J", "L"),
opcodes = listOf(
Opcode.ADD_LONG_2ADDR,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.RETURN
)
)

View File

@@ -249,3 +249,9 @@ fun Iterable<MethodFingerprint>.returnEarly(bool: Boolean = false) = forEach { f
fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) = forEach { fingerprint -> fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) = forEach { fingerprint ->
fingerprint.returnEarly(bool) fingerprint.returnEarly(bool)
} }
/**
* Resolves this fingerprint using the classDef of a parent fingerprint.
*/
fun MethodFingerprint.alsoResolve(context: BytecodeContext, parentFingerprint: MethodFingerprint) =
also { resolve(context, parentFingerprint.resultOrThrow().classDef) }.resultOrThrow()

View File

@@ -32,15 +32,16 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<!-- Settings about dialog. -->
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
</patch> </patch>
<patch id="misc.debugging.DebuggingPatch"> <patch id="misc.debugging.DebuggingPatch">
@@ -57,7 +58,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. --> <!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
@@ -171,8 +172,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<patch id="layout.sponsorblock.SponsorBlockResourcePatch"> <patch id="layout.sponsorblock.SponsorBlockResourcePatch">
<!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' --> <!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' -->
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<!-- Shown in the settings preferences, and translations can be any text length. --> <!-- Shown in the settings preferences, and translations can be any text length. -->
</patch> </patch>
<patch id="layout.spoofappversion.SpoofAppVersionPatch"> <patch id="layout.spoofappversion.SpoofAppVersionPatch">
@@ -206,6 +205,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
<patch id="misc.announcements.AnnouncementsPatch"> <patch id="misc.announcements.AnnouncementsPatch">
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
</patch> </patch>
<patch id="misc.dimensions.spoof.SpoofDeviceDimensionsPatch"> <patch id="misc.dimensions.spoof.SpoofDeviceDimensionsPatch">
@@ -232,10 +233,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
<patch id="interaction.seekbar.EnableSlideToSeekPatch"> <patch id="interaction.seekbar.EnableSlideToSeekPatch">
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
</patch>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. -->
<patch id="misc.fix.playback.SpoofSignaturePatch">
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

View File

@@ -32,15 +32,16 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<!-- Settings about dialog. -->
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
</patch> </patch>
<patch id="misc.debugging.DebuggingPatch"> <patch id="misc.debugging.DebuggingPatch">
@@ -57,7 +58,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. --> <!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
@@ -171,8 +172,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<patch id="layout.sponsorblock.SponsorBlockResourcePatch"> <patch id="layout.sponsorblock.SponsorBlockResourcePatch">
<!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' --> <!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' -->
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<!-- Shown in the settings preferences, and translations can be any text length. --> <!-- Shown in the settings preferences, and translations can be any text length. -->
</patch> </patch>
<patch id="layout.spoofappversion.SpoofAppVersionPatch"> <patch id="layout.spoofappversion.SpoofAppVersionPatch">
@@ -206,6 +205,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
<patch id="misc.announcements.AnnouncementsPatch"> <patch id="misc.announcements.AnnouncementsPatch">
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
</patch> </patch>
<patch id="misc.dimensions.spoof.SpoofDeviceDimensionsPatch"> <patch id="misc.dimensions.spoof.SpoofDeviceDimensionsPatch">
@@ -232,10 +233,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
<patch id="interaction.seekbar.EnableSlideToSeekPatch"> <patch id="interaction.seekbar.EnableSlideToSeekPatch">
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
</patch>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. -->
<patch id="misc.fix.playback.SpoofSignaturePatch">
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

View File

@@ -32,6 +32,17 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
<string name="revanced_check_environment_failed_title">ŲØ´Ų„ØĒ ØšŲ…Ų„ŲŠØ§ØĒ Ø§Ų„ØĒØ­Ų‚Ų‚</string>
<string name="revanced_check_environment_dialog_open_official_source_button">؁ØĒØ­ Ø§Ų„Ų…ŲˆŲ‚Øš Ø§Ų„ØąØŗŲ…ŲŠ</string>
<string name="revanced_check_environment_dialog_ignore_button">ØĒØŦØ§Ų‡Ų„</string>
<string name="revanced_check_environment_failed_message">&lt;h5&gt;Ų„Ø§ ŲŠØ¨Ø¯Ųˆ ØŖŲ† Ų‡Ø°Ø§ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ų‚Ø¯ ØĒŲ… ØĒØšØ¯ŲŠŲ„Ų‡ Ų…Ų† Ų‚Ø¨Ų„Ųƒ.&lt;/h5&gt;&lt;br&gt;Ų‚Ø¯ Ų„Ø§ ŲŠØšŲ…Ų„ Ų‡Ø°Ø§ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ø¨Ø´ŲƒŲ„ ØĩØ­ŲŠØ­ØŒ &lt;b&gt;Ų‚Ø¯ ŲŠŲƒŲˆŲ† ØļØ§ØąŲ‹Ø§ ØŖŲˆ Ø­ØĒŲ‰ ØŽØˇŲŠØąŲ‹Ø§ Ų„Ų„Ø§ØŗØĒØŽØ¯Ø§Ų…&lt;/b&gt;.&lt;br&gt;&lt;br&gt;ØĒØ´ŲŠØą Ų‡Ø°Ų‡ Ø§Ų„ŲØ­ŲˆØĩاØĒ ØĨŲ„Ų‰ ØŖŲ† Ų‡Ø°Ø§ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ ØĒŲ… ØĒØšØ¯ŲŠŲ„Ų‡ Ų…ØŗØ¨Ų‚Ų‹Ø§ ØŖŲˆ ØĒŲ… Ø§Ų„Ø­ØĩŲˆŲ„ ØšŲ„ŲŠŲ‡ Ų…Ų† Ø´ØŽØĩ ØĸØŽØą:&lt;br&gt;&lt;br&gt;&lt;small&gt;%1$s&lt;/small&gt;&lt;br&gt;؊؈ØĩŲ‰ بشد؊ Ø¨Ų€ &lt;b&gt;ØĨŲ„ØēØ§ØĄ ØĒØĢØ¨ŲŠØĒ Ų‡Ø°Ø§ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ ؈ØĒØšØ¯ŲŠŲ„Ų‡ Ø¨Ų†ŲØŗŲƒ&lt;/b&gt; Ų„Ų„ØĒØŖŲƒØ¯ Ų…Ų† ØŖŲ†Ųƒ ØĒØŗØĒØŽØ¯Ų… ØĒØˇØ¨ŲŠŲ‚Ų‹Ø§ Ų…ØšØĒŲ…Ø¯Ų‹Ø§ ؈ØĸŲ…Ų†Ų‹Ø§.&lt;p&gt;&lt;br&gt;؁؊ Ø­Ø§Ų„ØŠ ØĒØŦØ§Ų‡Ų„ Ų‡Ø°Ø§ Ø§Ų„ØĒØ­Ø°ŲŠØąØŒ ØŗŲŠØĒŲ… ØšØąØļŲ‡ Ų…ØąØĒŲŠŲ† ŲŲ‚Øˇ.</string>
<string name="revanced_check_environment_not_same_patching_device">ØĒŲ… ØĒØšØ¯ŲŠŲ„Ų‡ ØšŲ„Ų‰ ØŦŲ‡Ø§Ø˛ Ų…ØŽØĒ؄؁</string>
<string name="revanced_check_environment_manager_not_expected_installer">Ų„Ų… ؊ØĒŲ… ØĒØĢØ¨ŲŠØĒŲ‡ Ø¨ŲˆØ§ØŗØˇØŠ ReVanced Manager</string>
<string name="revanced_check_environment_not_near_patch_time">ØĒŲ… ØĒØšØ¯ŲŠŲ„Ų‡ Ų‚Ø¨Ų„ ØŖŲƒØĢØą Ų…Ų† 10 Ø¯Ų‚Ø§ØĻŲ‚</string>
<string name="revanced_check_environment_not_near_patch_time_days">ØĒŲ… Ø§Ų„ØĒØšØ¯ŲŠŲ„ Ų…Ų†Ø° %s ŲŠŲˆŲ…</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">ØĒØ§ØąŲŠØŽ ØĨŲ†Ø´Ø§ØĄ APK ØĒØ§Ų„Ų</string>
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<string name="revanced_settings_confirm_user_dialog_title">Ų‡Ų„ ØĒØąØēب ؁؊ Ø§Ų„Ų…ØĒابؚ؊؟</string> <string name="revanced_settings_confirm_user_dialog_title">Ų‡Ų„ ØĒØąØēب ؁؊ Ø§Ų„Ų…ØĒابؚ؊؟</string>
<string name="revanced_settings_reset">ØĨؚاد؊ Ø§Ų„ØĒØšŲŠŲŠŲ†</string> <string name="revanced_settings_reset">ØĨؚاد؊ Ø§Ų„ØĒØšŲŠŲŠŲ†</string>
@@ -42,6 +53,14 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_settings_import_reset">ØĨؚاد؊ ØĒØšŲŠŲŠŲ† ØĨؚداداØĒ ReVanced ØĨŲ„Ų‰ Ø§Ų„ŲˆØļØš Ø§Ų„Ø§ŲØĒØąØ§Øļ؊</string> <string name="revanced_settings_import_reset">ØĨؚاد؊ ØĒØšŲŠŲŠŲ† ØĨؚداداØĒ ReVanced ØĨŲ„Ų‰ Ø§Ų„ŲˆØļØš Ø§Ų„Ø§ŲØĒØąØ§Øļ؊</string>
<string name="revanced_settings_import_success">ØĒŲ… Ø§ØŗØĒŲŠØąØ§Ø¯ %d ØĨؚداداØĒ</string> <string name="revanced_settings_import_success">ØĒŲ… Ø§ØŗØĒŲŠØąØ§Ø¯ %d ØĨؚداداØĒ</string>
<string name="revanced_settings_import_failure_parse">ŲØ´Ų„ Ø§Ų„Ø§ØŗØĒŲŠØąØ§Ø¯: %s</string> <string name="revanced_settings_import_failure_parse">ŲØ´Ų„ Ø§Ų„Ø§ØŗØĒŲŠØąØ§Ø¯: %s</string>
<string name="revanced_pref_import_export_title">Ø§ØŗØĒŲŠØąØ§Ø¯ / ØĒØĩØ¯ŲŠØą</string>
<string name="revanced_pref_import_export_summary">Ø§ØŗØĒŲŠØąØ§Ø¯ / ØĒØĩØ¯ŲŠØą ØĨؚداداØĒ ReVanced</string>
<!-- Settings about dialog. -->
<string name="revanced_settings_about_links_body">ØŖŲ†ØĒ ØĒØŗØĒØŽØ¯Ų… ØĨØĩØ¯Ø§Øą ReVanced Patches &lt;i&gt;%s&lt;/i&gt;</string>
<string name="revanced_settings_about_links_dev_header">Ų…Ų„Ø§Ø­Ø¸ØŠ</string>
<string name="revanced_settings_about_links_dev_body">Ų‡Ø°Ø§ Ø§Ų„ØĨØĩØ¯Ø§Øą Ų‡Ųˆ ØĨØĩØ¯Ø§Øą Ų…ØŗØ¨Ų‚ØŒ ŲˆŲ‚Ø¯ ØĒŲˆØ§ØŦŲ‡ Ų…Ø´Ø§ŲƒŲ„ ØēŲŠØą Ų…ØĒŲˆŲ‚ØšØŠ</string>
<string name="revanced_settings_about_links_header">Ø§Ų„ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØąØŗŲ…ŲŠØŠ</string>
<string name="revanced_settings_about_links_donate">ØĒØ¨ØąØš</string>
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
@@ -54,14 +73,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
<string name="revanced_settings_about_links_body">ØŖŲ†ØĒ ØĒØŗØĒØŽØ¯Ų… ØĨØĩØ¯Ø§Øą ReVanced Patches &lt;i&gt;%s&lt;/i&gt;</string>
<string name="revanced_settings_about_links_dev_header">Ų…Ų„Ø§Ø­Ø¸ØŠ</string>
<string name="revanced_settings_about_links_dev_body">Ų‡Ø°Ø§ Ø§Ų„ØĨØĩØ¯Ø§Øą Ų‡Ųˆ ØĨØĩØ¯Ø§Øą Ų…ØŗØ¨Ų‚ØŒ ŲˆŲ‚Ø¯ ØĒŲˆØ§ØŦŲ‡ Ų…Ø´Ø§ŲƒŲ„ ØēŲŠØą Ų…ØĒŲˆŲ‚ØšØŠ</string>
<string name="revanced_settings_about_links_header">Ø§Ų„ØąŲˆØ§Ø¨Øˇ Ø§Ų„ØąØŗŲ…ŲŠØŠ</string>
<string name="revanced_pref_import_export_title">Ø§ØŗØĒŲŠØąØ§Ø¯ / ØĒØĩØ¯ŲŠØą</string>
<string name="revanced_pref_import_export_summary">Ø§ØŗØĒŲŠØąØ§Ø¯ / ØĒØĩØ¯ŲŠØą ØĨؚداداØĒ ReVanced</string>
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
<string name="revanced_settings_screen_00_about_title">Ų„Ų…Ø­ØŠ</string> <string name="revanced_settings_screen_00_about_title">Ų„Ų…Ø­ØŠ</string>
<string name="revanced_settings_screen_01_ads_title">Ø§Ų„ØĨØšŲ„Ø§Ų†Ø§ØĒ</string> <string name="revanced_settings_screen_01_ads_title">Ø§Ų„ØĨØšŲ„Ø§Ų†Ø§ØĒ</string>
@@ -211,6 +222,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_info_cards_section_title">ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø¨ØˇØ§Ų‚Ø§ØĒ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ</string> <string name="revanced_hide_info_cards_section_title">ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø¨ØˇØ§Ų‚Ø§ØĒ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ</string>
<string name="revanced_hide_info_cards_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø¨ØˇØ§Ų‚Ø§ØĒ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ</string> <string name="revanced_hide_info_cards_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø¨ØˇØ§Ų‚Ø§ØĒ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ</string>
<string name="revanced_hide_info_cards_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ø¨ØˇØ§Ų‚Ø§ØĒ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ</string> <string name="revanced_hide_info_cards_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ø¨ØˇØ§Ų‚Ø§ØĒ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ</string>
<string name="revanced_hide_key_concepts_section_title">ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… \'Ø§Ų„Ų…ŲØ§Ų‡ŲŠŲ… Ø§Ų„ØŖØŗØ§ØŗŲŠØŠ\'</string>
<string name="revanced_hide_key_concepts_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… \'Ø§Ų„Ų…ŲØ§Ų‡ŲŠŲ… Ø§Ų„ØŖØŗØ§ØŗŲŠØŠ\'</string>
<string name="revanced_hide_key_concepts_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… \'Ø§Ų„Ų…ŲØ§Ų‡ŲŠŲ… Ø§Ų„ØŖØŗØ§ØŗŲŠØŠ\'</string>
<string name="revanced_hide_transcript_section_title">ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø§Ų„Ų†Øĩ</string> <string name="revanced_hide_transcript_section_title">ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø§Ų„Ų†Øĩ</string>
<string name="revanced_hide_transcript_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø§Ų„Ų†Øĩ</string> <string name="revanced_hide_transcript_section_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ų‚ØŗŲ… Ø§Ų„Ų†Øĩ</string>
<string name="revanced_hide_transcript_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ø§Ų„Ų†Øĩ</string> <string name="revanced_hide_transcript_section_summary_off">؊ØĒŲ… ØšØąØļ Ų‚ØŗŲ… Ø§Ų„Ų†Øĩ</string>
@@ -239,14 +253,18 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_keyword_content_phrases_title">Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ Ø§Ų„Ų…ØąØ§Ø¯ ØĨØŽŲØ§Ø¤Ų‡Ø§</string> <string name="revanced_hide_keyword_content_phrases_title">Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ Ø§Ų„Ų…ØąØ§Ø¯ ØĨØŽŲØ§Ø¤Ų‡Ø§</string>
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<string name="revanced_hide_keyword_content_phrases_summary">Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ ŲˆØ§Ų„ØšØ¨Ø§ØąØ§ØĒ Ø§Ų„Ų…ØąØ§Ø¯ ØĨØŽŲØ§Ø¤Ų‡Ø§ØŒ ؅؁ØĩŲˆŲ„ØŠ Ø¨ØŖØŗØˇØą ØŦØ¯ŲŠØ¯\n\nØ§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„ØĒ؊ ØĒØ­ØĒ؈؊ ØšŲ„Ų‰ ØŖØ­ØąŲ ŲƒØ¨ŲŠØąØŠ ؁؊ Ø§Ų„ŲˆØŗØˇ ؊ØŦب ØĨØ¯ØŽØ§Ų„Ų‡Ø§ Ų…Øš Ø§Ų„ØĒØēŲ„ŲŠŲ (Ų…ØĢŲ„: iPhone, TikTok, Leblanc)</string> <string name="revanced_hide_keyword_content_phrases_summary">Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ ŲˆØ§Ų„ØšØ¨Ø§ØąØ§ØĒ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ Ø§Ų„ØĒ؊ ؊ØŦب ØĨØŽŲØ§Ø¤Ų‡Ø§ØŒ ؅؁ØĩŲˆŲ„ØŠ Ø¨ØŗØˇØą ØŦØ¯ŲŠØ¯\n\nØ§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ ŲŠŲ…ŲƒŲ† ØŖŲ† ØĒŲƒŲˆŲ† ØŖØŗŲ…Ø§ØĄ Ų‚Ų†ŲˆØ§ØĒ ØŖŲˆ ØŖŲŠ Ų†Øĩ ŲŠØ¸Ų‡Øą ؁؊ ØšŲ†Ø§ŲˆŲŠŲ† Ø§Ų„ŲŲŠØ¯ŲŠŲˆ\n\n؊ØŦب ØĨØ¯ØŽØ§Ų„ Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„ØĒ؊ ØĒØ­ØĒ؈؊ ØšŲ„Ų‰ ØŖØ­ØąŲ ŲƒØ¨ŲŠØąØŠ ؁؊ Ø§Ų„ŲˆØŗØˇ بØĨØŗØĒØŽØ¯Ø§Ų… Ø§Ų„ØŖØ­ØąŲ Ø§Ų„ŲƒØ¨ŲŠØąØŠ (Ų…ØĢØ§Ų„: iPhone، TikTok، LeBlanc)</string>
<string name="revanced_hide_keyword_content_about_title">Ø­ŲˆŲ„ ØĒØĩŲŲŠØŠ Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ</string> <string name="revanced_hide_keyword_content_about_title">Ø­ŲˆŲ„ ØĒØĩŲŲŠØŠ Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ</string>
<string name="revanced_hide_keyword_content_about_summary">Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ/Ø§Ų„Ø§Ø´ØĒØąØ§Ųƒ/Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ ؊ØĒŲ… ØĒØĩ؁؊ØĒŲ‡Ø§ Ų„ØĨØŽŲØ§ØĄ Ø§Ų„Ų…Ø­ØĒŲˆŲ‰ Ø§Ų„Ø°ŲŠ ŲŠØˇØ§Ø¨Ų‚ ØšØ¨Ø§ØąØ§ØĒ Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ\n\nØ§Ų„ØĒŲ‚ŲŠŲŠØ¯\nâ€ĸ بؚØļ Ø§Ų„Ų…Ų‚Ø§ØˇØš Ø§Ų„Ų‚ØĩŲŠØąØŠ Ų‚Ø¯ Ų„Ø§ ØĒŲƒŲˆŲ† Ų…ØŽŲŲŠØŠ\nâ€ĸ بؚØļ Ų…ŲƒŲˆŲ†Ø§ØĒ ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ų‚Ø¯ Ų„Ø§ ØĒŲƒŲˆŲ† Ų…ØŽŲŲŠØŠ\nâ€ĸ Ø§Ų„Ø¨Ø­ØĢ ØšŲ† ŲƒŲ„Ų…ØŠ ØąØĻŲŠØŗŲŠØŠ Ų‚Ø¯ Ų„Ø§ ŲŠØ¸Ų‡Øą ØŖŲŠ Ų†ØĒاØĻØŦ</string> <string name="revanced_hide_keyword_content_about_summary">Ø§Ų„ØĩŲØ­ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ/Ø§Ų„Ø§Ø´ØĒØąØ§ŲƒØ§ØĒ/Ų†ØĒاØĻØŦ Ø§Ų„ØĨØ´ØĒØąØ§Ųƒ/؊ØĒŲ… ØĒØĩŲŲŠØŠ Ų†ØĒاØĻØŦ Ø§Ų„Ø¨Ø­ØĢ Ų„ØĨØŽŲØ§ØĄ Ø§Ų„Ų…Ø­ØĒŲˆŲ‰ Ø§Ų„Ø°ŲŠ ؊ØĒØˇØ§Ø¨Ų‚ Ų…Øš ØšØ¨Ø§ØąØ§ØĒ Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ\n\nØ§Ų„Ų‚ŲŠŲˆØ¯\nâ€ĸ Ų„Ø§ ŲŠŲ…ŲƒŲ† ØĨØŽŲØ§ØĄ ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ Shorts Ø¨ŲˆØ§ØŗØˇØŠ Ø§ØŗŲ… Ø§Ų„Ų‚Ų†Ø§ØŠ\nâ€ĸ Ų‚Ø¯ Ų„Ø§ ØĒŲƒŲˆŲ† بؚØļ Ų…ŲƒŲˆŲ†Ø§ØĒ ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ų…ØŽŲŲŠØŠ\nâ€ĸ Ų‚Ø¯ Ų„Ø§ ØĒØ¸Ų‡Øą Ų†ØĒاØĻØŦ بحØĢ ØšŲ† ŲƒŲ„Ų…ØŠ ØąØĻŲŠØŗŲŠØŠ</string>
<string name="revanced_hide_keyword_content_about_whole_words_title">Ų…ØˇØ§Ø¨Ų‚ØŠ Ø§Ų„ŲƒŲ„Ų…Ø§ØĒ Ø¨ØŖŲƒŲ…Ų„Ų‡Ø§</string>
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<string name="revanced_hide_keyword_content_about_whole_words_summary">ØŗŲŠØ¤Ø¯ŲŠ ؈ØļØš ØšŲ„Ø§Ų…ØŠ Ø§Ų‚ØĒØ¨Ø§Øŗ Ų…Ø˛Ø¯ŲˆØŦØŠ Ø­ŲˆŲ„ ŲƒŲ„Ų…ØŠ ØąØĻŲŠØŗŲŠØŠ/ØšØ¨Ø§ØąØŠ ØĨŲ„Ų‰ Ų…Ų†Øš Ø§Ų„ØĒØˇØ§Ø¨Ų‚Ø§ØĒ Ø§Ų„ØŦØ˛ØĻŲŠØŠ Ų„ØšŲ†Ø§ŲˆŲŠŲ† Ø§Ų„ŲŲŠØ¯ŲŠŲˆ ŲˆØŖØŗŲ…Ø§ØĄ Ø§Ų„Ų‚Ų†ŲˆØ§ØĒ.&lt;br&gt;&lt;br&gt;ØšŲ„Ų‰ ØŗØ¨ŲŠŲ„ Ø§Ų„Ų…ØĢØ§Ų„ØŒ&lt;br&gt;&lt;b&gt;\"ai\"&lt;/b&gt; ØŗŲŠØŽŲŲŠ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ: &lt;b&gt;How does AI work?&lt;/b&gt;&lt;br&gt;ŲˆŲ„ŲƒŲ† Ų„Ų† ŲŠØŽŲŲŠ: &lt;b&gt;What does fair use mean?&lt;/b&gt;</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_common">Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ ØēŲŠØą ØĩØ§Ų„Ø­ØŠ. Ų„Ø§ ŲŠŲ…ŲƒŲ† Ø§ØŗØĒØŽØ¯Ø§Ų…: \'%s\' ŲƒØšØ§Ų…Ų„ ØĒØĩŲŲŠØŠ</string> <string name="revanced_hide_keyword_toast_invalid_common">Ų„Ø§ ŲŠŲ…ŲƒŲ† Ø§ØŗØĒØŽØ¯Ø§Ų… Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ: %s</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <string name="revanced_hide_keyword_toast_invalid_common_whole_word_required">ØĨØļØ§ŲØŠ Ø§Ų‚ØĒØ¨Ø§ØŗØ§ØĒ Ų„Ø§ØŗØĒØŽØ¯Ø§Ų… Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ: %s</string>
<string name="revanced_hide_keyword_toast_invalid_length">Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ŲØĒØ§Ø­ŲŠØŠ ØēŲŠØą ØĩØ§Ų„Ø­ØŠ. \'%1$s\' ØŖŲ‚Ų„ Ų…Ų† %2$d Ø­ØąŲŲ‹Ø§</string> <string name="revanced_hide_keyword_toast_invalid_conflicting">Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ Ų„Ų‡Ø§ Ø¨ŲŠØ§Ų†Ø§ØĒ Ų…ØĒØļØ§ØąØ¨ØŠ: %s</string>
<string name="revanced_hide_keyword_toast_invalid_broad">Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ \'%s\' ØŗŲˆŲ ØĒØŽŲŲŠ ØŦŲ…ŲŠØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ</string> <string name="revanced_hide_keyword_toast_invalid_length">Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ Ų‚ØĩŲŠØąØŠ ØŦØ¯Ų‹Ø§ ؈ØĒØĒØˇŲ„Ø¨ Ø§Ų‚ØĒØ¨Ø§ØŗØ§ØĒ: %s</string>
<string name="revanced_hide_keyword_toast_invalid_broad">Ø§Ų„ŲƒŲ„Ų…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ ØŗŲˆŲ ØĒØŽŲŲŠ ØŦŲ…ŲŠØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ: %s</string>
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
<string name="revanced_hide_general_ads_title">ØĨØŽŲØ§ØĄ Ø§Ų„ØĨØšŲ„Ø§Ų†Ø§ØĒ Ø§Ų„ØšØ§Ų…ØŠ</string> <string name="revanced_hide_general_ads_title">ØĨØŽŲØ§ØĄ Ø§Ų„ØĨØšŲ„Ø§Ų†Ø§ØĒ Ø§Ų„ØšØ§Ų…ØŠ</string>
@@ -612,6 +630,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_shorts_save_sound_button_title">ØĨØŽŲØ§ØĄ Ø­ŲØ¸ Ø§Ų„Øĩ؈ØĒ ØĨŲ„Ų‰ Ø˛Øą Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„</string> <string name="revanced_hide_shorts_save_sound_button_title">ØĨØŽŲØ§ØĄ Ø­ŲØ¸ Ø§Ų„Øĩ؈ØĒ ØĨŲ„Ų‰ Ø˛Øą Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„</string>
<string name="revanced_hide_shorts_save_sound_button_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø­ŲØ¸ Ø§Ų„Øĩ؈ØĒ ؁؊ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„</string> <string name="revanced_hide_shorts_save_sound_button_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø­ŲØ¸ Ø§Ų„Øĩ؈ØĒ ؁؊ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„</string>
<string name="revanced_hide_shorts_save_sound_button_summary_off">؊ØĒŲ… ØšØąØļ Ø­ŲØ¸ Ø§Ų„Øĩ؈ØĒ ؁؊ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„</string> <string name="revanced_hide_shorts_save_sound_button_summary_off">؊ØĒŲ… ØšØąØļ Ø­ŲØ¸ Ø§Ų„Øĩ؈ØĒ ؁؊ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„</string>
<string name="revanced_hide_shorts_use_this_sound_button_title">ØĨØŽŲØ§ØĄ Ø˛Øą Ø§ØŗØĒØŽØ¯Ø§Ų… Ų‡Ø°Ø§ Ø§Ų„Øĩ؈ØĒ</string>
<string name="revanced_hide_shorts_use_this_sound_button_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø˛Øą Ø§ØŗØĒØŽØ¯Ø§Ų… Ų‡Ø°Ø§ Ø§Ų„Øĩ؈ØĒ</string>
<string name="revanced_hide_shorts_use_this_sound_button_summary_off">؊ØĒŲ… ØšØąØļ Ø˛Øą Ø§ØŗØĒØŽØ¯Ø§Ų… Ų‡Ø°Ø§ Ø§Ų„Øĩ؈ØĒ</string>
<string name="revanced_hide_shorts_search_suggestions_title">ØĨØŽŲØ§ØĄ Ø§Ų‚ØĒØąØ§Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ</string> <string name="revanced_hide_shorts_search_suggestions_title">ØĨØŽŲØ§ØĄ Ø§Ų‚ØĒØąØ§Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_shorts_search_suggestions_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø§Ų‚ØĒØąØ§Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ</string> <string name="revanced_hide_shorts_search_suggestions_summary_on">ØĒŲ… ØĨØŽŲØ§ØĄ Ø§Ų‚ØĒØąØ§Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ</string>
<string name="revanced_hide_shorts_search_suggestions_summary_off">؊ØĒŲ… ØšØąØļ Ø§Ų‚ØĒØąØ§Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ</string> <string name="revanced_hide_shorts_search_suggestions_summary_off">؊ØĒŲ… ØšØąØļ Ø§Ų‚ØĒØąØ§Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ</string>
@@ -675,7 +696,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_player_overlay_opacity_invalid_toast">Ø´ŲØ§ŲŲŠØŠ ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…Ø´ØēŲ„ ؊ØŦب ØŖŲ† ØĒŲƒŲˆŲ† Ø¨ŲŠŲ† 0-100</string> <string name="revanced_player_overlay_opacity_invalid_toast">Ø´ŲØ§ŲŲŠØŠ ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…Ø´ØēŲ„ ؊ØŦب ØŖŲ† ØĒŲƒŲˆŲ† Ø¨ŲŠŲ† 0-100</string>
</patch> </patch>
<patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch"> <patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch">
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Ų…ØŽŲŲŠ</string>
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<string name="revanced_ryd_failure_connection_timeout">Ų„Ų… ŲŠØšØŦØ¨Ų†ŲŠ ØēŲŠØą Ų…ØĒاح Ų…Ø¤Ų‚ØĒŲ‹Ø§ (Ø§Ų†ØĒŲ‡ØĒ Ų…Ų‡Ų„ØŠ API)</string> <string name="revanced_ryd_failure_connection_timeout">Ų„Ų… ŲŠØšØŦØ¨Ų†ŲŠ ØēŲŠØą Ų…ØĒاح Ų…Ø¤Ų‚ØĒŲ‹Ø§ (Ø§Ų†ØĒŲ‡ØĒ Ų…Ų‡Ų„ØŠ API)</string>
<string name="revanced_ryd_failure_connection_status_code">Ų„Ų… ŲŠØšØŦØ¨Ų†ŲŠ ØēŲŠØą Ų…ØĒاح (Ø§Ų„Ø­Ø§Ų„ØŠ %d)</string> <string name="revanced_ryd_failure_connection_status_code">Ų„Ų… ŲŠØšØŦØ¨Ų†ŲŠ ØēŲŠØą Ų…ØĒاح (Ø§Ų„Ø­Ø§Ų„ØŠ %d)</string>
@@ -771,6 +791,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_general_skipcount_sum_off">ØĒŲ… ØĒØšØˇŲŠŲ„ ØĒØĒبؚ Ų…ØąØ§ØĒ Ø§Ų„ØĒØŽØˇŲŠ</string> <string name="revanced_sb_general_skipcount_sum_off">ØĒŲ… ØĒØšØˇŲŠŲ„ ØĒØĒبؚ Ų…ØąØ§ØĒ Ø§Ų„ØĒØŽØˇŲŠ</string>
<string name="revanced_sb_general_min_duration">Ø§Ų„Ø­Ø¯ Ø§Ų„ØŖØ¯Ų†Ų‰ Ų„Ų…Ø¯ØŠ Ø§Ų„Ų…Ų‚ØˇØš</string> <string name="revanced_sb_general_min_duration">Ø§Ų„Ø­Ø¯ Ø§Ų„ØŖØ¯Ų†Ų‰ Ų„Ų…Ø¯ØŠ Ø§Ų„Ų…Ų‚ØˇØš</string>
<string name="revanced_sb_general_min_duration_sum">Ų„Ų† ؊ØĒŲ… ØšØąØļ Ø§Ų„Ų…Ų‚Ø§ØˇØš Ø§Ų„ØŖŲ‚ØĩØą Ų…Ų† Ų‡Ø°Ų‡ Ø§Ų„Ų‚ŲŠŲ…ØŠ (Ø¨Ø§Ų„ØĢŲˆØ§Ų†ŲŠ) ØŖŲˆ ØĒØŽØˇŲŠŲ‡Ø§</string> <string name="revanced_sb_general_min_duration_sum">Ų„Ų† ؊ØĒŲ… ØšØąØļ Ø§Ų„Ų…Ų‚Ø§ØˇØš Ø§Ų„ØŖŲ‚ØĩØą Ų…Ų† Ų‡Ø°Ų‡ Ø§Ų„Ų‚ŲŠŲ…ØŠ (Ø¨Ø§Ų„ØĢŲˆØ§Ų†ŲŠ) ØŖŲˆ ØĒØŽØˇŲŠŲ‡Ø§</string>
<string name="revanced_sb_general_min_duration_invalid">Ø§Ų„Ų…Ø¯ØŠ Ø§Ų„Ø˛Ų…Ų†ŲŠØŠ ØēŲŠØą ØĩØ§Ų„Ø­ØŠ</string>
<string name="revanced_sb_general_uuid">Ų…ØšØąŲ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø§Ų„ŲØąŲŠØ¯ Ø§Ų„ØŽØ§Øĩ Ø¨Ųƒ</string> <string name="revanced_sb_general_uuid">Ų…ØšØąŲ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø§Ų„ŲØąŲŠØ¯ Ø§Ų„ØŽØ§Øĩ Ø¨Ųƒ</string>
<string name="revanced_sb_general_uuid_sum">؊ØŦب ØŖŲ† ŲŠØ¨Ų‚Ų‰ Ų‡Ø°Ø§ ؎اØĩŲ‹Ø§. Ø§Ų†Ų‡ Ų…ØĢŲ„ ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ØąŲˆØą ŲˆŲ„Ø§ ŲŠŲ†Ø¨Øē؊ Ų…Ø´Ø§ØąŲƒØĒŲ‡ Ų…Øš ØŖŲŠ Ø´ØŽØĩ. ØĨذا ŲƒØ§Ų† Ø´ØŽØĩ Ų…Ø§ ŲŠŲ…Ų„Ųƒ Ų‡Ø°Ø§ØŒ ŲŲŠŲ…ŲƒŲ†Ų‡ Ø§Ų†ØĒØ­Ø§Ų„ Ø´ØŽØĩ؊ØĒ؃</string> <string name="revanced_sb_general_uuid_sum">؊ØŦب ØŖŲ† ŲŠØ¨Ų‚Ų‰ Ų‡Ø°Ø§ ؎اØĩŲ‹Ø§. Ø§Ų†Ų‡ Ų…ØĢŲ„ ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ØąŲˆØą ŲˆŲ„Ø§ ŲŠŲ†Ø¨Øē؊ Ų…Ø´Ø§ØąŲƒØĒŲ‡ Ų…Øš ØŖŲŠ Ø´ØŽØĩ. ØĨذا ŲƒØ§Ų† Ø´ØŽØĩ Ų…Ø§ ŲŠŲ…Ų„Ųƒ Ų‡Ø°Ø§ØŒ ŲŲŠŲ…ŲƒŲ†Ų‡ Ø§Ų†ØĒØ­Ø§Ų„ Ø´ØŽØĩ؊ØĒ؃</string>
<string name="revanced_sb_general_uuid_invalid">؊ØŦب ØŖŲ† ŲŠŲƒŲˆŲ† Ų…ØšØąŲ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø§Ų„ØŽØ§Øĩ 30 Ø­ØąŲŲ‹Ø§ ØšŲ„Ų‰ Ø§Ų„ØŖŲ‚Ų„</string> <string name="revanced_sb_general_uuid_invalid">؊ØŦب ØŖŲ† ŲŠŲƒŲˆŲ† Ų…ØšØąŲ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø§Ų„ØŽØ§Øĩ 30 Ø­ØąŲŲ‹Ø§ ØšŲ„Ų‰ Ø§Ų„ØŖŲ‚Ų„</string>
@@ -871,8 +892,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_new_segment_time_start">Ø§Ų„ŲˆŲ‚ØĒ Ø§Ų„Ø°ŲŠ ŲŠØ¨Ø¯ØŖ ØšŲ†Ø¯Ų‡ Ø§Ų„Ų…Ų‚ØˇØš</string> <string name="revanced_sb_new_segment_time_start">Ø§Ų„ŲˆŲ‚ØĒ Ø§Ų„Ø°ŲŠ ŲŠØ¨Ø¯ØŖ ØšŲ†Ø¯Ų‡ Ø§Ų„Ų…Ų‚ØˇØš</string>
<string name="revanced_sb_new_segment_time_end">Ø§Ų„ŲˆŲ‚ØĒ Ø§Ų„Ø°ŲŠ ŲŠŲ†ØĒŲ‡ŲŠ ØšŲ†Ø¯Ų‡ Ø§Ų„Ų…Ų‚ØˇØš</string> <string name="revanced_sb_new_segment_time_end">Ø§Ų„ŲˆŲ‚ØĒ Ø§Ų„Ø°ŲŠ ŲŠŲ†ØĒŲ‡ŲŠ ØšŲ†Ø¯Ų‡ Ø§Ų„Ų…Ų‚ØˇØš</string>
<string name="revanced_sb_new_segment_confirm_title">Ų‡Ų„ Ø§Ų„ØŖŲˆŲ‚Ø§ØĒ ØĩØ­ŲŠØ­ØŠØŸ</string> <string name="revanced_sb_new_segment_confirm_title">Ų‡Ų„ Ø§Ų„ØŖŲˆŲ‚Ø§ØĒ ØĩØ­ŲŠØ­ØŠØŸ</string>
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<string name="revanced_sb_new_segment_confirm_content">Ø§Ų„Ų…Ų‚ØˇØš Ų…Ų†\n\n%1$s\nto\n%2$s\n\n(%3$s)\n\nReady to ØŦØ§Ų‡Ø˛ Ų„Ų„ØĨØąØŗØ§Ų„ØŸ</string> <string name="revanced_sb_new_segment_confirm_content">Ø§Ų„Ų…Ų‚ØˇØš Ų…Ų†\n\n%1$s\nto\n%2$s\n\n(%3$s)\n\nReady to ØŦØ§Ų‡Ø˛ Ų„Ų„ØĨØąØŗØ§Ų„ØŸ</string>
<string name="revanced_sb_new_segment_start_is_before_end">؊ØŦب ØŖŲ† ØĒŲƒŲˆŲ† Ø§Ų„Ø¨Ø¯Ø§ŲŠØŠ Ų‚Ø¨Ų„ Ø§Ų„Ų†Ų‡Ø§ŲŠØŠ</string> <string name="revanced_sb_new_segment_start_is_before_end">؊ØŦب ØŖŲ† ØĒŲƒŲˆŲ† Ø§Ų„Ø¨Ø¯Ø§ŲŠØŠ Ų‚Ø¨Ų„ Ø§Ų„Ų†Ų‡Ø§ŲŠØŠ</string>
<string name="revanced_sb_new_segment_mark_locations_first">ØļØš ØšŲ„Ø§Ų…ØŠ ØšŲ„Ų‰ Ų…ŲˆŲ‚ØšŲŠŲ† ؁؊ Ø´ØąŲŠØˇ Ø§Ų„ŲˆŲ‚ØĒ ØŖŲˆŲ„Ų‹Ø§</string> <string name="revanced_sb_new_segment_mark_locations_first">ØļØš ØšŲ„Ø§Ų…ØŠ ØšŲ„Ų‰ Ų…ŲˆŲ‚ØšŲŠŲ† ؁؊ Ø´ØąŲŠØˇ Ø§Ų„ŲˆŲ‚ØĒ ØŖŲˆŲ„Ų‹Ø§</string>
@@ -891,6 +910,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_stats_username_changed">ØĒŲ… ØĒØēŲŠŲŠØą Ø§ØŗŲ… Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø¨Ų†ØŦاح</string> <string name="revanced_sb_stats_username_changed">ØĒŲ… ØĒØēŲŠŲŠØą Ø§ØŗŲ… Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø¨Ų†ØŦاح</string>
<string name="revanced_sb_stats_reputation">ØŗŲ…ØšØĒ؃ Ų‡ŲŠ &lt;b&gt;%.2f&lt;/b&gt;</string> <string name="revanced_sb_stats_reputation">ØŗŲ…ØšØĒ؃ Ų‡ŲŠ &lt;b&gt;%.2f&lt;/b&gt;</string>
<string name="revanced_sb_stats_submissions">Ų„Ų‚Ø¯ ØŖŲ†Ø´ØŖØĒ &lt;b&gt;%s&lt;/b&gt; Ų…Ų‚ØˇØš</string> <string name="revanced_sb_stats_submissions">Ų„Ų‚Ø¯ ØŖŲ†Ø´ØŖØĒ &lt;b&gt;%s&lt;/b&gt; Ų…Ų‚ØˇØš</string>
<string name="revanced_sb_stats_submissions_sum">اØļØēØˇ Ų‡Ų†Ø§ Ų„ØšØąØļ Ø§Ų„Ų…Ų‚Ø§ØˇØš Ø§Ų„ØŽØ§ØĩØŠ Ø¨Ųƒ</string>
<string name="revanced_sb_stats_saved_zero">Ų…ØĒØĩØ¯ØąŲŠŲ† SponsorBlock</string> <string name="revanced_sb_stats_saved_zero">Ų…ØĒØĩØ¯ØąŲŠŲ† SponsorBlock</string>
<string name="revanced_sb_stats_saved">Ų„Ų‚Ø¯ Ų‚Ų…ØĒ Ø¨Ø­ŲØ¸ Ø§Ų„Ų†Ø§Øŗ Ų…Ų† &lt;b&gt;%s&lt;/b&gt; Ų…Ų‚ØˇØš</string> <string name="revanced_sb_stats_saved">Ų„Ų‚Ø¯ Ų‚Ų…ØĒ Ø¨Ø­ŲØ¸ Ø§Ų„Ų†Ø§Øŗ Ų…Ų† &lt;b&gt;%s&lt;/b&gt; Ų…Ų‚ØˇØš</string>
<string name="revanced_sb_stats_saved_sum_zero">اØļØēØˇ Ų‡Ų†Ø§ Ų„ØąØ¤ŲŠØŠ Ø§Ų„ØĨØ­ØĩاØĻŲŠØ§ØĒ Ø§Ų„ØšØ§Ų„Ų…ŲŠØŠ ŲˆØŖØ¨ØąØ˛ Ø§Ų„Ų…ØŗØ§Ų‡Ų…ŲŠŲ†</string> <string name="revanced_sb_stats_saved_sum_zero">اØļØēØˇ Ų‡Ų†Ø§ Ų„ØąØ¤ŲŠØŠ Ø§Ų„ØĨØ­ØĩاØĻŲŠØ§ØĒ Ø§Ų„ØšØ§Ų„Ų…ŲŠØŠ ŲˆØŖØ¨ØąØ˛ Ø§Ų„Ų…ØŗØ§Ų‡Ų…ŲŠŲ†</string>
@@ -923,7 +943,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_spoof_app_version_target_entry_2">18.20.39 - Ø§ØŗØĒؚاد؊ ØŗØąØšØŠ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„ŲˆØ§ØŗØšØŠ &amp; Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØŦŲˆØ¯ØŠ</string> <string name="revanced_spoof_app_version_target_entry_2">18.20.39 - Ø§ØŗØĒؚاد؊ ØŗØąØšØŠ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„ŲˆØ§ØŗØšØŠ &amp; Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØŦŲˆØ¯ØŠ</string>
<string name="revanced_spoof_app_version_target_entry_3">18.09.39 - Ø§ØŗØĒؚاد؊ ØšŲ„Ø§Ų…ØŠ ØĒØ¨ŲˆŲŠØ¨ Ø§Ų„Ų…ŲƒØĒب؊</string> <string name="revanced_spoof_app_version_target_entry_3">18.09.39 - Ø§ØŗØĒؚاد؊ ØšŲ„Ø§Ų…ØŠ ØĒØ¨ŲˆŲŠØ¨ Ø§Ų„Ų…ŲƒØĒب؊</string>
<string name="revanced_spoof_app_version_target_entry_4">17.41.37 - Ø§ØŗØĒؚاد؊ ØąŲ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų‚Ø¯ŲŠŲ…</string> <string name="revanced_spoof_app_version_target_entry_4">17.41.37 - Ø§ØŗØĒؚاد؊ ØąŲ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų‚Ø¯ŲŠŲ…</string>
<string name="revanced_spoof_app_version_target_entry_5">17.30.34 - Ø§ØŗØĒؚاد؊ ØĒØĩŲ…ŲŠŲ… ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø§Ų„Ų‚Ø¯ŲŠŲ…</string> <string name="revanced_spoof_app_version_target_entry_5">17.33.42 - Ø§ØŗØĒؚاد؊ ØĒØĩŲ…ŲŠŲ… ŲˆØ§ØŦŲ‡ØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ø§Ų„Ų‚Ø¯ŲŠŲ…</string>
</patch> </patch>
<patch id="layout.startpage.ChangeStartPagePatch"> <patch id="layout.startpage.ChangeStartPagePatch">
<string name="revanced_start_page_title">ØĒØšŲŠŲŠŲ† ØĩŲØ­ØŠ Ø§Ų„Ø¨Ø¯Ø§ŲŠØŠ</string> <string name="revanced_start_page_title">ØĒØšŲŠŲŠŲ† ØĩŲØ­ØŠ Ø§Ų„Ø¨Ø¯Ø§ŲŠØŠ</string>
@@ -1033,6 +1053,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_announcements_connection_failed">ŲØ´Ų„ Ø§Ų„Ø§ØĒØĩØ§Ų„ Ø¨Ų…ŲˆŲØą Ø§Ų„ØĨØšŲ„Ø§Ų†Ø§ØĒ</string> <string name="revanced_announcements_connection_failed">ŲØ´Ų„ Ø§Ų„Ø§ØĒØĩØ§Ų„ Ø¨Ų…ŲˆŲØą Ø§Ų„ØĨØšŲ„Ø§Ų†Ø§ØĒ</string>
<string name="revanced_announcements_dialog_dismiss">ØĒØŦØ§Ų‡Ų„</string> <string name="revanced_announcements_dialog_dismiss">ØĒØŦØ§Ų‡Ų„</string>
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">ØĒØ­Ø°ŲŠØą</string>
<string name="revanced_check_watch_history_domain_name_dialog_message">Ų„Ų… ؊ØĒŲ… Ø­ŲØ¸ ØŗØŦŲ„ Ø§Ų„Ų…Ø´Ø§Ų‡Ø¯ØŠ Ø§Ų„ØŽØ§Øĩ Ø¨Ųƒ.&lt;br&gt;&lt;br&gt;Ų…Ų† Ø§Ų„Ų…ØąØŦØ­ ØŖŲ† ŲŠŲƒŲˆŲ† Ø§Ų„ØŗØ¨Ø¨ ؁؊ Ø°Ų„Ųƒ Ų‡Ųˆ Ų…Ø§Ų†Øš ØĨØšŲ„Ø§Ų†Ø§ØĒ DNS ØŖŲˆ ŲˆŲƒŲŠŲ„ Ø§Ų„Ø´Ø¨ŲƒØŠ.&lt;br&gt;&lt;br&gt;Ų„ØĨØĩŲ„Ø§Ø­ Ų‡Ø°Ų‡ Ø§Ų„Ų…Ø´ŲƒŲ„ØŠØŒ Ų‚Ų… بØĨØļØ§ŲØŠ &lt;b&gt;s.youtube.com&lt;/b&gt; ØĨŲ„Ų‰ Ø§Ų„Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„Ø¨ŲŠØļØ§ØĄ ØŖŲˆ Ų‚Ų… بØĨŲŠŲ‚Ø§Ų ØĒØ´ØēŲŠŲ„ ØŦŲ…ŲŠØš ØŖØ¯ŲˆØ§ØĒ Ø­Ø¸Øą DNS ŲˆŲˆŲƒŲ„Ø§ØĄ Ø§Ų„Ø¨ØąŲˆŲƒØŗŲŠ.</string>
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Ų„Ø§ ØĒØšØąØļ Ų…ØąØŠ ØŖØŽØąŲ‰</string>
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
<string name="revanced_auto_repeat_title">ØĒŲ…ŲƒŲŠŲ† Ø§Ų„ØĒŲƒØąØ§Øą Ø§Ų„ØĒŲ„Ų‚Ø§ØĻ؊</string> <string name="revanced_auto_repeat_title">ØĒŲ…ŲƒŲŠŲ† Ø§Ų„ØĒŲƒØąØ§Øą Ø§Ų„ØĒŲ„Ų‚Ø§ØĻ؊</string>
<string name="revanced_auto_repeat_summary_on">ØĒŲ… ØĒŲ…ŲƒŲŠŲ† Ø§Ų„ØĒŲƒØąØ§Øą Ø§Ų„ØĒŲ„Ų‚Ø§ØĻ؊</string> <string name="revanced_auto_repeat_summary_on">ØĒŲ… ØĒŲ…ŲƒŲŠŲ† Ø§Ų„ØĒŲƒØąØ§Øą Ø§Ų„ØĒŲ„Ų‚Ø§ØĻ؊</string>
@@ -1107,21 +1132,23 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_slide_to_seek_summary_on">ØĒŲ… ØĒŲ…ŲƒŲŠŲ† Slide to Seek</string> <string name="revanced_slide_to_seek_summary_on">ØĒŲ… ØĒŲ…ŲƒŲŠŲ† Slide to Seek</string>
<string name="revanced_slide_to_seek_summary_off">ØĒŲ… ØĒØšØˇŲŠŲ„ Slide to Seek</string> <string name="revanced_slide_to_seek_summary_off">ØĒŲ… ØĒØšØˇŲŠŲ„ Slide to Seek</string>
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
<string name="revanced_spoof_client_screen_title">Spoof Client</string> <string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
<string name="revanced_spoof_client_screen_summary">Ų…Ø­Ø§ŲƒØ§ØŠ Ø§Ų„ØšŲ…ŲŠŲ„ Ų„Ų…Ų†Øš Ų…Ø´ŲƒŲ„Ø§ØĒ Ø§Ų„ØĒØ´ØēŲŠŲ„</string> <string name="revanced_spoof_video_streams_screen_summary">ØĒØ˛ŲŠŲŠŲ ØĒØ¯ŲŲ‚Ø§ØĒ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„ØŽØ§ØĩØŠ Ø¨Ø§Ų„ØšŲ…ŲŠŲ„ Ų„Ų…Ų†Øš Ø­Ø¯ŲˆØĢ Ų…Ø´ŲƒŲ„Ø§ØĒ ØŖØĢŲ†Ø§ØĄ Ø§Ų„ØĒØ´ØēŲŠŲ„</string>
<string name="revanced_spoof_client_title">Spoof Client</string> <string name="revanced_spoof_video_streams_title">Spoof Video Streams</string>
<string name="revanced_spoof_client_summary_on">؊ØĒŲ… Ų…Ø­Ø§ŲƒØ§ØŠ Ø§Ų„ØšŲ…ŲŠŲ„</string> <string name="revanced_spoof_video_streams_summary_on">؊ØĒŲ… ØĒØ˛ŲŠŲŠŲ ØĒØ¯ŲŲ‚Ø§ØĒ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_spoof_client_summary_off">Ų„Ø§ ؊ØĒŲ… Ų…Ø­Ø§ŲƒØ§ØŠ Ø§Ų„ØšŲ…ŲŠŲ„\n\nŲ‚Ø¯ Ų„Ø§ ŲŠØšŲ…Ų„ ØĒØ´ØēŲŠŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string> <string name="revanced_spoof_video_streams_summary_off">Ų„Ø§ ؊ØĒŲ… ØĒØ˛ŲŠŲŠŲ ØĒØ¯ŲŲ‚Ø§ØĒ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ\n\nŲ‚Ø¯ Ų„Ø§ ŲŠØšŲ…Ų„ ØĒØ´ØēŲŠŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ</string>
<string name="revanced_spoof_client_user_dialog_message">ØĨŲŠŲ‚Ø§Ų ØĒØ´ØēŲŠŲ„ Ų‡Ø°Ø§ Ø§Ų„ØĨؚداد Ų‚Ø¯ ŲŠØŗØ¨Ø¨ Ų…Ø´Ø§ŲƒŲ„ ؁؊ ØĒØ´ØēŲŠŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ.</string> <string name="revanced_spoof_video_streams_user_dialog_message">ØĨŲŠŲ‚Ø§Ų ØĒØ´ØēŲŠŲ„ Ų‡Ø°Ø§ Ø§Ų„ØĨؚداد Ų‚Ø¯ ŲŠØŗØ¨Ø¨ Ų…Ø´Ø§ŲƒŲ„ ؁؊ ØĒØ´ØēŲŠŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ.</string>
<string name="revanced_spoof_client_use_ios_title">Spoof Client to iOS</string> <string name="revanced_spoof_video_streams_client_type_title">Ø§Ų„ØšŲ…ŲŠŲ„ Ø§Ų„Ø§ŲØĒØąØ§Øļ؊</string>
<string name="revanced_spoof_client_use_ios_summary_on">Ø§Ų„ØšŲ…ŲŠŲ„ Ų…ØąØŗŲ„ Ø­Ø§Ų„ŲŠØ§Ų‹ ØĨŲ„Ų‰ iOS\n\nØ§Ų„ØĸØĢØ§Øą Ø§Ų„ØŦØ§Ų†Ø¨ŲŠØŠ ØĒØ´Ų…Ų„:\nâ€ĸ Ų„Ø§ ؊؈ØŦد HDR ŲŲŠØ¯ŲŠŲˆ\nâ€ĸ Ų‚Ø¯ ØĒŲƒŲˆŲ† ØŦŲˆØ¯ØŠ ŲŲŠØ¯ŲŠŲˆ ØŖØšŲ„Ų‰ Ų…ŲŲ‚ŲˆØ¯ØŠ\nâ€ĸ Ų„Ø§ ŲŠŲ…ŲƒŲ† ØĒØ´ØēŲŠŲ„ Ø§Ų„Ø¨ØĢ Ø§Ų„Ų…Ø¨Ø§Ø´Øą Ų„Ų„Øĩ؈ØĒ ŲŲ‚Øˇ</string> <string name="revanced_spoof_video_streams_ios_force_avc_title">ŲØąØļ AVC (H.264)</string>
<string name="revanced_spoof_client_use_ios_summary_off">Ø§Ų„ØšŲ…ŲŠŲ„ Ų…ØšØˇŲˆØ¨ Ø­Ø§Ų„ŲŠØ§Ų‹ ØĨŲ„Ų‰ ØŖŲ†Ø¯ØąŲˆŲŠØ¯ VR\n\nØ§Ų„ØĸØĢØ§Øą Ø§Ų„ØŦØ§Ų†Ø¨ŲŠØŠ ØĒØ´Ų…Ų„:\nâ€ĸ Ų„Ø§ ؊؈ØŦد ŲŲŠØ¯ŲŠŲˆ HDR\nâ€ĸ ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ Ø§Ų„ØŖØˇŲØ§Ų„ Ų„Ø§ ؊ØĒŲ… ØĒØ´ØēŲŠŲ„Ų‡Ų…\nâ€ĸ Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„Ų…ŲˆŲ‚ŲˆŲØŠ ŲŠŲ…ŲƒŲ† ØŖŲ† ØĒØŗØĒØŖŲ†Ų ØšØ´ŲˆØ§ØĻŲŠØ§Ų‹\nâ€ĸ ØŦŲˆØ¯ØŠ Ų…Ų†ØŽŲØļØŠ Ų„ØĩŲˆØą Ų…ØĩØēØąØŠ Ø´ØąŲŠØˇ Ø§Ų„Ø¨Ø­ØĢ\nâ€ĸ Ø˛Øą Ø§Ų„ØĒØ­Ų…ŲŠŲ„ Ų…ØŽŲŲŠ\nâ€ĸ Ø¨ØˇØ§Ų‚Ø§ØĒ ØĨŲ†Ų‡Ø§ØĄ Ø§Ų„Ø´Ø§Ø´ØŠ Ų…ØŽŲŲŠØŠ</string> <string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ØĒØąŲ…ŲŠØ˛ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų‡Ųˆ AVC (H.264)</string>
<string name="revanced_spoof_client_storyboard_timeout">Ų…Ø­Ø§ŲƒØ§ØŠ Ų…ØĩØēØąØ§ØĒ Ø§Ų„ØšŲ…ŲŠŲ„ ØēŲŠØą Ų…ØĒŲˆŲØąØŠ (Ø§Ų†ØĒŲ‡ØĒ Ų…Ų‡Ų„ØŠ API)</string> <string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ØĒØąŲ…ŲŠØ˛ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų‡Ųˆ VP9 ØŖŲˆ AV1</string>
<string name="revanced_spoof_client_storyboard_io_exception">Ų…Ø­Ø§ŲƒØ§ØŠ Ų…ØĩØēØąØ§ØĒ Ø§Ų„ØšŲ…ŲŠŲ„ ØēŲŠØą Ų…ØĒŲˆŲØąØŠ Ų…Ø¤Ų‚ØĒŲ‹Ø§: %s</string> <string name="revanced_spoof_video_streams_ios_force_avc_no_hardware_vp9_summary_on">Ų„Ø§ ŲŠØ­ØĒ؈؊ ØŦŲ‡Ø§Ø˛Ųƒ ØšŲ„Ų‰ ؁؃ ØĒØ´ŲŲŠØą Ø§Ų„ØŖØŦŲ‡Ø˛ØŠ VP9، ŲˆŲ‡Ø°Ø§ Ø§Ų„ØĨؚداد ŲŠØšŲ…Ų„ داØĻŲ…Ø§ ØšŲ†Ø¯ ØĒŲ…ŲƒŲŠŲ† ØĒØ˛ŲŠŲŠŲ Ø§Ų„ØšŲ…ŲŠŲ„</string>
</patch> <string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">Ų‚Ø¯ ŲŠØ¤Ø¯ŲŠ ØĒŲ…ŲƒŲŠŲ† Ų‡Ø°Ø§ ØĨŲ„Ų‰ ØĒØ­ØŗŲŠŲ† ØšŲ…Øą Ø§Ų„Ø¨ØˇØ§ØąŲŠØŠ ؈ØĨØĩŲ„Ø§Ø­ Ų…Ø´ŲƒŲ„ØŠ ØĒŲ‚ØˇŲŠØš Ø§Ų„ØĒØ´ØēŲŠŲ„.\n\n؊ØĒŲ…ØĒØš ØĒŲ†ØŗŲŠŲ‚ AVC Ø¨Ø¯Ų‚ØŠ Ų‚ØĩŲˆŲ‰ ØĒØ¨Ų„Øē 1080P، ŲˆØŗŲŠØŗØĒØŽØ¯Ų… ØĒØ´ØēŲŠŲ„ Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„Ų…Ø˛ŲŠØ¯ Ų…Ų† Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„ØĨŲ†ØĒØąŲ†ØĒ Ų…Ų‚Ø§ØąŲ†ØŠŲ‹ بØĒŲ†ØŗŲŠŲ‚ VP9 ØŖŲˆ AV1.</string>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. --> <string name="revanced_spoof_video_streams_about_ios_title">Ø§Ų„ØĒØŖØĢŲŠØąØ§ØĒ Ø§Ų„ØŦØ§Ų†Ø¨ŲŠØŠ Ų„Ų…Ø­Ø§ŲƒØ§ØŠ iOS</string>
<patch id="misc.fix.playback.SpoofSignaturePatch"> <string name="revanced_spoof_video_streams_about_ios_summary">â€ĸ Ų‚Ø¯ Ų„Ø§ ؊ØĒŲ… ØĒØ´ØēŲŠŲ„ Ø§Ų„ØŖŲŲ„Ø§Ų… ØŖŲˆ Ø§Ų„ŲŲŠØ¯ŲŠŲˆŲ‡Ø§ØĒ Ø§Ų„Ų…Ø¯ŲŲˆØšØŠ\nâ€ĸ ŲŠØ¨Ø¯ØŖ Ø§Ų„Ø¨ØĢ Ø§Ų„Ų…Ø¨Ø§Ø´Øą Ų…Ų† Ø§Ų„Ø¨Ø¯Ø§ŲŠØŠ</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Ø§Ų„ØĒØŖØĢŲŠØąØ§ØĒ Ø§Ų„ØŦØ§Ų†Ø¨ŲŠØŠ Ų„Ų…Ø­Ø§ŲƒØ§ØŠ Android VR</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">â€ĸ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„Ų…Ų‚ØˇØš Ø§Ų„Øĩ؈ØĒ؊ Ų…ŲŲ‚ŲˆØ¯ØŠ</string>
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

View File

@@ -32,15 +32,16 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<!-- Settings about dialog. -->
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
</patch> </patch>
<patch id="misc.debugging.DebuggingPatch"> <patch id="misc.debugging.DebuggingPatch">
@@ -57,7 +58,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. --> <!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
@@ -171,8 +172,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<patch id="layout.sponsorblock.SponsorBlockResourcePatch"> <patch id="layout.sponsorblock.SponsorBlockResourcePatch">
<!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' --> <!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' -->
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<!-- Shown in the settings preferences, and translations can be any text length. --> <!-- Shown in the settings preferences, and translations can be any text length. -->
</patch> </patch>
<patch id="layout.spoofappversion.SpoofAppVersionPatch"> <patch id="layout.spoofappversion.SpoofAppVersionPatch">
@@ -206,6 +205,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
<patch id="misc.announcements.AnnouncementsPatch"> <patch id="misc.announcements.AnnouncementsPatch">
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
</patch> </patch>
<patch id="misc.dimensions.spoof.SpoofDeviceDimensionsPatch"> <patch id="misc.dimensions.spoof.SpoofDeviceDimensionsPatch">
@@ -232,10 +233,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
<patch id="interaction.seekbar.EnableSlideToSeekPatch"> <patch id="interaction.seekbar.EnableSlideToSeekPatch">
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
</patch>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. -->
<patch id="misc.fix.playback.SpoofSignaturePatch">
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

View File

@@ -32,6 +32,17 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
<string name="revanced_check_environment_failed_title">Yoxlamalar uğursuz oldu</string>
<string name="revanced_check_environment_dialog_open_official_source_button">Xidməti veb saytÄą aç</string>
<string name="revanced_check_environment_dialog_ignore_button">Yan keç</string>
<string name="revanced_check_environment_failed_message">&lt;h5&gt;Bu tətbiq sizin tərəfinizdən yamaqlanmayÄąb.&lt;/h5&gt;&lt;br&gt;Bu tətbiq dÃŧzgÃŧn işləməyə bilər, &lt;b&gt;istifadə etmək zərərli və ya hətta təhlÃŧkəli ola bilər&lt;/b&gt;.&lt;br&gt;&lt;br&gt;&lt;br&gt;Bu yoxlamalar bu tətbiqin əvvəldən yamaqlandığınÄą və ya başqasÄąndan əldə edildiyini gÃļstərir:&lt;br&gt;&lt;br&gt;&lt;small&gt;%1$s&lt;/small&gt;&lt;br&gt; &lt;br&gt;onu silməyiniz və ÃļzÃŧnÃŧz yamaqlamağınÄąz tÃļvsiyə olunur. &lt;/b&gt;təsdiqlənmiş və təhlÃŧkəsiz tətbiq istifadə etdiyinizə əmin olmaq ÃŧçÃŧn. &lt;p&gt;&lt;br&gt; İnkar edilməzsə, bu xəbərdarlÄąq yalnÄąz iki dəfə gÃļstəriləcək.</string>
<string name="revanced_check_environment_not_same_patching_device">Fərqli cihazda yamaqlanıb</string>
<string name="revanced_check_environment_manager_not_expected_installer">ReVanced Manager tərəfindən quraşdÄąrÄąlmayÄąb</string>
<string name="revanced_check_environment_not_near_patch_time">10 dəqiqədən çox əvvəl yamaqlanÄąb</string>
<string name="revanced_check_environment_not_near_patch_time_days">%s gÃŧn əvvəl yamaqlanÄąb</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">APK quruluş tarixi pozulub</string>
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<string name="revanced_settings_confirm_user_dialog_title">Davam etmək istəyirsiniz?</string> <string name="revanced_settings_confirm_user_dialog_title">Davam etmək istəyirsiniz?</string>
<string name="revanced_settings_reset">SÄąfÄąrla</string> <string name="revanced_settings_reset">SÄąfÄąrla</string>
@@ -42,6 +53,14 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_settings_import_reset">ReVanced tənzimləmələr standarta təyin edildi</string> <string name="revanced_settings_import_reset">ReVanced tənzimləmələr standarta təyin edildi</string>
<string name="revanced_settings_import_success">%d tənzimləmə idxal edildi</string> <string name="revanced_settings_import_success">%d tənzimləmə idxal edildi</string>
<string name="revanced_settings_import_failure_parse">Uğursuz idxal prosesi: %s</string> <string name="revanced_settings_import_failure_parse">Uğursuz idxal prosesi: %s</string>
<string name="revanced_pref_import_export_title">İdxal/İxrac et</string>
<string name="revanced_pref_import_export_summary">ReVanced tənzimləmələrin idxal/ixrac et</string>
<!-- Settings about dialog. -->
<string name="revanced_settings_about_links_body">ReVanced Patches &lt;i&gt;%s&lt;/i&gt; versiyasını istifadə edirsiniz</string>
<string name="revanced_settings_about_links_dev_header">Qeyd</string>
<string name="revanced_settings_about_links_dev_body">Bu versiya ilkin buraxÄąlÄąÅŸdÄąr və gÃļzlənilməz problemlərlə Ãŧzləşə bilərsiniz</string>
<string name="revanced_settings_about_links_header">Rəsmi bağlantılar</string>
<string name="revanced_settings_about_links_donate">İanə ver</string>
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
@@ -54,14 +73,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
<string name="revanced_settings_about_links_body">ReVanced Patches &lt;i&gt;%s&lt;/i&gt; versiyasını istifadə edirsiniz</string>
<string name="revanced_settings_about_links_dev_header">Qeyd</string>
<string name="revanced_settings_about_links_dev_body">Bu versiya ilkin buraxÄąlÄąÅŸdÄąr və gÃļzlənilməz problemlərlə Ãŧzləşə bilərsiniz</string>
<string name="revanced_settings_about_links_header">Rəsmi bağlantılar</string>
<string name="revanced_pref_import_export_title">İdxal/İxrac et</string>
<string name="revanced_pref_import_export_summary">ReVanced tənzimləmələrin idxal/ixrac et</string>
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
<string name="revanced_settings_screen_00_about_title">HaqqÄąnda</string> <string name="revanced_settings_screen_00_about_title">HaqqÄąnda</string>
<string name="revanced_settings_screen_01_ads_title">Reklamlar</string> <string name="revanced_settings_screen_01_ads_title">Reklamlar</string>
@@ -145,9 +156,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_community_posts_title">İcma elanların gizlət</string> <string name="revanced_hide_community_posts_title">İcma elanların gizlət</string>
<string name="revanced_hide_community_posts_summary_on">İcma elanları gizlədilib</string> <string name="revanced_hide_community_posts_summary_on">İcma elanları gizlədilib</string>
<string name="revanced_hide_community_posts_summary_off">İcma elanlarÄą gÃļstərilir</string> <string name="revanced_hide_community_posts_summary_off">İcma elanlarÄą gÃļstərilir</string>
<string name="revanced_hide_compact_banner_title">Yığcam bannerləri gizlət</string> <string name="revanced_hide_compact_banner_title">Yığcam etiketləri gizlət</string>
<string name="revanced_hide_compact_banner_summary_on">Yığcam bannerlər gizlidir</string> <string name="revanced_hide_compact_banner_summary_on">Yığcam etiketlər gizlidir</string>
<string name="revanced_hide_compact_banner_summary_off">Yığcam bannerlər gÃļstərilir</string> <string name="revanced_hide_compact_banner_summary_off">Yığcam etiketlər gÃļstərilir</string>
<string name="revanced_hide_movies_section_title">Filmlər bÃļlməsini gizlət</string> <string name="revanced_hide_movies_section_title">Filmlər bÃļlməsini gizlət</string>
<string name="revanced_hide_movies_section_summary_on">Filmlər bÃļlməsi gizlidir</string> <string name="revanced_hide_movies_section_summary_on">Filmlər bÃļlməsi gizlidir</string>
<string name="revanced_hide_movies_section_summary_off">Filmlər bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_movies_section_summary_off">Filmlər bÃļlməsi gÃļstərilir</string>
@@ -184,7 +195,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_related_videos_title">Cəld fəaliyyətlərdə əlaqəli videoları gizlə</string> <string name="revanced_hide_related_videos_title">Cəld fəaliyyətlərdə əlaqəli videoları gizlə</string>
<string name="revanced_hide_related_videos_summary_on">Əlaqədar videolar gizlədilib</string> <string name="revanced_hide_related_videos_summary_on">Əlaqədar videolar gizlədilib</string>
<string name="revanced_hide_related_videos_summary_off">Əlaqədar videolar gÃļstərilir</string> <string name="revanced_hide_related_videos_summary_off">Əlaqədar videolar gÃļstərilir</string>
<string name="revanced_hide_image_shelf_title">AxtarÄąÅŸ nəticələrindəki şəkil bÃļlməsin gizlət</string> <string name="revanced_hide_image_shelf_title">AxtarÄąÅŸ nəticəsində şəkil bÃļlməsin gizlə</string>
<string name="revanced_hide_image_shelf_summary_on">Şəkil bÃļlməsi gizlidir</string> <string name="revanced_hide_image_shelf_summary_on">Şəkil bÃļlməsi gizlidir</string>
<string name="revanced_hide_image_shelf_summary_off">Şəkil bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_image_shelf_summary_off">Şəkil bÃļlməsi gÃļstərilir</string>
<string name="revanced_hide_latest_posts_ads_title">Son elanları gizlət</string> <string name="revanced_hide_latest_posts_ads_title">Son elanları gizlət</string>
@@ -211,6 +222,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_info_cards_section_title">Məlumat kartlarÄą bÃļlməsini gizlət</string> <string name="revanced_hide_info_cards_section_title">Məlumat kartlarÄą bÃļlməsini gizlət</string>
<string name="revanced_hide_info_cards_section_summary_on">Məlumat kartlarÄą bÃļlməsi gizlədilir</string> <string name="revanced_hide_info_cards_section_summary_on">Məlumat kartlarÄą bÃļlməsi gizlədilir</string>
<string name="revanced_hide_info_cards_section_summary_off">Məlumat kartlarÄą bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_info_cards_section_summary_off">Məlumat kartlarÄą bÃļlməsi gÃļstərilir</string>
<string name="revanced_hide_key_concepts_section_title">\"Əsas anlayÄąÅŸlar\" bÃļlməsini gizlət</string>
<string name="revanced_hide_key_concepts_section_summary_on">\"Əsas anlayÄąÅŸlar\" bÃļlməsi gizlidir</string>
<string name="revanced_hide_key_concepts_section_summary_off">\"Əsas anlayÄąÅŸlar\" bÃļlməsi gÃļstərilir</string>
<string name="revanced_hide_transcript_section_title">Transkripsiya bÃļlməsini gizlət</string> <string name="revanced_hide_transcript_section_title">Transkripsiya bÃļlməsini gizlət</string>
<string name="revanced_hide_transcript_section_summary_on">Transkripsiya bÃļlməsi gizlidir</string> <string name="revanced_hide_transcript_section_summary_on">Transkripsiya bÃļlməsi gizlidir</string>
<string name="revanced_hide_transcript_section_summary_off">Transkripsiya bÃļlməsi gÃļstərilir</string> <string name="revanced_hide_transcript_section_summary_off">Transkripsiya bÃļlməsi gÃļstərilir</string>
@@ -239,14 +253,18 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_keyword_content_phrases_title">Gizlədiləcək açar sÃļzlər</string> <string name="revanced_hide_keyword_content_phrases_title">Gizlədiləcək açar sÃļzlər</string>
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<string name="revanced_hide_keyword_content_phrases_summary">Yeni sətirlərlə ayrÄąlmÄąÅŸ gizlədiləcək açar sÃļzlər və ifadələr\n\nOrtada bÃļyÃŧk hərf olan sÃļzlər korpusla birlikdə daxil edilməlidir (yəni: iPhone, TikTok, LeBlanc)</string> <string name="revanced_hide_keyword_content_phrases_summary">Yeni sətirlərlə ayrÄąlmÄąÅŸ gizlədiləcək açar sÃļzlər və frazalar\n\nAçar sÃļzlər kanal adlarÄą və ya video adlarÄąnda gÃļstərilən istənilən mətn ola bilər\n\nOrtada bÃļyÃŧk hərf olan sÃļzlər korpusla birlikdə qeyd edilməlidir (yəni: iPhone, TikTok, LeBlanc)</string>
<string name="revanced_hide_keyword_content_about_title">Açar sÃļz filtrləməsi haqqÄąnda</string> <string name="revanced_hide_keyword_content_about_title">Açar sÃļz filtrləməsi haqqÄąnda</string>
<string name="revanced_hide_keyword_content_about_summary">Əsas səhifə/Abunəlik/AxtarÄąÅŸ nəticələri açar sÃļz ifadələrinə uyğunlaşan məzmunu gizlətmək ÃŧçÃŧn filtrlənir\n\nMəhdudiyyətlər\nâ€ĸ Bəzi Shorts gizlənə bilməz\nâ€ĸ Bəzi UI elementləri gizlənə bilməz\nâ€ĸ Açar sÃļz axtarÄąÅŸÄą heç bir nəticə gÃļstərməyə bilər</string> <string name="revanced_hide_keyword_content_about_summary">Əsas səhifə/Abunəlik/AxtarÄąÅŸ nəticələri açar sÃļz ifadələrinə uyğunlaşan məzmunu gizlətmək ÃŧçÃŧn filtrlənir\n\nMəhdudiyyətlər\nâ€ĸ Shorts-lar kanal adÄąna gÃļrə gizlənə bilməz\nâ€ĸ Bəzi UI hissəcikləri gizlədilə bilməz\nâ€ĸ Açar sÃļz axtarÄąÅŸÄąnda nəticə olmaya bilər</string>
<string name="revanced_hide_keyword_content_about_whole_words_title">BÃŧtÃŧn sÃļzləri uyğunlaşdÄąr</string>
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<string name="revanced_hide_keyword_content_about_whole_words_summary">Açar sÃļz/frazanÄąn qoşa dÄąrnaqlarla əhatə olunmasÄą video adlarÄą və kanal adlarÄąnÄąn qismən uyğunlaşmasÄąna mane olacaq &lt;br&gt;&lt;br&gt;Məsələn,&lt;br&gt;&lt;b&gt;\"ai\"&lt;/b&gt; videonu gizlədəcək:&lt;b&gt;How does AI work?&lt;/b&gt;&lt;br&gt; lakin gizlətməyəcək: DÃŧzgÃŧn;&lt;b&gt;What does fair use mean?&lt;/b&gt;</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_common">EtibarsÄąz açar sÃļzÃŧ. \'%s\' istifadə edilə bilməz</string> <string name="revanced_hide_keyword_toast_invalid_common">Açar sÃļz istifadə edilə bilmir: %s</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <string name="revanced_hide_keyword_toast_invalid_common_whole_word_required">Açar sÃļz istifadəsi ÃŧçÃŧn istinad əlavə et: %s</string>
<string name="revanced_hide_keyword_toast_invalid_length">EtibarsÄąz açar sÃļzÃŧ. \'%1$s\', %2$d simvoldan azdÄąr</string> <string name="revanced_hide_keyword_toast_invalid_conflicting">Açar sÃļzÃŧn ziddiyyətli hissəcikləri var: %s</string>
<string name="revanced_hide_keyword_toast_invalid_broad">\"%s\" açar sÃļzÃŧ, bÃŧtÃŧn videolarda gizlədiləcək</string> <string name="revanced_hide_keyword_toast_invalid_length">Açar sÃļz çox qÄąsadÄąr və istinad tələb edir: %s</string>
<string name="revanced_hide_keyword_toast_invalid_broad">Açar sÃļz, bÃŧtÃŧn videolarÄą gizlədəcək: %s</string>
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
<string name="revanced_hide_general_ads_title">Ümumi reklamlarÄą gizlət</string> <string name="revanced_hide_general_ads_title">Ümumi reklamlarÄą gizlət</string>
@@ -264,22 +282,22 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_self_sponsor_ads_title">Öz-sponsorlu kartlarÄą gizlət</string> <string name="revanced_hide_self_sponsor_ads_title">Öz-sponsorlu kartlarÄą gizlət</string>
<string name="revanced_hide_self_sponsor_ads_summary_on">ÖzÃŧnə sponsorluq edilən kartlar gizlidir</string> <string name="revanced_hide_self_sponsor_ads_summary_on">ÖzÃŧnə sponsorluq edilən kartlar gizlidir</string>
<string name="revanced_hide_self_sponsor_ads_summary_off">ÖzÃŧnə sponsorluq edilən kartlar gÃļstərilir</string> <string name="revanced_hide_self_sponsor_ads_summary_off">ÖzÃŧnə sponsorluq edilən kartlar gÃļstərilir</string>
<string name="revanced_hide_products_banner_title">Məhsullara baxma panelin gizlət</string> <string name="revanced_hide_products_banner_title">Məhsullara baxma etiketin gizlət</string>
<string name="revanced_hide_products_banner_summary_on">Panel gizlədilib</string> <string name="revanced_hide_products_banner_summary_on">Etiket gizlədilib</string>
<string name="revanced_hide_products_banner_summary_off">Panel gÃļstərilir</string> <string name="revanced_hide_products_banner_summary_off">Etiket gÃļstərilir</string>
<string name="revanced_hide_shopping_links_title">Video aÃ§ÄąqlamadakÄą alÄąÅŸ-veriş linklərin gizlə</string> <string name="revanced_hide_shopping_links_title">Video aÃ§Äąqlama alÄąÅŸ-veriş linklər gizlə</string>
<string name="revanced_hide_shopping_links_summary_on">AlÄąÅŸ-veriş bağlantÄąlarÄą gizlədilir</string> <string name="revanced_hide_shopping_links_summary_on">AlÄąÅŸ-veriş bağlantÄąlarÄą gizlədilir</string>
<string name="revanced_hide_shopping_links_summary_off">AlÄąÅŸ-veriş bağlantÄąlarÄą gÃļstərilir</string> <string name="revanced_hide_shopping_links_summary_off">AlÄąÅŸ-veriş bağlantÄąlarÄą gÃļstərilir</string>
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. --> <!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_visit_store_button_title">KanaldakÄą \"MağazanÄą ziyarət et\" dÃŧyməsin gizlə</string> <string name="revanced_hide_visit_store_button_title">Kanalda \"Mağaza ziyarət\" dÃŧymə gizlə</string>
<string name="revanced_hide_visit_store_button_summary_on">DÃŧymə gizlidir</string> <string name="revanced_hide_visit_store_button_summary_on">DÃŧymə gizlidir</string>
<string name="revanced_hide_visit_store_button_summary_off">DÃŧymə gÃļstərilir</string> <string name="revanced_hide_visit_store_button_summary_off">DÃŧymə gÃļstərilir</string>
<string name="revanced_hide_web_search_results_title">Veb axtarÄąÅŸ nəticələrini gizlət</string> <string name="revanced_hide_web_search_results_title">Veb axtarÄąÅŸ nəticələrini gizlət</string>
<string name="revanced_hide_web_search_results_summary_on">Veb axtarÄąÅŸ nəticələri gizlədilir</string> <string name="revanced_hide_web_search_results_summary_on">Veb axtarÄąÅŸ nəticələri gizlədilir</string>
<string name="revanced_hide_web_search_results_summary_off">Veb axtarÄąÅŸ nəticələri gÃļstərilir</string> <string name="revanced_hide_web_search_results_summary_off">Veb axtarÄąÅŸ nəticələri gÃļstərilir</string>
<string name="revanced_hide_merchandise_banners_title">Məhsul bannerlərini gizlət</string> <string name="revanced_hide_merchandise_banners_title">Məhsul etiketlərini gizlət</string>
<string name="revanced_hide_merchandise_banners_summary_on">Məhsul bannerləri gizlədilir</string> <string name="revanced_hide_merchandise_banners_summary_on">Məhsul etiketləri gizlədilir</string>
<string name="revanced_hide_merchandise_banners_summary_off">Məhsul bannerləri gÃļstərilir</string> <string name="revanced_hide_merchandise_banners_summary_off">Məhsul etiketləri gÃļstərilir</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_fullscreen_ads_feature_not_available_toast">Tam ekran reklamlarÄą gizlətmə yalnÄąz kÃļhnə cihazlarda işləyir</string> <string name="revanced_hide_fullscreen_ads_feature_not_available_toast">Tam ekran reklamlarÄą gizlətmə yalnÄąz kÃļhnə cihazlarda işləyir</string>
</patch> </patch>
@@ -304,7 +322,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_copy_video_url_timestamp_summary_off">DÃŧymə gÃļstərilmir</string> <string name="revanced_copy_video_url_timestamp_summary_off">DÃŧymə gÃļstərilmir</string>
</patch> </patch>
<patch id="interaction.dialog.RemoveViewerDiscretionDialogPatch"> <patch id="interaction.dialog.RemoveViewerDiscretionDialogPatch">
<string name="revanced_remove_viewer_discretion_dialog_title">İzləyici mÃŧlahizə dialoqunu sil</string> <string name="revanced_remove_viewer_discretion_dialog_title">İzləyici mÃŧlahizə dialoqun sil</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_on">Dialoq silindi</string> <string name="revanced_remove_viewer_discretion_dialog_summary_on">Dialoq silindi</string>
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialoq gÃļstərilir</string> <string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialoq gÃļstərilir</string>
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Bu, yaş məhdudiyyətini ÃļtÃŧrmÃŧr. Sadəcə avtomatik qəbul edir.</string> <string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Bu, yaş məhdudiyyətini ÃļtÃŧrmÃŧr. Sadəcə avtomatik qəbul edir.</string>
@@ -316,7 +334,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_external_downloader_summary_on">YÃŧkləmə dÃŧyməsi oynadÄącÄąda gÃļstərilir</string> <string name="revanced_external_downloader_summary_on">YÃŧkləmə dÃŧyməsi oynadÄącÄąda gÃļstərilir</string>
<string name="revanced_external_downloader_summary_off">YÃŧkləmə dÃŧyməsi oynadÄącÄąda gÃļstərilmir</string> <string name="revanced_external_downloader_summary_off">YÃŧkləmə dÃŧyməsi oynadÄącÄąda gÃļstərilmir</string>
<!-- 'download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title' --> <!-- 'download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title' -->
<string name="revanced_external_downloader_action_button_title">YÃŧkləmə fəaliyyəti dÃŧyməsini qəbul etmə</string> <string name="revanced_external_downloader_action_button_title">YÃŧkləmə fəaliyyət dÃŧyməsin qəbul etmə</string>
<string name="revanced_external_downloader_action_button_summary_on">YÃŧkləmə dÃŧyməsi, xarici yÃŧkləyicini aÃ§Äąr</string> <string name="revanced_external_downloader_action_button_summary_on">YÃŧkləmə dÃŧyməsi, xarici yÃŧkləyicini aÃ§Äąr</string>
<string name="revanced_external_downloader_action_button_summary_off">YÃŧkləmə dÃŧyməsi tətbiqdəki standart yÃŧkləyicini aÃ§Äąr</string> <string name="revanced_external_downloader_action_button_summary_off">YÃŧkləmə dÃŧyməsi tətbiqdəki standart yÃŧkləyicini aÃ§Äąr</string>
<string name="revanced_external_downloader_name_title">YÃŧkləyici paketi adÄą</string> <string name="revanced_external_downloader_name_title">YÃŧkləyici paketi adÄą</string>
@@ -567,7 +585,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_disable_rolling_number_animations_summary_off">SÃŧrÃŧşən say animasiyasÄą aÃ§ÄąqdÄąr</string> <string name="revanced_disable_rolling_number_animations_summary_off">SÃŧrÃŧşən say animasiyasÄą aÃ§ÄąqdÄąr</string>
</patch> </patch>
<patch id="layout.hide.seekbar.HideSeekbarPatch"> <patch id="layout.hide.seekbar.HideSeekbarPatch">
<string name="revanced_hide_seekbar_title">Video oynadÄącÄąda axtarÄąÅŸ çubuğunu gizlət</string> <string name="revanced_hide_seekbar_title">Video oynadÄącÄąda axtarÄąÅŸ çubuğun gizlə</string>
<string name="revanced_hide_seekbar_summary_on">Video oynadÄącÄą axtarÄąÅŸ çubuğu gizlidir</string> <string name="revanced_hide_seekbar_summary_on">Video oynadÄącÄą axtarÄąÅŸ çubuğu gizlidir</string>
<string name="revanced_hide_seekbar_summary_off">Video oynadÄącÄą axtarÄąÅŸ çubuğu gÃļstərilir</string> <string name="revanced_hide_seekbar_summary_off">Video oynadÄącÄą axtarÄąÅŸ çubuğu gÃļstərilir</string>
<string name="revanced_hide_seekbar_thumbnail_title">Video miniatÃŧrlərdə vaxt çubuğun gizlə</string> <string name="revanced_hide_seekbar_thumbnail_title">Video miniatÃŧrlərdə vaxt çubuğun gizlə</string>
@@ -606,12 +624,15 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_shorts_tagged_products_title">Etiketlənmiş məhsullarÄą gizlət</string> <string name="revanced_hide_shorts_tagged_products_title">Etiketlənmiş məhsullarÄą gizlət</string>
<string name="revanced_hide_shorts_tagged_products_summary_on">Etiketlənmiş məhsullar gizlədilir</string> <string name="revanced_hide_shorts_tagged_products_summary_on">Etiketlənmiş məhsullar gizlədilir</string>
<string name="revanced_hide_shorts_tagged_products_summary_off">Etiketlənmiş məhsullar gÃļstərilir</string> <string name="revanced_hide_shorts_tagged_products_summary_off">Etiketlənmiş məhsullar gÃļstərilir</string>
<string name="revanced_hide_shorts_location_label_title">Yerləşmə etiketini gizlət</string> <string name="revanced_hide_shorts_location_label_title">Məkan etiketini gizlət</string>
<string name="revanced_hide_shorts_location_label_summary_on">Məkan etiketi gizlidir</string> <string name="revanced_hide_shorts_location_label_summary_on">Məkan etiketi gizlidir</string>
<string name="revanced_hide_shorts_location_label_summary_off">Məkan etiketi gÃļstərilir</string> <string name="revanced_hide_shorts_location_label_summary_off">Məkan etiketi gÃļstərilir</string>
<string name="revanced_hide_shorts_save_sound_button_title">Səsi pleylistdə saxlama dÃŧyməsini gizlət</string> <string name="revanced_hide_shorts_save_sound_button_title">Səsi pleylistdə saxlama dÃŧyməsini gizlət</string>
<string name="revanced_hide_shorts_save_sound_button_summary_on">Səsi pleylistdə saxlama gizlidir</string> <string name="revanced_hide_shorts_save_sound_button_summary_on">Səsi pleylistdə saxlama gizlidir</string>
<string name="revanced_hide_shorts_save_sound_button_summary_off">Səsi pleylistdə saxlama gÃļstərilir</string> <string name="revanced_hide_shorts_save_sound_button_summary_off">Səsi pleylistdə saxlama gÃļstərilir</string>
<string name="revanced_hide_shorts_use_this_sound_button_title">\"Bu səsi istifadə et\" dÃŧyməsini gizlət</string>
<string name="revanced_hide_shorts_use_this_sound_button_summary_on">\"Bu səsi istifadə et\" dÃŧyməsi gizlidir</string>
<string name="revanced_hide_shorts_use_this_sound_button_summary_off">\"Bu səsi istifadə et\" dÃŧyməsi gÃļstərilir</string>
<string name="revanced_hide_shorts_search_suggestions_title">AxtarÄąÅŸ təkliflərini gizlət</string> <string name="revanced_hide_shorts_search_suggestions_title">AxtarÄąÅŸ təkliflərini gizlət</string>
<string name="revanced_hide_shorts_search_suggestions_summary_on">AxtarÄąÅŸ təklifləri gizlədilib</string> <string name="revanced_hide_shorts_search_suggestions_summary_on">AxtarÄąÅŸ təklifləri gizlədilib</string>
<string name="revanced_hide_shorts_search_suggestions_summary_off">AxtarÄąÅŸ təklifləri gÃļstərilir</string> <string name="revanced_hide_shorts_search_suggestions_summary_off">AxtarÄąÅŸ təklifləri gÃļstərilir</string>
@@ -665,7 +686,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_timestamp_summary_off">Vaxt mÃļhÃŧrÃŧ gÃļstərilir</string> <string name="revanced_hide_timestamp_summary_off">Vaxt mÃļhÃŧrÃŧ gÃļstərilir</string>
</patch> </patch>
<patch id="layout.panels.popup.PlayerPopupPanelsPatch"> <patch id="layout.panels.popup.PlayerPopupPanelsPatch">
<string name="revanced_hide_player_popup_panels_title">OynadÄącÄą aÃ§Äąlan pəncərə panellərini gizlət</string> <string name="revanced_hide_player_popup_panels_title">OynadÄącÄą aÃ§Äąlan pəncərə panellərin gizlə</string>
<string name="revanced_hide_player_popup_panels_summary_on">OynadÄącÄą aÃ§Äąlan pəncərə panelləri gizlidir</string> <string name="revanced_hide_player_popup_panels_summary_on">OynadÄącÄą aÃ§Äąlan pəncərə panelləri gizlidir</string>
<string name="revanced_hide_player_popup_panels_summary_off">OynadÄącÄą aÃ§Äąlan pəncərə panelləri gÃļstərilir</string> <string name="revanced_hide_player_popup_panels_summary_off">OynadÄącÄą aÃ§Äąlan pəncərə panelləri gÃļstərilir</string>
</patch> </patch>
@@ -675,7 +696,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_player_overlay_opacity_invalid_toast">OynadÄącÄą ÃļrtÃŧyÃŧnÃŧn qeyri-şəffaflığı 0-100 arasÄą olmalÄądÄąr</string> <string name="revanced_player_overlay_opacity_invalid_toast">OynadÄącÄą ÃļrtÃŧyÃŧnÃŧn qeyri-şəffaflığı 0-100 arasÄą olmalÄądÄąr</string>
</patch> </patch>
<patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch"> <patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch">
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Gizli</string>
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<string name="revanced_ryd_failure_connection_timeout">\"Bəyənməmə\" mÃŧvəqqəti əlçatmazdÄąr(API vaxtÄą bitdi)</string> <string name="revanced_ryd_failure_connection_timeout">\"Bəyənməmə\" mÃŧvəqqəti əlçatmazdÄąr(API vaxtÄą bitdi)</string>
<string name="revanced_ryd_failure_connection_status_code">Bəyənməmə əlçatmazdÄąr (status %d)</string> <string name="revanced_ryd_failure_connection_status_code">Bəyənməmə əlçatmazdÄąr (status %d)</string>
@@ -725,7 +745,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_wide_searchbar_summary_off">Geniş axtarÄąÅŸ çubuğu qeyri-aktivdir</string> <string name="revanced_wide_searchbar_summary_off">Geniş axtarÄąÅŸ çubuğu qeyri-aktivdir</string>
</patch> </patch>
<patch id="layout.seekbar.RestoreOldSeekbarThumbnailsPatch"> <patch id="layout.seekbar.RestoreOldSeekbarThumbnailsPatch">
<string name="revanced_restore_old_seekbar_thumbnails_title">KÃļhnə axtarÄąÅŸ çubuğu miniatÃŧrlərini qaytar</string> <string name="revanced_restore_old_seekbar_thumbnails_title">KÃļhnə axtarÄąÅŸ çubuğu miniatÃŧrlərin al</string>
<string name="revanced_restore_old_seekbar_thumbnails_summary_on">AxtarÄąÅŸ çubuğu miniatÃŧrləri axtarÄąÅŸ çubuğu ÃŧstÃŧndə gÃļrÃŧnəcək</string> <string name="revanced_restore_old_seekbar_thumbnails_summary_on">AxtarÄąÅŸ çubuğu miniatÃŧrləri axtarÄąÅŸ çubuğu ÃŧstÃŧndə gÃļrÃŧnəcək</string>
<string name="revanced_restore_old_seekbar_thumbnails_summary_off">AxtarÄąÅŸ çubuğu miniatÃŧrləri tam ekranda gÃļrÃŧnəcək</string> <string name="revanced_restore_old_seekbar_thumbnails_summary_off">AxtarÄąÅŸ çubuğu miniatÃŧrləri tam ekranda gÃļrÃŧnəcək</string>
</patch> </patch>
@@ -771,6 +791,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_general_skipcount_sum_off">ÖtÃŧrmə sayÄąnÄąn izlənməsi aktiv deyil</string> <string name="revanced_sb_general_skipcount_sum_off">ÖtÃŧrmə sayÄąnÄąn izlənməsi aktiv deyil</string>
<string name="revanced_sb_general_min_duration">Minimum bÃļlÃŧm mÃŧddəti</string> <string name="revanced_sb_general_min_duration">Minimum bÃļlÃŧm mÃŧddəti</string>
<string name="revanced_sb_general_min_duration_sum">BÃļlÃŧmlər bu dəyərdən (saniyə olaraq) daha qÄąsadÄąrsa gÃļstərilməyəcək və ya ÃļtÃŧrÃŧlməyəcək</string> <string name="revanced_sb_general_min_duration_sum">BÃļlÃŧmlər bu dəyərdən (saniyə olaraq) daha qÄąsadÄąrsa gÃļstərilməyəcək və ya ÃļtÃŧrÃŧlməyəcək</string>
<string name="revanced_sb_general_min_duration_invalid">EtibarsÄąz vaxt mÃŧddəti</string>
<string name="revanced_sb_general_uuid">Şəxsi istifadəçi kimliyiniz</string> <string name="revanced_sb_general_uuid">Şəxsi istifadəçi kimliyiniz</string>
<string name="revanced_sb_general_uuid_sum">Bu gizli saxlanÄąlmalÄądÄąr. Bu, parol kimidir və heç kimlə paylaÅŸÄąlmamalÄądÄąr. Kimsə bunu bilsə, onlar sizi təqlid edə bilər</string> <string name="revanced_sb_general_uuid_sum">Bu gizli saxlanÄąlmalÄądÄąr. Bu, parol kimidir və heç kimlə paylaÅŸÄąlmamalÄądÄąr. Kimsə bunu bilsə, onlar sizi təqlid edə bilər</string>
<string name="revanced_sb_general_uuid_invalid">Şəxsi istifadəçi kimliyiniz ən az 30 simvol uzunluğunda olmalÄądÄąr</string> <string name="revanced_sb_general_uuid_invalid">Şəxsi istifadəçi kimliyiniz ən az 30 simvol uzunluğunda olmalÄądÄąr</string>
@@ -788,7 +809,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_settings_export_failed">%s ixrac uğursuz</string> <string name="revanced_sb_settings_export_failed">%s ixrac uğursuz</string>
<string name="revanced_sb_settings_revanced_export_user_id_warning">Tənzimləmələr şəxsi SponsorBlock istifadəçi kimliyi ehtiva edir.\n\nİstifadəçi kimliyiniz parol kimidir və bu paylaÅŸÄąlmamalÄądÄąr.\n</string> <string name="revanced_sb_settings_revanced_export_user_id_warning">Tənzimləmələr şəxsi SponsorBlock istifadəçi kimliyi ehtiva edir.\n\nİstifadəçi kimliyiniz parol kimidir və bu paylaÅŸÄąlmamalÄądÄąr.\n</string>
<string name="revanced_sb_settings_revanced_export_user_id_warning_dismiss">Təkrar gÃļstərmə</string> <string name="revanced_sb_settings_revanced_export_user_id_warning_dismiss">Təkrar gÃļstərmə</string>
<string name="revanced_sb_diff_segments">Seqment davranÄąÅŸÄąnÄą dəyişdir</string> <string name="revanced_sb_diff_segments">BÃļlÃŧm davranÄąÅŸÄąnÄą dəyişdir</string>
<string name="revanced_sb_segments_sponsor">Sponsor</string> <string name="revanced_sb_segments_sponsor">Sponsor</string>
<string name="revanced_sb_segments_sponsor_sum">Ödənişli tanÄątÄąm, Ãļdənişli yÃļnləndirmələr və birbaşa reklamlar. Öz-tanÄątÄąm və ya bəyəndikləri səbəblərə/yaradÄącÄąlara/veb saytlara/məhsullara Ãļdənişsiz çağırÄąÅŸlar etmək ÃŧçÃŧn deyil</string> <string name="revanced_sb_segments_sponsor_sum">Ödənişli tanÄątÄąm, Ãļdənişli yÃļnləndirmələr və birbaşa reklamlar. Öz-tanÄątÄąm və ya bəyəndikləri səbəblərə/yaradÄącÄąlara/veb saytlara/məhsullara Ãļdənişsiz çağırÄąÅŸlar etmək ÃŧçÃŧn deyil</string>
<string name="revanced_sb_segments_selfpromo">Ödənişsiz/Öz reklamÄą</string> <string name="revanced_sb_segments_selfpromo">Ödənişsiz/Öz reklamÄą</string>
@@ -871,8 +892,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_new_segment_time_start">BÃļlÃŧm başladığı vaxt</string> <string name="revanced_sb_new_segment_time_start">BÃļlÃŧm başladığı vaxt</string>
<string name="revanced_sb_new_segment_time_end">BÃļlÃŧmÃŧn bitmə vaxtÄą</string> <string name="revanced_sb_new_segment_time_end">BÃļlÃŧmÃŧn bitmə vaxtÄą</string>
<string name="revanced_sb_new_segment_confirm_title">Vaxtlar dÃŧzgÃŧndÃŧr?</string> <string name="revanced_sb_new_segment_confirm_title">Vaxtlar dÃŧzgÃŧndÃŧr?</string>
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<string name="revanced_sb_new_segment_confirm_content">BÃļlÃŧm \n\n%1$s\n\n%2$s\n\n(%3$s)\n\nTəqdim etməyə hazÄąrsÄąnÄąz?</string> <string name="revanced_sb_new_segment_confirm_content">BÃļlÃŧm \n\n%1$s\n\n%2$s\n\n(%3$s)\n\nTəqdim etməyə hazÄąrsÄąnÄąz?</string>
<string name="revanced_sb_new_segment_start_is_before_end">Başlanğıc sondan əvvəl olmalÄądÄąr</string> <string name="revanced_sb_new_segment_start_is_before_end">Başlanğıc sondan əvvəl olmalÄądÄąr</string>
<string name="revanced_sb_new_segment_mark_locations_first">Əvvəlcə vaxt çubuğunda iki yeri doldur</string> <string name="revanced_sb_new_segment_mark_locations_first">Əvvəlcə vaxt çubuğunda iki yeri doldur</string>
@@ -891,6 +910,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_stats_username_changed">İstifadəçi adÄą uğurla dəyişdirildi</string> <string name="revanced_sb_stats_username_changed">İstifadəçi adÄą uğurla dəyişdirildi</string>
<string name="revanced_sb_stats_reputation">NÃŧfuzunuz &lt;b&gt;%.2f&lt;/b&gt;</string> <string name="revanced_sb_stats_reputation">NÃŧfuzunuz &lt;b&gt;%.2f&lt;/b&gt;</string>
<string name="revanced_sb_stats_submissions">&lt;b&gt;%s&lt;/b&gt; bÃļlÃŧm yaratdÄąnÄąz</string> <string name="revanced_sb_stats_submissions">&lt;b&gt;%s&lt;/b&gt; bÃļlÃŧm yaratdÄąnÄąz</string>
<string name="revanced_sb_stats_submissions_sum">BÃļlÃŧmlərinizə baxmaq ÃŧçÃŧn bura toxunun</string>
<string name="revanced_sb_stats_saved_zero">SponsorBlock liderlik lÃļvhəsi</string> <string name="revanced_sb_stats_saved_zero">SponsorBlock liderlik lÃļvhəsi</string>
<string name="revanced_sb_stats_saved">İnsanlarÄą &lt;b&gt;%s&lt;/b&gt; bÃļlÃŧmdən xilas etdiniz</string> <string name="revanced_sb_stats_saved">İnsanlarÄą &lt;b&gt;%s&lt;/b&gt; bÃļlÃŧmdən xilas etdiniz</string>
<string name="revanced_sb_stats_saved_sum_zero">Qlobal statistikalarÄą və başlÄąca tÃļhfəçiləri gÃļrmək ÃŧçÃŧn bura toxunun</string> <string name="revanced_sb_stats_saved_sum_zero">Qlobal statistikalarÄą və başlÄąca tÃļhfəçiləri gÃļrmək ÃŧçÃŧn bura toxunun</string>
@@ -942,7 +962,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_start_page_entry_9">Trenddə olan</string> <string name="revanced_start_page_entry_9">Trenddə olan</string>
</patch> </patch>
<patch id="layout.startupshortsreset.DisableResumingShortsOnStartupPatch"> <patch id="layout.startupshortsreset.DisableResumingShortsOnStartupPatch">
<string name="revanced_disable_resuming_shorts_player_title">Shorts oynadÄącÄą davam etdirməsini bağla</string> <string name="revanced_disable_resuming_shorts_player_title">Shorts oynadÄącÄą başladÄącÄąnÄą bağla</string>
<string name="revanced_disable_resuming_shorts_player_summary_on">Tətbiq aÃ§Äąlanda Shorts oynadÄącÄą davam etməyəcək</string> <string name="revanced_disable_resuming_shorts_player_summary_on">Tətbiq aÃ§Äąlanda Shorts oynadÄącÄą davam etməyəcək</string>
<string name="revanced_disable_resuming_shorts_player_summary_off">Tətbiq aÃ§Äąlanda Shorts oynadÄącÄą davam edəcək</string> <string name="revanced_disable_resuming_shorts_player_summary_off">Tətbiq aÃ§Äąlanda Shorts oynadÄącÄą davam edəcək</string>
</patch> </patch>
@@ -1004,7 +1024,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_alt_thumbnail_search_title">AxtarÄąÅŸ nəticələri</string> <string name="revanced_alt_thumbnail_search_title">AxtarÄąÅŸ nəticələri</string>
<string name="revanced_alt_thumbnail_options_entry_1">Orijinal miniatÃŧrlər</string> <string name="revanced_alt_thumbnail_options_entry_1">Orijinal miniatÃŧrlər</string>
<string name="revanced_alt_thumbnail_options_entry_2">DeArrow &amp; Orijinal miniatÃŧrlər</string> <string name="revanced_alt_thumbnail_options_entry_2">DeArrow &amp; Orijinal miniatÃŧrlər</string>
<string name="revanced_alt_thumbnail_options_entry_3">DeArrow &amp; Kadr çəkilişləri</string> <string name="revanced_alt_thumbnail_options_entry_3">DeArrow &amp; Kadr çəkilişlər</string>
<string name="revanced_alt_thumbnail_options_entry_4">Kadr çəkilişləri</string> <string name="revanced_alt_thumbnail_options_entry_4">Kadr çəkilişləri</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">DeArrow YouTube videolarÄą ÃŧçÃŧn bÃļlÃŧk mənbəli miniatÃŧrlər təchiz edir. Bu miniatÃŧrlər hər zaman YouTube tərəfindən təmin edilənlərdən daha uyğun olur\n\nƏgər aktivləşdirilərsə, video URL-lər API serverinə gÃļndəriləcək və başqa heç bir məlumat gÃļndərilməyəcək. Videoda DeArrow miniatÃŧrləri yoxdursa, orijinal və ya hələ də kadr çəkilişləri gÃļstərilir\n\nDeArrow haqqÄąnda ətraflÄą Ãļyrənmək ÃŧçÃŧn bura toxun</string> <string name="revanced_alt_thumbnail_dearrow_about_summary">DeArrow YouTube videolarÄą ÃŧçÃŧn bÃļlÃŧk mənbəli miniatÃŧrlər təchiz edir. Bu miniatÃŧrlər hər zaman YouTube tərəfindən təmin edilənlərdən daha uyğun olur\n\nƏgər aktivləşdirilərsə, video URL-lər API serverinə gÃļndəriləcək və başqa heç bir məlumat gÃļndərilməyəcək. Videoda DeArrow miniatÃŧrləri yoxdursa, orijinal və ya hələ də kadr çəkilişləri gÃļstərilir\n\nDeArrow haqqÄąnda ətraflÄą Ãļyrənmək ÃŧçÃŧn bura toxun</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">API əlçatan deyilsə ani bildiriş gÃļstər</string> <string name="revanced_alt_thumbnail_dearrow_connection_toast_title">API əlçatan deyilsə ani bildiriş gÃļstər</string>
@@ -1033,6 +1053,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_announcements_connection_failed">Elan provayderinə bağlanmaq olmadı</string> <string name="revanced_announcements_connection_failed">Elan provayderinə bağlanmaq olmadı</string>
<string name="revanced_announcements_dialog_dismiss">Ləğv et</string> <string name="revanced_announcements_dialog_dismiss">Ləğv et</string>
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">XĶ™bĶ™rdarlÄąq</string>
<string name="revanced_check_watch_history_domain_name_dialog_message">BaxÄąÅŸ tarixçəniz saxlanmÄąr.&lt;br&gt;&lt;br&gt;Bu çox gÃŧman ki, DNS reklam bloklayÄącÄą və ya şəbəkə proksisinə gÃļrədir.&lt;br&gt;&lt;br&gt;.Bunu dÃŧzəltmək ÃŧçÃŧn s.youtube.com-u&lt;/b&gt; &lt;b&gt;ağ siyahÄąya salÄąn və ya bÃŧtÃŧn DNS bloklayÄącÄąlarÄą və proksiləri bağlayÄąn.</string>
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Təkrar gÃļstərmə</string>
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
<string name="revanced_auto_repeat_title">Avto-təkrarlamanÄą aktivləşdir</string> <string name="revanced_auto_repeat_title">Avto-təkrarlamanÄą aktivləşdir</string>
<string name="revanced_auto_repeat_summary_on">Avtomatik təkrar aktivləşdirilib</string> <string name="revanced_auto_repeat_summary_on">Avtomatik təkrar aktivləşdirilib</string>
@@ -1059,9 +1084,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_external_browser_summary_off">BağlantÄąlar tətbiqdə aÃ§ÄąlÄąr</string> <string name="revanced_external_browser_summary_off">BağlantÄąlar tətbiqdə aÃ§ÄąlÄąr</string>
</patch> </patch>
<patch id="misc.privacy.RemoveTrackingQueryParameterPatch"> <patch id="misc.privacy.RemoveTrackingQueryParameterPatch">
<string name="revanced_remove_tracking_query_parameter_title">İzləmə sorğusu parametrini sil</string> <string name="revanced_remove_tracking_query_parameter_title">İzləmə sorğusu faktorun sil</string>
<string name="revanced_remove_tracking_query_parameter_summary_on">İzləmə sorğusu parametri bağlantılardan silinir</string> <string name="revanced_remove_tracking_query_parameter_summary_on">İzləmə sorğusu faktoru bağlantılardan silinir</string>
<string name="revanced_remove_tracking_query_parameter_summary_off">İzləmə sorğusu parametri bağlantılardan silinmir</string> <string name="revanced_remove_tracking_query_parameter_summary_off">İzləmə sorğusu faktoru bağlantılardan silinmir</string>
</patch> </patch>
<patch id="misc.zoomhaptics.ZoomHapticsPatch"> <patch id="misc.zoomhaptics.ZoomHapticsPatch">
<string name="revanced_disable_zoom_haptics_title">YaxÄąnlaşdÄąrma əks-əlaqəsini bağla</string> <string name="revanced_disable_zoom_haptics_title">YaxÄąnlaşdÄąrma əks-əlaqəsini bağla</string>
@@ -1107,21 +1132,23 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_slide_to_seek_summary_on">Axtarmaq ÃŧçÃŧn sÃŧrÃŧşdÃŧrmə aktivdir</string> <string name="revanced_slide_to_seek_summary_on">Axtarmaq ÃŧçÃŧn sÃŧrÃŧşdÃŧrmə aktivdir</string>
<string name="revanced_slide_to_seek_summary_off">Axtarmaq ÃŧçÃŧn sÃŧrÃŧşdÃŧrmə aktiv deyil</string> <string name="revanced_slide_to_seek_summary_off">Axtarmaq ÃŧçÃŧn sÃŧrÃŧşdÃŧrmə aktiv deyil</string>
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
<string name="revanced_spoof_client_screen_title">Qəbuledicini saxtalaşdÄąr</string> <string name="revanced_spoof_video_streams_screen_title">Video yayÄąmlarÄą təqlid et</string>
<string name="revanced_spoof_client_screen_summary">Oynatma problemlərinin olmamasÄą ÃŧçÃŧn client-i saxtalaşdÄąr</string> <string name="revanced_spoof_video_streams_screen_summary">Oxutma problemlərini Ãļnləmək ÃŧçÃŧn client video yayÄąmlarÄąnÄą təqlid et</string>
<string name="revanced_spoof_client_title">Qəbuledicini saxtalaşdÄąr</string> <string name="revanced_spoof_video_streams_title">Video yayÄąmlarÄą təqlid et</string>
<string name="revanced_spoof_client_summary_on">Qəbuledici saxtalaşdÄąrÄąldÄą</string> <string name="revanced_spoof_video_streams_summary_on">Video yayÄąmlarÄą təqlid edilir</string>
<string name="revanced_spoof_client_summary_off">Qəbuledici dəyişməyib\n\nVideo oynatma işləməyə bilər</string> <string name="revanced_spoof_video_streams_summary_off">Video yayÄąmlarÄą təqlid edilmir\n\nVideo oxutma işləməyə bilər</string>
<string name="revanced_spoof_client_user_dialog_message">Bu seçimin bağlanmasÄą, video oynatma problemlərinə səbəb ola bilər.</string> <string name="revanced_spoof_video_streams_user_dialog_message">Bu ayarÄą sÃļndÃŧrmək, video oxutma problemlərinə səbəb ola bilər.</string>
<string name="revanced_spoof_client_use_ios_title">Qəbuledicini iOS olaraq saxtalaşdÄąr</string> <string name="revanced_spoof_video_streams_client_type_title">İlkin client</string>
<string name="revanced_spoof_client_use_ios_summary_on">Qəbuledici hazÄąrda iOS-a saxtalaşdÄąrÄąlÄąb\n\nYan təsirlərə daxildir:\nâ€ĸ HDR video yoxdur\nâ€ĸ Daha yÃŧksək video keyfiyyətlər olmaya bilər\nâ€ĸ CanlÄą yayÄąmlar yalnÄąz səs kimi oynadÄąla bilməz</string> <string name="revanced_spoof_video_streams_ios_force_avc_title">Məcburi AVC (H.264)</string>
<string name="revanced_spoof_client_use_ios_summary_off">Qəbuledici hazÄąrda Android VR\'ə saxtalaşdÄąrÄąlÄąb \n\nYan təsirlərə daxildir:\nâ€ĸ HDR video yoxdur\nâ€ĸ Uşaq videolarÄą oynadÄąlmÄąr\nâ€ĸ Fasilə verilmiş videolar gÃļzlənilmədən davam edə bilər\nâ€ĸ Aşağı keyfiyyətli Shorts axtarma çubuğu miniatÃŧrləri\nâ€ĸ \"YÃŧklə\" fəaliyyət dÃŧyməsi gizlidir\nâ€ĸ Bitiş ekran kartlarÄą gizlidir</string> <string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video kodlaşdÄąrma: AVC (H.264)</string>
<string name="revanced_spoof_client_storyboard_timeout">Client kiçik şəkillərini təqlid etmə əlçatmazdÄąr (API vaxtÄą bitdi)</string> <string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video kodlaşdÄąrma: VP9 və ya AV1</string>
<string name="revanced_spoof_client_storyboard_io_exception">Client kiçik şəkillərini təqlid etmə mÃŧvəqqəti əlçatmazdÄąr: %s</string> <string name="revanced_spoof_video_streams_ios_force_avc_no_hardware_vp9_summary_on">CihazÄąnÄązda VP9 hardware decoding yoxdur və bu ayar, \"Client təqlid etmə\" fəal olduqda həmişə aÃ§ÄąqdÄąr</string>
</patch> <string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">Bunu fəallaşdÄąrmaq, batareya ÃļmrÃŧnÃŧ uzada və oxutmadakÄą ilişmələri dÃŧzəldə bilər.\n\nAVC, maksimum 1080p dəqiqliyinə sahibdir və video oxutma, VP9 və ya AV1-ə gÃļrə daha çox internet datasÄą istifadə edəcək.</string>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. --> <string name="revanced_spoof_video_streams_about_ios_title">iOS təqlidinin yan təsirləri</string>
<patch id="misc.fix.playback.SpoofSignaturePatch"> <string name="revanced_spoof_video_streams_about_ios_summary">â€ĸ Filmlər və ya Ãļdənişli videolar oxudulmaya bilər\nâ€ĸ CanlÄą yayÄąmlar başdan başlayÄąr</string>
<string name="revanced_spoof_video_streams_about_android_vr_title">Android VR təqlidinin yan təsirləri</string>
<string name="revanced_spoof_video_streams_about_android_vr_summary">â€ĸ Səs trek menyusu əskikdir</string>
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

View File

@@ -32,6 +32,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<string name="revanced_settings_confirm_user_dialog_title">Đ’Ņ‹ Ņ…ĐžŅ‡Đ°Ņ†Đĩ ĐŋŅ€Đ°Ņ†ŅĐŗĐŊŅƒŅ†ŅŒ?</string> <string name="revanced_settings_confirm_user_dialog_title">Đ’Ņ‹ Ņ…ĐžŅ‡Đ°Ņ†Đĩ ĐŋŅ€Đ°Ņ†ŅĐŗĐŊŅƒŅ†ŅŒ?</string>
<string name="revanced_settings_reset">ĐĄĐēŅ–ĐŊŅƒŅ†ŅŒ</string> <string name="revanced_settings_reset">ĐĄĐēŅ–ĐŊŅƒŅ†ŅŒ</string>
@@ -42,6 +44,13 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_settings_import_reset">НаĐģĐ°Đ´Ņ‹ ReVanced ҁĐēŅ–ĐŊŅƒŅ‚Ņ‹ да ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊҋ҅</string> <string name="revanced_settings_import_reset">НаĐģĐ°Đ´Ņ‹ ReVanced ҁĐēŅ–ĐŊŅƒŅ‚Ņ‹ да ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊҋ҅</string>
<string name="revanced_settings_import_success">ІĐŧĐŋĐ°Ņ€Ņ‚Đ°Đ˛Đ°ĐŊа %d ĐŊаĐģад</string> <string name="revanced_settings_import_success">ІĐŧĐŋĐ°Ņ€Ņ‚Đ°Đ˛Đ°ĐŊа %d ĐŊаĐģад</string>
<string name="revanced_settings_import_failure_parse">ПаĐŧŅ‹ĐģĐēа Ņ–ĐŧĐŋĐ°Ņ€Ņ‚Ņƒ: %s</string> <string name="revanced_settings_import_failure_parse">ПаĐŧŅ‹ĐģĐēа Ņ–ĐŧĐŋĐ°Ņ€Ņ‚Ņƒ: %s</string>
<string name="revanced_pref_import_export_title">ІĐŧĐŋĐ°Ņ€Ņ‚ / Đ­ĐēҁĐŋĐ°Ņ€Ņ‚</string>
<string name="revanced_pref_import_export_summary">ІĐŧĐŋĐ°Ņ€Ņ‚ / Đ­ĐēҁĐŋĐ°Ņ€Ņ‚ ĐŊаĐģад ReVanced</string>
<!-- Settings about dialog. -->
<string name="revanced_settings_about_links_body">Đ’Ņ‹ Đ˛Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚ĐžŅžĐ˛Đ°Đĩ҆Đĩ вĐĩŅ€ŅŅ–ŅŽ ReVanced Patches &lt;i&gt;%s&lt;/i&gt;</string>
<string name="revanced_settings_about_links_dev_header">ĐĐ°Ņ‚Đ°Ņ‚Đēа</string>
<string name="revanced_settings_about_links_dev_body">Đ“ŅŅ‚Đ°Ņ вĐĩŅ€ŅŅ–Ņ С\"ŅŅžĐģŅĐĩŅ†Ņ†Đ° ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅĐš вĐĩŅ€ŅŅ–ŅĐš, Ņ– Đ˛Ņ‹ ĐŧĐžĐļĐ°Ņ†Đĩ ŅŅƒŅ‚Ņ‹ĐēĐŊŅƒŅ†Ņ†Đ° С ĐŊĐĩĐŋŅ€Đ°Đ´ĐąĐ°Ņ‡Đ°ĐŊŅ‹ĐŧŅ– ĐŋŅ€Đ°ĐąĐģĐĩĐŧаĐŧŅ–</string>
<string name="revanced_settings_about_links_header">ĐŅ„Ņ–Ņ†Ņ‹ĐšĐŊŅ‹Ņ ҁĐŋĐ°ŅŅ‹ĐģĐēŅ–</string>
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
@@ -54,14 +63,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
<string name="revanced_settings_about_links_body">Đ’Ņ‹ Đ˛Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚ĐžŅžĐ˛Đ°Đĩ҆Đĩ вĐĩŅ€ŅŅ–ŅŽ ReVanced Patches &lt;i&gt;%s&lt;/i&gt;</string>
<string name="revanced_settings_about_links_dev_header">ĐĐ°Ņ‚Đ°Ņ‚Đēа</string>
<string name="revanced_settings_about_links_dev_body">Đ“ŅŅ‚Đ°Ņ вĐĩŅ€ŅŅ–Ņ С\"ŅŅžĐģŅĐĩŅ†Ņ†Đ° ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅĐš вĐĩŅ€ŅŅ–ŅĐš, Ņ– Đ˛Ņ‹ ĐŧĐžĐļĐ°Ņ†Đĩ ŅŅƒŅ‚Ņ‹ĐēĐŊŅƒŅ†Ņ†Đ° С ĐŊĐĩĐŋŅ€Đ°Đ´ĐąĐ°Ņ‡Đ°ĐŊŅ‹ĐŧŅ– ĐŋŅ€Đ°ĐąĐģĐĩĐŧаĐŧŅ–</string>
<string name="revanced_settings_about_links_header">ĐŅ„Ņ–Ņ†Ņ‹ĐšĐŊŅ‹Ņ ҁĐŋĐ°ŅŅ‹ĐģĐēŅ–</string>
<string name="revanced_pref_import_export_title">ІĐŧĐŋĐ°Ņ€Ņ‚ / Đ­ĐēҁĐŋĐ°Ņ€Ņ‚</string>
<string name="revanced_pref_import_export_summary">ІĐŧĐŋĐ°Ņ€Ņ‚ / Đ­ĐēҁĐŋĐ°Ņ€Ņ‚ ĐŊаĐģад ReVanced</string>
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
<string name="revanced_settings_screen_00_about_title">ĐŸŅ€Đ° ĐŋŅ€Đ°ĐŗŅ€Đ°Đŧ҃</string> <string name="revanced_settings_screen_00_about_title">ĐŸŅ€Đ° ĐŋŅ€Đ°ĐŗŅ€Đ°Đŧ҃</string>
<string name="revanced_settings_screen_01_ads_title">Ай\"ŅĐ˛Ņ‹</string> <string name="revanced_settings_screen_01_ads_title">Ай\"ŅĐ˛Ņ‹</string>
@@ -211,6 +212,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_info_cards_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ĐšĐŊҋ҅ ĐēĐ°Ņ€Ņ‚</string> <string name="revanced_hide_info_cards_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ĐšĐŊҋ҅ ĐēĐ°Ņ€Ņ‚</string>
<string name="revanced_hide_info_cards_section_summary_on">РаСдСĐĩĐģ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ĐšĐŊҋ҅ ĐēĐ°Ņ€Ņ‚Đ°Đē ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_info_cards_section_summary_on">РаСдСĐĩĐģ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ĐšĐŊҋ҅ ĐēĐ°Ņ€Ņ‚Đ°Đē ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_info_cards_section_summary_off">ПаĐēаСваĐĩŅ†Ņ†Đ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ĐšĐŊҋ҅ ĐēĐ°Ņ€Ņ‚</string> <string name="revanced_hide_info_cards_section_summary_off">ПаĐēаСваĐĩŅ†Ņ†Đ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ĐšĐŊҋ҅ ĐēĐ°Ņ€Ņ‚</string>
<string name="revanced_hide_key_concepts_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ÂĢКĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ ĐŋаĐŊŅŅ†Ņ†Ņ–Âģ</string>
<string name="revanced_hide_key_concepts_section_summary_on">РаСдСĐĩĐģ \"КĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ ĐŋаĐŊŅŅ†Ņ†Ņ–\" ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_key_concepts_section_summary_off">ПаĐēаСаĐŊŅ‹ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ÂĢКĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ ĐŋаĐŊŅŅ†Ņ†Ņ–Âģ</string>
<string name="revanced_hide_transcript_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ŅŅ‚ŅĐŊĐ°ĐŗŅ€Đ°ĐŧŅ‹</string> <string name="revanced_hide_transcript_section_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ŅŅ‚ŅĐŊĐ°ĐŗŅ€Đ°ĐŧŅ‹</string>
<string name="revanced_hide_transcript_section_summary_on">РаСдСĐĩĐģ ŅŅ‚ŅĐŊĐ°ĐŗŅ€Đ°ĐŧŅ‹ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string> <string name="revanced_hide_transcript_section_summary_on">РаСдСĐĩĐģ ŅŅ‚ŅĐŊĐ°ĐŗŅ€Đ°ĐŧŅ‹ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<string name="revanced_hide_transcript_section_summary_off">ПаĐēаСваĐĩŅ†Ņ†Đ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ŅŅ‚ŅĐŊĐ°ĐŗŅ€Đ°ĐŧŅ‹</string> <string name="revanced_hide_transcript_section_summary_off">ПаĐēаСваĐĩŅ†Ņ†Đ° Ņ€Đ°ĐˇĐ´ĐˇĐĩĐģ ŅŅ‚ŅĐŊĐ°ĐŗŅ€Đ°ĐŧŅ‹</string>
@@ -239,14 +243,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_keyword_content_phrases_title">КĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ ҁĐģĐžĐ˛Ņ‹, ŅĐēŅ–Ņ Ņ‚Ņ€ŅĐąĐ° ŅŅ…Đ°Đ˛Đ°Ņ†ŅŒ</string> <string name="revanced_hide_keyword_content_phrases_title">КĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ ҁĐģĐžĐ˛Ņ‹, ŅĐēŅ–Ņ Ņ‚Ņ€ŅĐąĐ° ŅŅ…Đ°Đ˛Đ°Ņ†ŅŒ</string>
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<string name="revanced_hide_keyword_content_phrases_summary">КĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ ҁĐģĐžĐ˛Ņ‹ Ņ– Ņ„Ņ€Đ°ĐˇŅ‹, ŅĐēŅ–Ņ Ņ‚Ņ€ŅĐąĐ° ŅŅ…Đ°Đ˛Đ°Ņ†ŅŒ, ĐŋадСĐĩĐģĐĩĐŊŅ‹Ņ ĐŊĐžĐ˛Ņ‹ĐŧŅ– Ņ€Đ°Đ´ĐēаĐŧŅ–\n\nĐĄĐģĐžĐ˛Ņ‹ С Đ˛ŅĐģŅ–ĐēŅ–ĐŧŅ– ĐģŅ–Ņ‚Đ°Ņ€Đ°ĐŧŅ– ĐŋĐ°ŅŅŅ€ŅĐ´ĐˇŅ–ĐŊĐĩ Ņ‚Ņ€ŅĐąĐ° ŅžĐ˛ĐžĐ´ĐˇŅ–Ņ†ŅŒ С Đ˛ŅĐģŅ–ĐēŅ–Đŧ Ņ€ŅĐŗŅ–ŅŅ‚Ņ€Đ°Đŧ (ĐŊаĐŋҀҋĐēĐģад: iPhone, TikTok, LeBlanc)</string>
<string name="revanced_hide_keyword_content_about_title">Ай ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ‹Ņ– ĐēĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ… ҁĐģĐžŅž</string> <string name="revanced_hide_keyword_content_about_title">Ай ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ‹Ņ– ĐēĐģŅŽŅ‡Đ°Đ˛Ņ‹Ņ… ҁĐģĐžŅž</string>
<string name="revanced_hide_keyword_content_about_summary">ГаĐģĐžŅžĐŊĐ°Ņ/ПадĐŋҖҁĐēа/Đ’Ņ‹ĐŊŅ–ĐēŅ– ĐŋĐžŅˆŅƒĐē҃ ҄ҖĐģŅŒŅ‚Ņ€ŅƒŅŽŅ†Ņ†Đ°, Đēай ŅŅ…Đ°Đ˛Đ°Ņ†ŅŒ СĐŧĐĩŅŅ†Ņ–Đ˛Đ°, ŅĐēĐžĐĩ ҁ҃ĐŋадаĐĩ С ĐēĐģŅŽŅ‡Đ°Đ˛Ņ‹ĐŧŅ– Ņ„Ņ€Đ°ĐˇĐ°ĐŧŅ–\n\nАйĐŧĐĩĐļаваĐŊĐŊŅ–\nâ€ĸ НĐĩĐēĐ°Ņ‚ĐžŅ€Ņ‹Ņ ŅˆĐžŅ€Ņ‚Ņ‹ ĐŧĐžĐŗŅƒŅ†ŅŒ ĐąŅ‹Ņ†ŅŒ ĐŊĐĩ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹\nâ€ĸ НĐĩĐēĐ°Ņ‚ĐžŅ€Ņ‹Ņ ĐēаĐŧĐŋаĐŊĐĩĐŊ҂ҋ ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊҖ҆ĐēĐ°ĐŗĐ° Ņ–ĐŊŅ‚ŅŅ€Ņ„ĐĩĐšŅŅƒ ĐŧĐžĐŗŅƒŅ†ŅŒ ĐąŅ‹Ņ†ŅŒ ĐŊĐĩ ŅŅ…Đ°Đ˛Đ°ĐŊŅ‹\nâ€ĸ ĐŸĐžŅˆŅƒĐē Đŋа ĐēĐģŅŽŅ‡Đ°Đ˛Ņ‹Đŧ ҁĐģОвĐĩ ĐŧĐžĐļа ĐŊĐĩ Đ´Đ°Ņ†ŅŒ Đ˛Ņ‹ĐŊŅ–ĐēĐ°Ņž</string> <!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_common">ĐŅĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊаĐĩ ĐēĐģŅŽŅ‡Đ°Đ˛ĐžĐĩ ҁĐģОва. НĐĩĐŧĐ°ĐŗŅ‡Ņ‹Đŧа Đ˛Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚ĐžŅžĐ˛Đ°Ņ†ŅŒ: \"%s\" ҃ ŅĐēĐ°ŅŅ†Ņ– ҄ҖĐģŅŒŅ‚Ņ€Đ°</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_length">ĐŅĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊаĐĩ ĐēĐģŅŽŅ‡Đ°Đ˛ĐžĐĩ ҁĐģОва. \"%1$s\" СĐŧŅŅˆŅ‡Đ°Đĩ ĐŧĐĩĐŊ҈ Са %2$d ҁҖĐŧваĐģĐ°Ņž</string>
<string name="revanced_hide_keyword_toast_invalid_broad">КĐģŅŽŅ‡Đ°Đ˛ĐžĐĩ ҁĐģОва \"%s\" ŅŅ…Đ°Đ˛Đ°Đĩ ŅžŅĐĩ Đ˛Ņ–Đ´ŅĐ°</string>
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
<string name="revanced_hide_general_ads_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Đ°ĐŗŅƒĐģҌĐŊŅƒŅŽ Ņ€ŅĐēĐģаĐŧ҃</string> <string name="revanced_hide_general_ads_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ Đ°ĐŗŅƒĐģҌĐŊŅƒŅŽ Ņ€ŅĐēĐģаĐŧ҃</string>
@@ -427,7 +426,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_home_button_summary_on">КĐŊĐžĐŋĐēа \"ДадоĐŧ҃\" ŅŅ…Đ°Đ˛Đ°ĐŊа</string> <string name="revanced_hide_home_button_summary_on">КĐŊĐžĐŋĐēа \"ДадоĐŧ҃\" ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_home_button_summary_off">ПаĐēаСаĐŊа ĐēĐŊĐžĐŋĐēа \"ДадоĐŧ҃\".</string> <string name="revanced_hide_home_button_summary_off">ПаĐēаСаĐŊа ĐēĐŊĐžĐŋĐēа \"ДадоĐŧ҃\".</string>
<!-- 'Shorts' should be translated using the same localized wording YouTube displays the tab. --> <!-- 'Shorts' should be translated using the same localized wording YouTube displays the tab. -->
<string name="revanced_hide_shorts_button_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ŅˆĐžŅ€Ņ‚Ņ‹</string> <string name="revanced_hide_shorts_button_title">ĐĄŅ…Đ°Đ˛Đ°Ņ†ŅŒ ĐēĐŊĐžĐŋĐē҃ \"Shorts\"</string>
<string name="revanced_hide_shorts_button_summary_on">КĐŊĐžĐŋĐēа Shorts ŅŅ…Đ°Đ˛Đ°ĐŊа</string> <string name="revanced_hide_shorts_button_summary_on">КĐŊĐžĐŋĐēа Shorts ŅŅ…Đ°Đ˛Đ°ĐŊа</string>
<string name="revanced_hide_shorts_button_summary_off">ПаĐēаСаĐŊа ĐēĐŊĐžĐŋĐēа Shorts</string> <string name="revanced_hide_shorts_button_summary_off">ПаĐēаСаĐŊа ĐēĐŊĐžĐŋĐēа Shorts</string>
<!-- The Create button has no display name. Translate normally. --> <!-- The Create button has no display name. Translate normally. -->
@@ -675,7 +674,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_player_overlay_opacity_invalid_toast">НĐĩĐŋŅ€Đ°ĐˇŅ€Ņ‹ŅŅ‚Đ°ŅŅ†ŅŒ ĐŊаĐēĐģадаĐŊĐŊŅ ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐģҌĐŊŅ–Đēа ĐŋĐ°Đ˛Ņ–ĐŊĐŊа ĐąŅ‹Ņ†ŅŒ ĐŋаĐŧŅ–Đļ 0-100</string> <string name="revanced_player_overlay_opacity_invalid_toast">НĐĩĐŋŅ€Đ°ĐˇŅ€Ņ‹ŅŅ‚Đ°ŅŅ†ŅŒ ĐŊаĐēĐģадаĐŊĐŊŅ ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐģҌĐŊŅ–Đēа ĐŋĐ°Đ˛Ņ–ĐŊĐŊа ĐąŅ‹Ņ†ŅŒ ĐŋаĐŧŅ–Đļ 0-100</string>
</patch> </patch>
<patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch"> <patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch">
<string name="revanced_ryd_video_likes_hidden_by_video_owner">ĐĄŅ…Đ°Đ˛Đ°ĐŊŅ‹</string>
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<string name="revanced_ryd_failure_connection_timeout">АдСĐŊаĐēŅ– \"НĐĩ ĐŋадайаĐĩŅ†Ņ†Đ°\" Ņ‡Đ°ŅĐžĐ˛Đ° ĐŊĐĩĐ´Đ°ŅŅ‚ŅƒĐŋĐŊŅ‹Ņ (Ņ‡Đ°Ņ Ņ‡Đ°ĐēаĐŊĐŊŅ API ҁĐēĐžĐŊŅ‡Ņ‹ŅžŅŅ)</string> <string name="revanced_ryd_failure_connection_timeout">АдСĐŊаĐēŅ– \"НĐĩ ĐŋадайаĐĩŅ†Ņ†Đ°\" Ņ‡Đ°ŅĐžĐ˛Đ° ĐŊĐĩĐ´Đ°ŅŅ‚ŅƒĐŋĐŊŅ‹Ņ (Ņ‡Đ°Ņ Ņ‡Đ°ĐēаĐŊĐŊŅ API ҁĐēĐžĐŊŅ‡Ņ‹ŅžŅŅ)</string>
<string name="revanced_ryd_failure_connection_status_code">Đ”Ņ‹ĐˇĐģаКĐēŅ– ĐŊĐĩĐ´Đ°ŅŅ‚ŅƒĐŋĐŊŅ‹Ņ (ŅŅ‚Đ°Ņ‚ŅƒŅ %d)</string> <string name="revanced_ryd_failure_connection_status_code">Đ”Ņ‹ĐˇĐģаКĐēŅ– ĐŊĐĩĐ´Đ°ŅŅ‚ŅƒĐŋĐŊŅ‹Ņ (ŅŅ‚Đ°Ņ‚ŅƒŅ %d)</string>
@@ -864,14 +862,13 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_new_segment_choose_category">Đ’Ņ‹ĐąĐĩҀҋ҆Đĩ ĐēĐ°Ņ‚ŅĐŗĐžŅ€Ņ‹ŅŽ ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°</string> <string name="revanced_sb_new_segment_choose_category">Đ’Ņ‹ĐąĐĩҀҋ҆Đĩ ĐēĐ°Ņ‚ŅĐŗĐžŅ€Ņ‹ŅŽ ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°</string>
<string name="revanced_sb_new_segment_disabled_category">ĐšĐ°Ņ‚ŅĐŗĐžŅ€Ņ‹Ņ адĐēĐģŅŽŅ‡Đ°ĐŊа Ņž ĐŊаĐģĐ°Đ´Đ°Ņ…. ĐŖĐēĐģŅŽŅ‡Ņ‹Ņ†Đĩ ĐēĐ°Ņ‚ŅĐŗĐžŅ€Ņ‹ŅŽ Đ´ĐģŅ адĐŋŅ€Đ°ŅžĐēŅ–.</string> <string name="revanced_sb_new_segment_disabled_category">ĐšĐ°Ņ‚ŅĐŗĐžŅ€Ņ‹Ņ адĐēĐģŅŽŅ‡Đ°ĐŊа Ņž ĐŊаĐģĐ°Đ´Đ°Ņ…. ĐŖĐēĐģŅŽŅ‡Ņ‹Ņ†Đĩ ĐēĐ°Ņ‚ŅĐŗĐžŅ€Ņ‹ŅŽ Đ´ĐģŅ адĐŋŅ€Đ°ŅžĐēŅ–.</string>
<string name="revanced_sb_new_segment_title">ĐĐžĐ˛Ņ‹ ҁĐĩĐŗĐŧĐĩĐŊŅ‚ SponsorBlock</string> <string name="revanced_sb_new_segment_title">ĐĐžĐ˛Ņ‹ ҁĐĩĐŗĐŧĐĩĐŊŅ‚ SponsorBlock</string>
<string name="revanced_sb_new_segment_mark_time_as_question">ĐŖŅŅ‚Đ°ĐģŅĐ˛Đ°Ņ†ŅŒ %s ҃ ŅĐēĐ°ŅŅ†Ņ– ĐŋĐ°Ņ‡Đ°Ņ‚Đē҃ айО ĐēаĐŊŅ†Đ° ĐŊĐžĐ˛Đ°ĐŗĐ° ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°?</string>
<string name="revanced_sb_new_segment_mark_start">ĐŋĐ°Ņ‡Đ°Ņ†ŅŒ</string> <string name="revanced_sb_new_segment_mark_start">ĐŋĐ°Ņ‡Đ°Ņ†ŅŒ</string>
<string name="revanced_sb_new_segment_mark_end">ĐēаĐŊĐĩ҆</string> <string name="revanced_sb_new_segment_mark_end">ĐēаĐŊĐĩ҆</string>
<string name="revanced_sb_new_segment_now">ĐˇĐ°Ņ€Đ°Đˇ</string> <string name="revanced_sb_new_segment_now">ĐˇĐ°Ņ€Đ°Đˇ</string>
<string name="revanced_sb_new_segment_time_start">Đ§Đ°Ņ ĐŋĐ°Ņ‡Đ°Ņ‚Đē҃ ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°</string> <string name="revanced_sb_new_segment_time_start">Đ§Đ°Ņ ĐŋĐ°Ņ‡Đ°Ņ‚Đē҃ ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°</string>
<string name="revanced_sb_new_segment_time_end">Đ§Đ°Ņ СаĐēаĐŊŅ‡ŅĐŊĐŊŅ ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°</string> <string name="revanced_sb_new_segment_time_end">Đ§Đ°Ņ СаĐēаĐŊŅ‡ŅĐŊĐŊŅ ҁĐĩĐŗĐŧĐĩĐŊŅ‚Đ°</string>
<string name="revanced_sb_new_segment_confirm_title">ĐĻŅ– ĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊŅ‹ Ņ‡Đ°Ņ?</string> <string name="revanced_sb_new_segment_confirm_title">ĐĻŅ– ĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊŅ‹ Ņ‡Đ°Ņ?</string>
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<string name="revanced_sb_new_segment_confirm_content">ĐĄĐĩĐŗĐŧĐĩĐŊŅ‚ ад\n\n%1$s\nда\n%2$s\n\n(%3$s)\n\nĐ“Đ°Ņ‚ĐžĐ˛Ņ‹ адĐŋŅ€Đ°Đ˛Ņ–Ņ†ŅŒ?</string> <string name="revanced_sb_new_segment_confirm_content">ĐĄĐĩĐŗĐŧĐĩĐŊŅ‚ ад\n\n%1$s\nда\n%2$s\n\n(%3$s)\n\nĐ“Đ°Ņ‚ĐžĐ˛Ņ‹ адĐŋŅ€Đ°Đ˛Ņ–Ņ†ŅŒ?</string>
<string name="revanced_sb_new_segment_start_is_before_end">ĐŸĐ°Ņ‡Ņ‹ĐŊĐ°Ņ†ŅŒ Ņ‚Ņ€ŅĐąĐ° Ņ€Đ°ĐŊĐĩĐš Са ĐēаĐŊĐĩ҆</string> <string name="revanced_sb_new_segment_start_is_before_end">ĐŸĐ°Ņ‡Ņ‹ĐŊĐ°Ņ†ŅŒ Ņ‚Ņ€ŅĐąĐ° Ņ€Đ°ĐŊĐĩĐš Са ĐēаĐŊĐĩ҆</string>
<string name="revanced_sb_new_segment_mark_locations_first">ĐĄĐŋĐ°Ņ‡Đ°Ņ‚Đē҃ адСĐŊĐ°Ņ‡Ņ†Đĩ два ĐŧĐĩҁ҆ҋ ĐŊа ĐŋаĐŊŅĐģŅ– Ņ‡Đ°ŅŅƒ</string> <string name="revanced_sb_new_segment_mark_locations_first">ĐĄĐŋĐ°Ņ‡Đ°Ņ‚Đē҃ адСĐŊĐ°Ņ‡Ņ†Đĩ два ĐŧĐĩҁ҆ҋ ĐŊа ĐŋаĐŊŅĐģŅ– Ņ‡Đ°ŅŅƒ</string>
@@ -988,6 +985,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_seekbar_custom_color_invalid">ĐŅĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊаĐĩ СĐŊĐ°Ņ‡ŅĐŊĐŊĐĩ ĐēĐžĐģĐĩŅ€Ņƒ ĐŋаĐŊŅĐģŅ– ĐŋĐžŅˆŅƒĐē҃. Đ’Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚ĐžŅžĐ˛Đ°ĐĩŅ†Ņ†Đ° СĐŊĐ°Ņ‡ŅĐŊĐŊĐĩ Đŋа СĐŧĐ°ŅžŅ‡Đ°ĐŊĐŊŅ–.</string> <string name="revanced_seekbar_custom_color_invalid">ĐŅĐŋŅ€Đ°Đ˛Ņ–ĐģҌĐŊаĐĩ СĐŊĐ°Ņ‡ŅĐŊĐŊĐĩ ĐēĐžĐģĐĩŅ€Ņƒ ĐŋаĐŊŅĐģŅ– ĐŋĐžŅˆŅƒĐē҃. Đ’Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚ĐžŅžĐ˛Đ°ĐĩŅ†Ņ†Đ° СĐŊĐ°Ņ‡ŅĐŊĐŊĐĩ Đŋа СĐŧĐ°ŅžŅ‡Đ°ĐŊĐŊŅ–.</string>
</patch> </patch>
<patch id="layout.thumbnails.BypassImageRegionRestrictions"> <patch id="layout.thumbnails.BypassImageRegionRestrictions">
<string name="revanced_bypass_image_region_restrictions_title">ĐĐąŅ‹Ņ…ĐžĐ´ айĐŧĐĩĐļаваĐŊĐŊŅŅž Ņ€ŅĐŗŅ–Ņ‘ĐŊ҃</string>
<string name="revanced_bypass_image_region_restrictions_summary_on">Đ’Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐŊĐŊĐĩ Ņ…Đ°ŅŅ‚Đ° Đ˛Ņ–Đ´Đ°Ņ€Ņ‹ŅĐ°Ņž yt4.ggpht.com</string>
<string name="revanced_bypass_image_region_restrictions_summary_off">Đ’Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐŊĐŊĐĩ Đ°Ņ€Ņ‹ĐŗŅ–ĐŊаĐģҌĐŊĐ°ĐŗĐ° Ņ…Đ°ŅŅ‚Đ° Đ˛Ņ–Đ´Đ°Ņ€Ņ‹ŅĐ°Ņž\n\nĐŖĐēĐģŅŽŅ‡ŅĐŊĐŊĐĩ ĐŗŅŅ‚Đ°Đš ĐžĐŋ҆ҋҖ ĐŧĐžĐļа Đ˛Ņ‹ĐŋŅ€Đ°Đ˛Ņ–Ņ†ŅŒ Đ°Đ´ŅŅƒŅ‚ĐŊŅ–Ņ‡Đ°ŅŽŅ‡Ņ‹Ņ Đ˛Ņ–Đ´Đ°Ņ€Ņ‹ŅŅ‹, ŅĐēŅ–Ņ СайĐģаĐēŅ–Ņ€Đ°Đ˛Đ°ĐŊŅ‹Ņ Ņž ĐŊĐĩĐēĐ°Ņ‚ĐžŅ€Ņ‹Ņ… Ņ€ŅĐŗŅ–Ņ‘ĐŊĐ°Ņ…</string>
</patch> </patch>
<patch id="layout.thumbnails.AlternativeThumbnailsPatch"> <patch id="layout.thumbnails.AlternativeThumbnailsPatch">
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. --> <!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
@@ -1029,6 +1029,10 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_announcements_connection_failed">НĐĩ ŅžĐ´Đ°ĐģĐžŅŅ ĐŋадĐēĐģŅŽŅ‡Ņ‹Ņ†Ņ†Đ° да ĐŋĐ°ŅŅ‚Đ°ŅžŅˆŅ‡Ņ‹Đēа ай\"ŅŅž</string> <string name="revanced_announcements_connection_failed">НĐĩ ŅžĐ´Đ°ĐģĐžŅŅ ĐŋадĐēĐģŅŽŅ‡Ņ‹Ņ†Ņ†Đ° да ĐŋĐ°ŅŅ‚Đ°ŅžŅˆŅ‡Ņ‹Đēа ай\"ŅŅž</string>
<string name="revanced_announcements_dialog_dismiss">Ņ€Đ°ŅŅĐģĐ°ĐąŅ–Ņ†Ņ†Đ°</string> <string name="revanced_announcements_dialog_dismiss">Ņ€Đ°ŅŅĐģĐ°ĐąŅ–Ņ†Ņ†Đ°</string>
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">ĐŖĐ˛Đ°ĐŗĐ°</string>
<string name="revanced_check_watch_history_domain_name_dialog_ignore">БоĐģҌ҈ ĐŊĐĩ ĐŋаĐēĐ°ĐˇĐ˛Đ°Ņ†ŅŒ</string>
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
<string name="revanced_auto_repeat_title">ĐŖĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ Đ°ŅžŅ‚Đ°ĐŧĐ°Ņ‚Ņ‹Ņ‡ĐŊŅ‹ ĐŋĐ°ŅžŅ‚ĐžŅ€</string> <string name="revanced_auto_repeat_title">ĐŖĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ Đ°ŅžŅ‚Đ°ĐŧĐ°Ņ‚Ņ‹Ņ‡ĐŊŅ‹ ĐŋĐ°ŅžŅ‚ĐžŅ€</string>
<string name="revanced_auto_repeat_summary_on">ĐŅžŅ‚Đ°ĐŧĐ°Ņ‚Ņ‹Ņ‡ĐŊŅ‹ ĐŋĐ°ŅžŅ‚ĐžŅ€ ҃ĐēĐģŅŽŅ‡Đ°ĐŊŅ‹</string> <string name="revanced_auto_repeat_summary_on">ĐŅžŅ‚Đ°ĐŧĐ°Ņ‚Ņ‹Ņ‡ĐŊŅ‹ ĐŋĐ°ŅžŅ‚ĐžŅ€ ҃ĐēĐģŅŽŅ‡Đ°ĐŊŅ‹</string>
@@ -1103,19 +1107,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_slide_to_seek_summary_on">ĐĄĐģаКд Đ´ĐģŅ ĐŋĐžŅˆŅƒĐē҃ ŅžĐēĐģŅŽŅ‡Đ°ĐŊŅ‹</string> <string name="revanced_slide_to_seek_summary_on">ĐĄĐģаКд Đ´ĐģŅ ĐŋĐžŅˆŅƒĐē҃ ŅžĐēĐģŅŽŅ‡Đ°ĐŊŅ‹</string>
<string name="revanced_slide_to_seek_summary_off">ĐĄĐģаКд Đ´ĐģŅ ĐŋĐžŅˆŅƒĐē҃ ĐŊĐĩ ŅžĐēĐģŅŽŅ‡Đ°ĐŊŅ‹</string> <string name="revanced_slide_to_seek_summary_off">ĐĄĐģаКд Đ´ĐģŅ ĐŋĐžŅˆŅƒĐē҃ ĐŊĐĩ ŅžĐēĐģŅŽŅ‡Đ°ĐŊŅ‹</string>
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
<string name="revanced_spoof_client_screen_title">ПадĐŧаĐŊ ĐēĐģŅ–ĐĩĐŊŅ‚Đ°</string> <string name="revanced_spoof_video_streams_user_dialog_message">АдĐēĐģŅŽŅ‡ŅĐŊĐŊĐĩ ĐŗŅŅ‚Đ°Đš ĐŊаĐģĐ°Đ´Ņ‹ ĐŧĐžĐļа Đ˛Ņ‹ĐēĐģŅ–ĐēĐ°Ņ†ŅŒ ĐŋŅ€Đ°ĐąĐģĐĩĐŧŅ‹ С ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊĐĩĐŧ Đ˛Ņ–Đ´ŅĐ°.</string>
<string name="revanced_spoof_client_screen_summary">ĐŸĐ°Đ´Ņ€ĐžĐąĐēа ĐēĐģŅ–ĐĩĐŊŅ‚Đ°, Đēай ĐŋŅ€Đ°Đ´ŅƒŅ…Ņ–ĐģŅ–Ņ†ŅŒ ĐŋŅ€Đ°ĐąĐģĐĩĐŧŅ‹ С ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊĐĩĐŧ</string>
<string name="revanced_spoof_client_title">ПадĐŧаĐŊ ĐēĐģŅ–ĐĩĐŊŅ‚Đ°</string>
<string name="revanced_spoof_client_summary_on">КĐģŅ–ĐĩĐŊŅ‚ ĐŋĐ°Đ´Ņ€ĐžĐąĐģĐĩĐŊŅ‹</string>
<string name="revanced_spoof_client_summary_off">КĐģŅ–ĐĩĐŊŅ‚ ĐŊĐĩ ĐŋĐ°Đ´Ņ€ĐžĐąĐģĐĩĐŊŅ‹\n\nĐŸŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊĐĩ Đ˛Ņ–Đ´ŅĐ° ĐŧĐžĐļа ĐŊĐĩ ĐŋŅ€Đ°Ņ†Đ°Đ˛Đ°Ņ†ŅŒ</string>
<string name="revanced_spoof_client_user_dialog_message">АдĐēĐģŅŽŅ‡ŅĐŊĐŊĐĩ ĐŗŅŅ‚Đ°Đš ĐŊаĐģĐ°Đ´Ņ‹ ĐŧĐžĐļа Đ˛Ņ‹ĐēĐģŅ–ĐēĐ°Ņ†ŅŒ ĐŋŅ€Đ°ĐąĐģĐĩĐŧŅ‹ С ĐŋŅ€Đ°ĐšĐŗŅ€Đ°Đ˛Đ°ĐŊĐŊĐĩĐŧ Đ˛Ņ–Đ´ŅĐ°.</string>
<string name="revanced_spoof_client_use_ios_title">ĐŸĐ°Đ´Ņ€ĐžĐąĐēа ĐēĐģŅ–ĐĩĐŊŅ‚Đ° Đ´ĐģŅ iOS</string>
<string name="revanced_spoof_client_storyboard_timeout">ĐœŅ–ĐŊŅ–ŅŅ†ŅŽŅ€Ņ‹ ĐēĐģŅ–ĐĩĐŊŅ‚Đ° Spoof ĐŊĐĩĐ´Đ°ŅŅ‚ŅƒĐŋĐŊŅ‹Ņ (Ņ‡Đ°Ņ Ņ‡Đ°ĐēаĐŊĐŊŅ API ҁĐēĐžĐŊŅ‡Ņ‹ŅžŅŅ)</string>
<string name="revanced_spoof_client_storyboard_io_exception">ĐœŅ–ĐŊŅ–ŅŅ†ŅŽŅ€Ņ‹ ĐēĐģŅ–ĐĩĐŊŅ‚Đ° Spoof Ņ‡Đ°ŅĐžĐ˛Đ° ĐŊĐĩĐ´Đ°ŅŅ‚ŅƒĐŋĐŊŅ‹Ņ: %s</string>
</patch>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. -->
<patch id="misc.fix.playback.SpoofSignaturePatch">
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
--> -->
<resources> <resources>
<app id="shared"> <app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch"> <patch id="misc.settings.BaseSettingsResourcePatch">
<string name="revanced_settings_confirm_user_dialog_title">āφāĻĒāύāĻŋ āĻ•āĻŋ āĻāĻ—āĻŋā§Ÿā§‡ āϝ⧇āϤ⧇ āχāĻšā§āϛ⧁āĻ•?</string> <string name="revanced_settings_confirm_user_dialog_title">āφāĻĒāύāĻŋ āĻ•āĻŋ āĻāĻ—āĻŋā§Ÿā§‡ āϝ⧇āϤ⧇ āχāĻšā§āϛ⧁āĻ•?</string>
<string name="revanced_settings_reset">āφāĻŦāĻžāϰ āϏ⧇āϟ āĻ•āϰ⧁āύ</string> <string name="revanced_settings_reset">āφāĻŦāĻžāϰ āϏ⧇āϟ āĻ•āϰ⧁āύ</string>
@@ -42,6 +44,13 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_settings_import_reset">ReVanced āϏ⧇āϟāĻŋāĻ‚ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āϏ⧇āϟ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_settings_import_reset">ReVanced āϏ⧇āϟāĻŋāĻ‚ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āϏ⧇āϟ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_settings_import_success">%d āϏ⧇āϟāĻŋāĻ‚ āφāĻŽāĻĻāĻžāύāĻŋ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_settings_import_success">%d āϏ⧇āϟāĻŋāĻ‚ āφāĻŽāĻĻāĻžāύāĻŋ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_settings_import_failure_parse">āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻž āϝāĻžā§ŸāύāĻŋ: %s</string> <string name="revanced_settings_import_failure_parse">āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰāĻž āϝāĻžā§ŸāύāĻŋ: %s</string>
<string name="revanced_pref_import_export_title">āφāĻŽāĻĻāĻžāύāĻŋ āĻāĻŦāĻ‚ āϰāĻĒā§āϤāĻžāύāĻŋ</string>
<string name="revanced_pref_import_export_summary">ReVanced āϏ⧇āϟāĻŋāĻ‚ āφāĻŽāĻĻāĻžāύāĻŋ āĻŦāĻž āϰāĻĒā§āϤāĻžāύāĻŋ āĻ•āϰ⧁āύ</string>
<!-- Settings about dialog. -->
<string name="revanced_settings_about_links_body">āφāĻĒāύāĻŋ ReVanced āĻĒā§āϝāĻžāϚ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ &lt;i&gt;%s&lt;/i&gt; āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϛ⧇āύ</string>
<string name="revanced_settings_about_links_dev_header">āĻĻā§āϰāĻˇā§āϟāĻŦā§āϝ</string>
<string name="revanced_settings_about_links_dev_body">āĻāχ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āĻāĻ•āϟāĻŋ āĻĒā§āϰāĻžāĻ•-āĻĒā§āϰāĻ•āĻžāĻļāύāĻž āĻāĻŦāĻ‚ āĻāϤ⧇ āφāĻĒāύāĻŋ āĻ…āύāĻžāĻ•āĻžāĻ™ā§āĻ–āĻŋāϤ āϏāĻŽāĻ¸ā§āϝāĻžāϰ āϏāĻŽā§āĻŽā§āĻ–āĻŋāύ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āύ</string>
<string name="revanced_settings_about_links_header">āĻ…āĻĢāĻŋāĻļā§āϝāĻžāϞ āϞāĻŋāĻ‚āĻ•āϏāĻŽā§‚āĻš</string>
</patch> </patch>
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch"> <patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
@@ -54,14 +63,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
</patch> </patch>
</app> </app>
<app id="youtube"> <app id="youtube">
<patch id="misc.settings.SettingsResourcePatch">
<string name="revanced_settings_about_links_body">āφāĻĒāύāĻŋ ReVanced āĻĒā§āϝāĻžāϚ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ &lt;i&gt;%s&lt;/i&gt; āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϛ⧇āύ</string>
<string name="revanced_settings_about_links_dev_header">āĻĻā§āϰāĻˇā§āϟāĻŦā§āϝ</string>
<string name="revanced_settings_about_links_dev_body">āĻāχ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ āĻāĻ•āϟāĻŋ āĻĒā§āϰāĻžāĻ•-āĻĒā§āϰāĻ•āĻžāĻļāύāĻž āĻāĻŦāĻ‚ āĻāϤ⧇ āφāĻĒāύāĻŋ āĻ…āύāĻžāĻ•āĻžāĻ™ā§āĻ–āĻŋāϤ āϏāĻŽāĻ¸ā§āϝāĻžāϰ āϏāĻŽā§āĻŽā§āĻ–āĻŋāύ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āύ</string>
<string name="revanced_settings_about_links_header">āĻ…āĻĢāĻŋāĻļā§āϝāĻžāϞ āϞāĻŋāĻ‚āĻ•āϏāĻŽā§‚āĻš</string>
<string name="revanced_pref_import_export_title">āφāĻŽāĻĻāĻžāύāĻŋ āĻāĻŦāĻ‚ āϰāĻĒā§āϤāĻžāύāĻŋ</string>
<string name="revanced_pref_import_export_summary">ReVanced āϏ⧇āϟāĻŋāĻ‚ āφāĻŽāĻĻāĻžāύāĻŋ āĻŦāĻž āϰāĻĒā§āϤāĻžāύāĻŋ āĻ•āϰ⧁āύ</string>
</patch>
<patch id="misc.settings.SettingsPatch"> <patch id="misc.settings.SettingsPatch">
<string name="revanced_settings_screen_00_about_title">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ</string> <string name="revanced_settings_screen_00_about_title">āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ</string>
<string name="revanced_settings_screen_01_ads_title">āĻŦāĻŋāĻœā§āĻžāĻžāĻĒāύ</string> <string name="revanced_settings_screen_01_ads_title">āĻŦāĻŋāĻœā§āĻžāĻžāĻĒāύ</string>
@@ -201,6 +202,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_chips_shelf_summary_off">āϚāĻŋāĻĒ āĻļ⧇āϞāĻĒ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_chips_shelf_summary_off">āϚāĻŋāĻĒ āĻļ⧇āϞāĻĒ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_attributes_section_title">āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_attributes_section_title">āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āĻŦāĻŋāĻ­āĻžāĻ— āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_attributes_section_summary_on">\'āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϝ⧁āĻ•ā§āϤ āĻ¸ā§āĻĨāĻžāύ\', āϗ⧇āĻŽ āĻāĻŦāĻ‚ āϏāĻ™ā§āĻ—ā§€āϤ āĻŦāĻŋāĻ­āĻžāĻ—āϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string> <string name="revanced_hide_attributes_section_summary_on">\'āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϝ⧁āĻ•ā§āϤ āĻ¸ā§āĻĨāĻžāύ\', āϗ⧇āĻŽ āĻāĻŦāĻ‚ āϏāĻ™ā§āĻ—ā§€āϤ āĻŦāĻŋāĻ­āĻžāĻ—āϗ⧁āϞāĻŋ āϞ⧁āĻ•āĻžāύ⧋ āφāϛ⧇</string>
<string name="revanced_hide_attributes_section_summary_off">\'āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϝ⧁āĻ•ā§āϤ āĻ¸ā§āĻĨāĻžāύ\', āϗ⧇āĻŽ āĻāĻŦāĻ‚ āϏāĻ™ā§āĻ—ā§€āϤ āĻŦāĻŋāĻ­āĻžāĻ—āϗ⧁āϞāĻŋ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_info_cards_section_title">āϤāĻĨā§āϝ āĻ•āĻžāĻ°ā§āĻĄ āϏ⧇āĻ•āĻļāύ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_info_cards_section_title">āϤāĻĨā§āϝ āĻ•āĻžāĻ°ā§āĻĄ āϏ⧇āĻ•āĻļāύ āϞ⧁āĻ•āĻžāύ</string>
<string name="revanced_hide_info_cards_section_summary_on">āϤāĻĨā§āϝ āĻ•āĻžāĻ°ā§āĻĄ āϏ⧇āĻ•āĻļāύ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_info_cards_section_summary_on">āϤāĻĨā§āϝ āĻ•āĻžāĻ°ā§āĻĄ āϏ⧇āĻ•āĻļāύ āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<string name="revanced_hide_info_cards_section_summary_off">āϤāĻĨā§āϝ āĻ•āĻžāĻ°ā§āĻĄ āϏ⧇āĻ•āĻļāύ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_hide_info_cards_section_summary_off">āϤāĻĨā§āϝ āĻ•āĻžāĻ°ā§āĻĄ āϏ⧇āĻ•āĻļāύ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇</string>
@@ -231,13 +233,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_keyword_content_phrases_title">āϞ⧁āĻ•āĻžāύ⧋āϰ āϜāĻ¨ā§āϝ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ</string> <string name="revanced_hide_keyword_content_phrases_title">āϞ⧁āĻ•āĻžāύ⧋āϰ āϜāĻ¨ā§āϝ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ</string>
<!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word. <!-- For localization it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
This is because keywords can be in any language, and showing an example in the localized script helps convey this. --> This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
<string name="revanced_hide_keyword_content_phrases_summary">āϞ⧁āĻ•āĻžāύ⧋āϰ āϜāĻ¨ā§āϝ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āĻāĻŦāĻ‚ āĻŦāĻžāĻ•ā§āϝāĻžāĻ‚āĻļ, āύāϤ⧁āύ āϞāĻžāχāύ⧇ āĻĒ⧃āĻĨāĻ• āĻ•āϰāĻž\n\nāĻļāĻŦā§āĻĻ⧇āϰ āĻŽāĻžāĻā§‡ āĻŦ⧜ āĻšāĻžāϤ⧇āϰ āĻ…āĻ•ā§āώāϰ āĻĨāĻžāĻ•āϞ⧇ āϤāĻž āĻ…āĻŦāĻļā§āϝāχ āϏāĻ āĻŋāĻ• āφāĻŦāϰāϪ⧇ āϞāĻŋāĻ–āϤ⧇ āĻšāĻŦ⧇ (āωāĻĻāĻžāĻšāϰāĻŖ: iPhone, TikTok, LeBlanc)</string>
<string name="revanced_hide_keyword_content_about_title">āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āĻĢāĻŋāĻ˛ā§āϟāĻžāϰāĻŋāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇</string> <string name="revanced_hide_keyword_content_about_title">āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āĻĢāĻŋāĻ˛ā§āϟāĻžāϰāĻŋāĻ‚ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇</string>
<string name="revanced_hide_keyword_content_about_summary">āĻĒā§āϰāϧāĻžāύ āĻĒāĻžāϤāĻž/āϏāĻžāĻŦāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒāĻļāύ/āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻĢāϞāĻžāĻĢāϞ āϗ⧁āϞ⧋ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āĻŦāĻžāĻ•ā§āϝāĻžāĻ‚āĻļ⧇āϰ āϏāĻžāĻĨ⧇ āĻŽāĻŋāϞāĻŋā§Ÿā§‡ āϞ⧁āĻ•āĻžāύ⧋āϰ āϜāĻ¨ā§āϝ āĻĢāĻŋāĻ˛ā§āϟāĻžāϰ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇\n\nāϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻž\nâ€ĸ āĻ•āĻŋāϛ⧁ Shorts āύāĻžāĻ“ āϞ⧁āĻ•āĻžāύ⧋ āĻšāϤ⧇ āĻĒāĻžāϰ⧇\nâ€ĸ āĻ•āĻŋāϛ⧁ āχāωāφāχ āωāĻĒāĻžāĻĻāĻžāύ āύāĻžāĻ“ āϞ⧁āĻ•āĻžāύ⧋ āĻšāϤ⧇ āĻĒāĻžāϰ⧇\nâ€ĸ āϕ⧋āύ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āϏāĻžāĻ°ā§āϚ āĻ•āϰāϞ⧇ āϕ⧋āύ āĻĢāϞāĻžāĻĢāϞ āύāĻžāĻ“ āĻĻ⧇āĻ–āĻžāϤ⧇ āĻĒāĻžāϰ⧇</string> <!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. --> <!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_common">āĻ…āĻŦ⧈āϧ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄ āĻĢāĻŋāĻ˛ā§āϟāĻžāϰ \'%s\' āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻž</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_length">āĻ¤ā§āϰ⧁āϟāĻŋāĻĒā§‚āĻ°ā§āĻŖ āϕ⧀āĻ“ā§ŸāĻžāĻ°ā§āĻĄāĨ¤ \'%1$s\' āϟāĻŋ %2$d āĻ…āĻ•ā§āώāϰ āĻĨ⧇āϕ⧇ āĻ•āĻŽ</string>
</patch> </patch>
<patch id="ad.general.HideAdsResourcePatch"> <patch id="ad.general.HideAdsResourcePatch">
<string name="revanced_hide_general_ads_title">āϏāĻžāϧāĻžāϰāĻŖ āĻŦāĻŋāĻœā§āĻžāĻžāĻĒāύ āϞ⧁āĻ•āĻžāύ</string> <string name="revanced_hide_general_ads_title">āϏāĻžāϧāĻžāϰāĻŖ āĻŦāĻŋāĻœā§āĻžāĻžāĻĒāύ āϞ⧁āĻ•āĻžāύ</string>
@@ -603,7 +601,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_player_overlay_opacity_invalid_toast">āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ“āĻ­āĻžāϰāϞ⧇ āĻ…āĻ¸ā§āĻŦāĻšā§āĻ›āϤāĻž āĻ…āĻŦāĻļā§āϝāχ ā§Ļ-ā§§ā§Ļā§Ļ āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻšāϤ⧇ āĻšāĻŦ⧇</string> <string name="revanced_player_overlay_opacity_invalid_toast">āĻĒā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ“āĻ­āĻžāϰāϞ⧇ āĻ…āĻ¸ā§āĻŦāĻšā§āĻ›āϤāĻž āĻ…āĻŦāĻļā§āϝāχ ā§Ļ-ā§§ā§Ļā§Ļ āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻšāϤ⧇ āĻšāĻŦ⧇</string>
</patch> </patch>
<patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch"> <patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch">
<string name="revanced_ryd_video_likes_hidden_by_video_owner">āϞ⧁āĻ•āĻŋā§Ÿā§‡ āĻ°ā§Ÿā§‡āϛ⧇</string>
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. --> <!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
<string name="revanced_ryd_failure_connection_timeout">āĻ…āĻĒāĻ›āĻ¨ā§āĻĻ āϏāĻžāĻŽā§ŸāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āωāĻĒāϞāĻ­ā§āϝ āύ⧟ (API āϏāĻŽā§Ÿ āĻļ⧇āώ āĻšā§Ÿā§‡āϛ⧇)</string> <string name="revanced_ryd_failure_connection_timeout">āĻ…āĻĒāĻ›āĻ¨ā§āĻĻ āϏāĻžāĻŽā§ŸāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āωāĻĒāϞāĻ­ā§āϝ āύ⧟ (API āϏāĻŽā§Ÿ āĻļ⧇āώ āĻšā§Ÿā§‡āϛ⧇)</string>
<string name="revanced_ryd_failure_connection_status_code">āĻ…āĻĒāĻ›āĻ¨ā§āĻĻ āωāĻĒāϞāĻ­ā§āϝ āύ⧟ (āĻ…āĻŦāĻ¸ā§āĻĨāĻž %d)</string> <string name="revanced_ryd_failure_connection_status_code">āĻ…āĻĒāĻ›āĻ¨ā§āĻĻ āωāĻĒāϞāĻ­ā§āϝ āύ⧟ (āĻ…āĻŦāĻ¸ā§āĻĨāĻž %d)</string>
@@ -798,8 +795,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_sb_new_segment_time_start">āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻļ⧁āϰ⧁ āĻšāĻ“āϝāĻŧāĻžāϰ āϏāĻŽāϝāĻŧ</string> <string name="revanced_sb_new_segment_time_start">āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻļ⧁āϰ⧁ āĻšāĻ“āϝāĻŧāĻžāϰ āϏāĻŽāϝāĻŧ</string>
<string name="revanced_sb_new_segment_time_end">āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āϏāĻŽāϝāĻŧ</string> <string name="revanced_sb_new_segment_time_end">āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āϏāĻŽāϝāĻŧ</string>
<string name="revanced_sb_new_segment_confirm_title">āϏāĻŽāϝāĻŧāĻ•āĻžāϞ āĻ•āĻŋ āϏāĻ āĻŋāĻ•?</string> <string name="revanced_sb_new_segment_confirm_title">āϏāĻŽāϝāĻŧāĻ•āĻžāϞ āĻ•āĻŋ āϏāĻ āĻŋāĻ•?</string>
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
<string name="revanced_sb_new_segment_confirm_content">āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āϟ āϏāĻŽā§ŸāĻ•āĻžāϞ\n\n%1$s\nāĻĨ⧇āϕ⧇\n%2$s\n\n(%3$s)\n\nāϜāĻŽāĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ?</string> <string name="revanced_sb_new_segment_confirm_content">āϏ⧇āĻ—āĻŽā§‡āĻ¨ā§āϟ āϏāĻŽā§ŸāĻ•āĻžāϞ\n\n%1$s\nāĻĨ⧇āϕ⧇\n%2$s\n\n(%3$s)\n\nāϜāĻŽāĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāĻ¸ā§āϤ⧁āϤ?</string>
<string name="revanced_sb_new_segment_start_is_before_end">āĻļ⧁āϰ⧁ āĻ…āĻŦāĻļā§āϝāχ āĻļ⧇āώ⧇āϰ āφāϗ⧇ āĻšāϤ⧇ āĻšāĻŦ⧇</string> <string name="revanced_sb_new_segment_start_is_before_end">āĻļ⧁āϰ⧁ āĻ…āĻŦāĻļā§āϝāχ āĻļ⧇āώ⧇āϰ āφāϗ⧇ āĻšāϤ⧇ āĻšāĻŦ⧇</string>
<string name="revanced_sb_new_segment_mark_locations_first">āφāϗ⧇ āϏāĻŽā§Ÿ āĻŦāĻžāϰ⧇ āĻĻ⧁āϟāĻŋ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ</string> <string name="revanced_sb_new_segment_mark_locations_first">āφāϗ⧇ āϏāĻŽā§Ÿ āĻŦāĻžāϰ⧇ āĻĻ⧁āϟāĻŋ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ</string>
@@ -958,6 +953,10 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_announcements_connection_failed">āĻ˜ā§‹āώāύāĻžāĻĻāĻžāϤāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ• āĻ¸ā§āĻĨāĻžāĻĒāύ āĻŦā§āϝāĻ°ā§āĻĨ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_announcements_connection_failed">āĻ˜ā§‹āώāύāĻžāĻĻāĻžāϤāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ• āĻ¸ā§āĻĨāĻžāĻĒāύ āĻŦā§āϝāĻ°ā§āĻĨ āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_announcements_dialog_dismiss">āĻŦāĻžāϤāĻŋāϞ āĻ•āϰ⧁āύ</string> <string name="revanced_announcements_dialog_dismiss">āĻŦāĻžāϤāĻŋāϞ āĻ•āϰ⧁āύ</string>
</patch> </patch>
<patch id="misc.dns.CheckWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">āϏāϤāĻ°ā§āϕ⧀āĻ•āϰāĻŖ</string>
<string name="revanced_check_watch_history_domain_name_dialog_ignore">āφāĻŦāĻžāϰ āĻĻ⧇āĻ–āĻžāĻŦ⧇āύ āύāĻž</string>
</patch>
<patch id="misc.autorepeat.AutoRepeatPatch"> <patch id="misc.autorepeat.AutoRepeatPatch">
<string name="revanced_auto_repeat_title">āĻ¸ā§āĻŦ⧟āĻ‚āĻ•ā§āϰāĻŋ⧟āĻ­āĻžāĻŦ⧇-āφāĻŦāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āϏāĻ•ā§āϰāĻŋ⧟ āĻ•āϰ⧁āύ</string> <string name="revanced_auto_repeat_title">āĻ¸ā§āĻŦ⧟āĻ‚āĻ•ā§āϰāĻŋ⧟āĻ­āĻžāĻŦ⧇-āφāĻŦāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āϏāĻ•ā§āϰāĻŋ⧟ āĻ•āϰ⧁āύ</string>
<string name="revanced_auto_repeat_summary_on">āĻ¸ā§āĻŦ⧟āĻ‚āĻ•ā§āϰāĻŋ⧟āĻ­āĻžāĻŦ⧇-āφāĻŦāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āϏāĻ•ā§āϰāĻŋ⧟ āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_auto_repeat_summary_on">āĻ¸ā§āĻŦ⧟āĻ‚āĻ•ā§āϰāĻŋ⧟āĻ­āĻžāĻŦ⧇-āφāĻŦāĻžāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āϏāĻ•ā§āϰāĻŋ⧟ āĻšā§Ÿā§‡āϛ⧇</string>
@@ -1032,19 +1031,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_slide_to_seek_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļ⧇ āϝ⧇āϤ⧇ āϟāĻžāύ⧁āύ āϏāĻ•ā§āϰāĻŋ⧟ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇</string> <string name="revanced_slide_to_seek_summary_on">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļ⧇ āϝ⧇āϤ⧇ āϟāĻžāύ⧁āύ āϏāĻ•ā§āϰāĻŋ⧟ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_slide_to_seek_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļ⧇ āϝ⧇āϤ⧇ āϟāĻžāύ⧁āύ āϏāĻ•ā§āϰāĻŋ⧟ āĻ•āϰāĻž āĻšā§ŸāύāĻŋ</string> <string name="revanced_slide_to_seek_summary_off">āĻ­āĻŋāĻĄāĻŋāĻ“āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļ⧇ āϝ⧇āϤ⧇ āϟāĻžāύ⧁āύ āϏāĻ•ā§āϰāĻŋ⧟ āĻ•āϰāĻž āĻšā§ŸāύāĻŋ</string>
</patch> </patch>
<patch id="misc.fix.playback.SpoofClientPatch"> <patch id="misc.fix.playback.SpoofVideoStreamsPatch">
<string name="revanced_spoof_client_screen_title">āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻ¸ā§āĻĒ⧁āĻĢ āĻ•āϰ⧁āύ</string> <string name="revanced_spoof_video_streams_user_dialog_message">āĻāχ āϏ⧇āϟāĻŋāĻ‚āϟāĻŋ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻžāϰ āĻĢāϞ⧇ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ¤ā§āϰ⧁āϟāĻŋ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤</string>
<string name="revanced_spoof_client_screen_summary">āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āϏāĻŽāĻ¸ā§āϝāĻž āĻĒā§āϰāϤāĻŋāϰ⧋āϧ āĻ•āϰāϤ⧇ āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻ¸ā§āĻĒ⧁āĻĢ āĻ•āϰ⧁āύ</string>
<string name="revanced_spoof_client_title">āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻ¸ā§āĻĒ⧁āĻĢ āĻ•āϰ⧁āύ</string>
<string name="revanced_spoof_client_summary_on">āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻ¸ā§āĻĒ⧁āĻĢ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇</string>
<string name="revanced_spoof_client_summary_off">āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻ¸ā§āĻĒ⧁āĻĢ āĻ•āϰāĻž āĻšā§ŸāύāĻŋ\n\nāĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ āĻŋāĻ•āĻŽāϤ⧋ āĻ•āĻžāϜ āύāĻžāĻ“ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇</string>
<string name="revanced_spoof_client_user_dialog_message">āĻāχ āϏ⧇āϟāĻŋāĻ‚āϟāĻŋ āĻŦāĻ¨ā§āϧ āĻ•āϰāĻžāϰ āĻĢāϞ⧇ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻĒā§āϞ⧇āĻŦā§āϝāĻžāĻ• āĻ¤ā§āϰ⧁āϟāĻŋ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤</string>
<string name="revanced_spoof_client_use_ios_title">āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ iOS āĻ āĻ¸ā§āĻĒ⧁āĻĢ āĻ•āϰ⧁āύ</string>
<string name="revanced_spoof_client_storyboard_timeout">āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻ¸ā§āĻĒ⧁āĻĢ āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāĻžāĻŽā§ŸāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āωāĻĒāϞāĻ­ā§āϝ āύ⧟ (API āϏāĻŽā§Ÿ āĻļ⧇āώ āĻšā§Ÿā§‡āϛ⧇)</string>
<string name="revanced_spoof_client_storyboard_io_exception">āĻ¸ā§āĻĒ⧁āĻĢ āĻ•ā§āϞāĻžā§Ÿā§‡āĻ¨ā§āϟ āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāĻžāĻŽā§ŸāĻŋāĻ•āĻ­āĻžāĻŦ⧇ āωāĻĒāϞāĻ­ā§āϝ āύ⧟: %s</string>
</patch>
<!-- This patch is no longer used, these strings are not in use, and these strings will be deleted in the future. -->
<patch id="misc.fix.playback.SpoofSignaturePatch">
</patch> </patch>
<!-- This patch is no longer used and these strings will soon be deleted. --> <!-- This patch is no longer used and these strings will soon be deleted. -->
<patch id="video.hdrbrightness.HDRBrightnessPatch"> <patch id="video.hdrbrightness.HDRBrightnessPatch">

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