Compare commits

..

43 Commits

Author SHA1 Message Date
semantic-release-bot
729997ec3e chore: Release v5.40.0-dev.3 [skip ci]
# [5.40.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.40.0-dev.2...v5.40.0-dev.3) (2025-09-19)

### Bug Fixes

* **Instagram - Limit feed to followed profiles:** Change patch to default off ([767f1e3](767f1e3695))
2025-09-19 15:43:08 +00:00
LisoUseInAIKyrios
767f1e3695 fix(Instagram - Limit feed to followed profiles): Change patch to default off
Co-authored-by: brosssh <44944126+brosssh@users.noreply.github.com>
2025-09-19 19:40:32 +04:00
github-actions[bot]
7857876551 chore: Sync translations (#5933) 2025-09-19 19:40:03 +04:00
semantic-release-bot
04057c6e56 chore: Release v5.40.0-dev.2 [skip ci]
# [5.40.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.40.0-dev.1...v5.40.0-dev.2) (2025-09-18)

### Features

* **Instagram:** Add `Limit feed to followed profiles` patch ([#5908](https://github.com/ReVanced/revanced-patches/issues/5908)) ([8ba9a19](8ba9a19ade))
2025-09-18 06:16:27 +00:00
brosssh
8ba9a19ade feat(Instagram): Add Limit feed to followed profiles patch (#5908) 2025-09-18 10:13:46 +04:00
LisoUseInAIKyrios
6862200a28 chore: Fix api dump 2025-09-17 23:42:11 +04:00
semantic-release-bot
dfff3d7c0a chore: Release v5.40.0-dev.1 [skip ci]
# [5.40.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.39.1-dev.1...v5.40.0-dev.1) (2025-09-17)

### Features

* **Viber - Hide ads:** Support latest app target ([#5863](https://github.com/ReVanced/revanced-patches/issues/5863)) ([e6cce85](e6cce85541))
2025-09-17 17:54:19 +00:00
Samo Hribar
e6cce85541 feat(Viber - Hide ads): Support latest app target (#5863) 2025-09-17 21:51:33 +04:00
github-actions[bot]
8502eb8eac chore: Sync translations (#5918) 2025-09-17 21:51:15 +04:00
semantic-release-bot
0652c56d0d chore: Release v5.39.1-dev.1 [skip ci]
## [5.39.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.39.0...v5.39.1-dev.1) (2025-09-17)

### Bug Fixes

* **YouTube - Force original audio:** Show UI setting summary if spoofing to Android Studio ([b7026b7](b7026b7086))
2025-09-17 16:18:22 +00:00
LisoUseInAIKyrios
b7026b7086 fix(YouTube - Force original audio): Show UI setting summary if spoofing to Android Studio 2025-09-17 20:13:44 +04:00
semantic-release-bot
fa4f422a15 chore: Release v5.39.0 [skip ci]
# [5.39.0](https://github.com/ReVanced/revanced-patches/compare/v5.38.0...v5.39.0) (2025-09-17)

### Bug Fixes

* **YouTube - Spoof video streams:** Do not use Android Creator for livestreams ([cbe576b](cbe576bc38))
* **YouTube - Spoof video streams:** Show Android Studio in spoof stream menu ([c9f741e](c9f741e616))
* **YouTube Music - Spoof video streams:** Remove iPadOS client ([7eeffd3](7eeffd3392))

### Features

* **YouTube - Hide video action buttons:** Add "Hide Shop button" setting ([a84db7b](a84db7be7f))
2025-09-17 09:15:36 +00:00
LisoUseInAIKyrios
38e0cbd724 chore: Merge branch dev to main (#5907) 2025-09-17 13:12:21 +04:00
semantic-release-bot
0bdebd927d chore: Release v5.39.0-dev.2 [skip ci]
# [5.39.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.39.0-dev.1...v5.39.0-dev.2) (2025-09-17)

### Bug Fixes

* **YouTube - Spoof video streams:** Show Android Studio in spoof stream menu ([c9f741e](c9f741e616))
2025-09-17 09:01:12 +00:00
github-actions[bot]
3eac25cf7f chore: Sync translations (#5914) 2025-09-17 12:56:47 +04:00
LisoUseInAIKyrios
c9f741e616 fix(YouTube - Spoof video streams): Show Android Studio in spoof stream menu 2025-09-17 12:54:52 +04:00
semantic-release-bot
cba44ccfc8 chore: Release v5.39.0-dev.1 [skip ci]
# [5.39.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.38.1-dev.2...v5.39.0-dev.1) (2025-09-17)

### Features

* **YouTube - Hide video action buttons:** Add "Hide Shop button" setting ([a84db7b](a84db7be7f))
2025-09-17 07:19:06 +00:00
LisoUseInAIKyrios
a84db7be7f feat(YouTube - Hide video action buttons): Add "Hide Shop button" setting 2025-09-17 11:14:24 +04:00
semantic-release-bot
2520129ace chore: Release v5.38.1-dev.2 [skip ci]
## [5.38.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.38.1-dev.1...v5.38.1-dev.2) (2025-09-16)

### Bug Fixes

* **YouTube Music - Spoof video streams:** Remove iPadOS client ([7eeffd3](7eeffd3392))
2025-09-16 21:49:36 +00:00
LisoUseInAIKyrios
7eeffd3392 fix(YouTube Music - Spoof video streams): Remove iPadOS client 2025-09-17 01:44:48 +04:00
LisoUseInAIKyrios
6c3391164e chore: Remove spoof stream data migration since iPadOS can cause 1 minute playback failure for users in some regions 2025-09-16 23:44:01 +04:00
semantic-release-bot
0b8b46c73e chore: Release v5.38.1-dev.1 [skip ci]
## [5.38.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.38.0...v5.38.1-dev.1) (2025-09-16)

### Bug Fixes

* **YouTube - Spoof video streams:** Do not use Android Creator for livestreams ([cbe576b](cbe576bc38))
2025-09-16 19:27:03 +00:00
LisoUseInAIKyrios
cbe576bc38 fix(YouTube - Spoof video streams): Do not use Android Creator for livestreams 2025-09-16 23:24:07 +04:00
github-actions[bot]
3a29f2a805 chore: Sync translations (#5909) 2025-09-16 23:21:01 +04:00
LisoUseInAIKyrios
50069c7e05 chore: Fix merge typo 2025-09-16 17:26:48 +04:00
semantic-release-bot
2e9c9dc244 chore: Release v5.38.0 [skip ci]
# [5.38.0](https://github.com/ReVanced/revanced-patches/compare/v5.37.0...v5.38.0) (2025-09-16)

### Bug Fixes

* **Instagram - Hide navigation buttons:** Support v397.1.0.52.81 ([#5855](https://github.com/ReVanced/revanced-patches/issues/5855)) ([f11d1ef](f11d1ef990))
* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](abe3943f98))
* **YouTube - Spoof video streams:** Show settings summary if `Force original audio` is enabled ([3776dda](3776dda710))
* **YouTube Music - Spoof video streams:** Fix playback issues when using a cellular network ([fa04c8e](fa04c8eecf))
* **YouTube Music:** Use correct light/dark mode settings UI ([1475643](1475643f84))

### Features

* **Instagram:** Add `Hide explore feed` patch ([#5856](https://github.com/ReVanced/revanced-patches/issues/5856)) ([1d65887](1d65887e01))
* **YouTube - Spoof video streams:** Add iPadOS client ([2726231](2726231404))
* **YouTube Music:** Add `Settings` patch ([#5838](https://github.com/ReVanced/revanced-patches/issues/5838)) ([5e20bd8](5e20bd80f1))
2025-09-16 13:01:23 +00:00
LisoUseInAIKyrios
56166896d9 chore: Merge branch dev to main (#5857) 2025-09-16 16:57:55 +04:00
semantic-release-bot
b4c695b1d5 chore: Release v5.38.0-dev.5 [skip ci]
# [5.38.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.4...v5.38.0-dev.5) (2025-09-16)

### Bug Fixes

* **YouTube Music:** Use correct light/dark mode settings UI ([1475643](1475643f84))
2025-09-16 12:34:52 +00:00
LisoUseInAIKyrios
1475643f84 fix(YouTube Music): Use correct light/dark mode settings UI 2025-09-16 16:31:04 +04:00
github-actions[bot]
9a7179f9cf chore: Sync translations (#5906) 2025-09-16 16:29:53 +04:00
semantic-release-bot
6fb94a7a41 chore: Release v5.38.0-dev.4 [skip ci]
# [5.38.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.3...v5.38.0-dev.4) (2025-09-16)

### Bug Fixes

* **YouTube - Spoof video streams:** Show settings summary if `Force original audio` is enabled ([3776dda](3776dda710))
2025-09-16 12:05:23 +00:00
LisoUseInAIKyrios
3776dda710 fix(YouTube - Spoof video streams): Show settings summary if Force original audio is enabled 2025-09-16 15:59:32 +04:00
LisoUseInAIKyrios
f88b3a5162 refactor(YouTube - Spoof video streams): Adjust preferred client order 2025-09-16 15:40:55 +04:00
semantic-release-bot
0eeaf7ad67 chore: Release v5.38.0-dev.3 [skip ci]
# [5.38.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.2...v5.38.0-dev.3) (2025-09-16)

### Features

* **YouTube - Spoof video streams:** Add iPadOS client ([2726231](2726231404))
2025-09-16 11:36:54 +00:00
LisoUseInAIKyrios
2726231404 feat(YouTube - Spoof video streams): Add iPadOS client 2025-09-16 15:33:55 +04:00
github-actions[bot]
9f0558e494 chore: Sync translations (#5905) 2025-09-16 15:11:04 +04:00
semantic-release-bot
01f7bc9f8d chore: Release v5.38.0-dev.2 [skip ci]
# [5.38.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.1...v5.38.0-dev.2) (2025-09-16)

### Features

* **YouTube Music:** Add `Settings` patch ([#5838](https://github.com/ReVanced/revanced-patches/issues/5838)) ([5e20bd8](5e20bd80f1))
2025-09-16 06:57:43 +00:00
MarcaD
5e20bd80f1 feat(YouTube Music): Add Settings patch (#5838)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2025-09-16 10:53:49 +04:00
semantic-release-bot
f304c178e2 chore: Release v5.38.0-dev.1 [skip ci]
# [5.38.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.3...v5.38.0-dev.1) (2025-09-15)

### Features

* **Instagram:** Add `Hide explore feed` patch ([#5856](https://github.com/ReVanced/revanced-patches/issues/5856)) ([1d65887](1d65887e01))
2025-09-15 19:30:52 +00:00
brosssh
1d65887e01 feat(Instagram): Add Hide explore feed patch (#5856) 2025-09-15 23:28:01 +04:00
github-actions[bot]
6b6eea8414 chore: Sync translations (#5864) 2025-09-15 23:26:07 +04:00
semantic-release-bot
1db131e90e chore: Release v5.37.1-dev.3 [skip ci]
## [5.37.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.2...v5.37.1-dev.3) (2025-09-15)

### Bug Fixes

* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](abe3943f98))
2025-09-15 17:02:01 +00:00
LisoUseInAIKyrios
abe3943f98 fix(Spoof video streams): Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for Force original audio to work with any spoof client (#5861) 2025-09-15 20:58:56 +04:00
168 changed files with 6225 additions and 2570 deletions

View File

@@ -1,3 +1,133 @@
# [5.40.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.40.0-dev.2...v5.40.0-dev.3) (2025-09-19)
### Bug Fixes
* **Instagram - Limit feed to followed profiles:** Change patch to default off ([767f1e3](https://github.com/ReVanced/revanced-patches/commit/767f1e3695327bdbc4daea8b50a80d4c0a38456a))
# [5.40.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.40.0-dev.1...v5.40.0-dev.2) (2025-09-18)
### Features
* **Instagram:** Add `Limit feed to followed profiles` patch ([#5908](https://github.com/ReVanced/revanced-patches/issues/5908)) ([8ba9a19](https://github.com/ReVanced/revanced-patches/commit/8ba9a19ade24c5fe9bd6d4e49772b7663522780e))
# [5.40.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.39.1-dev.1...v5.40.0-dev.1) (2025-09-17)
### Features
* **Viber - Hide ads:** Support latest app target ([#5863](https://github.com/ReVanced/revanced-patches/issues/5863)) ([e6cce85](https://github.com/ReVanced/revanced-patches/commit/e6cce8554116df3c0ea6dbb7440c59c9e73d8334))
## [5.39.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.39.0...v5.39.1-dev.1) (2025-09-17)
### Bug Fixes
* **YouTube - Force original audio:** Show UI setting summary if spoofing to Android Studio ([b7026b7](https://github.com/ReVanced/revanced-patches/commit/b7026b70865bc44de07b30f84ba8b8b608930d5b))
# [5.39.0](https://github.com/ReVanced/revanced-patches/compare/v5.38.0...v5.39.0) (2025-09-17)
### Bug Fixes
* **YouTube - Spoof video streams:** Do not use Android Creator for livestreams ([cbe576b](https://github.com/ReVanced/revanced-patches/commit/cbe576bc384ef5f5ee2fa341147925ed0dff568b))
* **YouTube - Spoof video streams:** Show Android Studio in spoof stream menu ([c9f741e](https://github.com/ReVanced/revanced-patches/commit/c9f741e616c7acab0cd4558e02b0c4ec18392c10))
* **YouTube Music - Spoof video streams:** Remove iPadOS client ([7eeffd3](https://github.com/ReVanced/revanced-patches/commit/7eeffd3392c57555342173103d3a417c038d0970))
### Features
* **YouTube - Hide video action buttons:** Add "Hide Shop button" setting ([a84db7b](https://github.com/ReVanced/revanced-patches/commit/a84db7be7fde2e9bb3ac41aec709a1681e845fe1))
# [5.39.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.39.0-dev.1...v5.39.0-dev.2) (2025-09-17)
### Bug Fixes
* **YouTube - Spoof video streams:** Show Android Studio in spoof stream menu ([c9f741e](https://github.com/ReVanced/revanced-patches/commit/c9f741e616c7acab0cd4558e02b0c4ec18392c10))
# [5.39.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.38.1-dev.2...v5.39.0-dev.1) (2025-09-17)
### Features
* **YouTube - Hide video action buttons:** Add "Hide Shop button" setting ([a84db7b](https://github.com/ReVanced/revanced-patches/commit/a84db7be7fde2e9bb3ac41aec709a1681e845fe1))
## [5.38.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.38.1-dev.1...v5.38.1-dev.2) (2025-09-16)
### Bug Fixes
* **YouTube Music - Spoof video streams:** Remove iPadOS client ([7eeffd3](https://github.com/ReVanced/revanced-patches/commit/7eeffd3392c57555342173103d3a417c038d0970))
## [5.38.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.38.0...v5.38.1-dev.1) (2025-09-16)
### Bug Fixes
* **YouTube - Spoof video streams:** Do not use Android Creator for livestreams ([cbe576b](https://github.com/ReVanced/revanced-patches/commit/cbe576bc384ef5f5ee2fa341147925ed0dff568b))
# [5.38.0](https://github.com/ReVanced/revanced-patches/compare/v5.37.0...v5.38.0) (2025-09-16)
### Bug Fixes
* **Instagram - Hide navigation buttons:** Support v397.1.0.52.81 ([#5855](https://github.com/ReVanced/revanced-patches/issues/5855)) ([f11d1ef](https://github.com/ReVanced/revanced-patches/commit/f11d1ef9907082512f139d4ab0e2e9f707de7e48))
* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](https://github.com/ReVanced/revanced-patches/commit/abe3943f98fd86dcd74c7e07cf65d3c7fc24fef9))
* **YouTube - Spoof video streams:** Show settings summary if `Force original audio` is enabled ([3776dda](https://github.com/ReVanced/revanced-patches/commit/3776dda710a7780717b7e6f2cdc1333ab67b92fc))
* **YouTube Music - Spoof video streams:** Fix playback issues when using a cellular network ([fa04c8e](https://github.com/ReVanced/revanced-patches/commit/fa04c8eecfbdd0b6ed082b464ca9032536d71762))
* **YouTube Music:** Use correct light/dark mode settings UI ([1475643](https://github.com/ReVanced/revanced-patches/commit/1475643f84e9ee4af2ba360a2274001ff1570dad))
### Features
* **Instagram:** Add `Hide explore feed` patch ([#5856](https://github.com/ReVanced/revanced-patches/issues/5856)) ([1d65887](https://github.com/ReVanced/revanced-patches/commit/1d65887e015a067196f5a84db486fff355c96596))
* **YouTube - Spoof video streams:** Add iPadOS client ([2726231](https://github.com/ReVanced/revanced-patches/commit/2726231404384d87f101d825e10a17c944e8f1bd))
* **YouTube Music:** Add `Settings` patch ([#5838](https://github.com/ReVanced/revanced-patches/issues/5838)) ([5e20bd8](https://github.com/ReVanced/revanced-patches/commit/5e20bd80f138d7ca94f18857194c46e489c435dc))
# [5.38.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.4...v5.38.0-dev.5) (2025-09-16)
### Bug Fixes
* **YouTube Music:** Use correct light/dark mode settings UI ([1475643](https://github.com/ReVanced/revanced-patches/commit/1475643f84e9ee4af2ba360a2274001ff1570dad))
# [5.38.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.3...v5.38.0-dev.4) (2025-09-16)
### Bug Fixes
* **YouTube - Spoof video streams:** Show settings summary if `Force original audio` is enabled ([3776dda](https://github.com/ReVanced/revanced-patches/commit/3776dda710a7780717b7e6f2cdc1333ab67b92fc))
# [5.38.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.2...v5.38.0-dev.3) (2025-09-16)
### Features
* **YouTube - Spoof video streams:** Add iPadOS client ([2726231](https://github.com/ReVanced/revanced-patches/commit/2726231404384d87f101d825e10a17c944e8f1bd))
# [5.38.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.1...v5.38.0-dev.2) (2025-09-16)
### Features
* **YouTube Music:** Add `Settings` patch ([#5838](https://github.com/ReVanced/revanced-patches/issues/5838)) ([5e20bd8](https://github.com/ReVanced/revanced-patches/commit/5e20bd80f138d7ca94f18857194c46e489c435dc))
# [5.38.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.3...v5.38.0-dev.1) (2025-09-15)
### Features
* **Instagram:** Add `Hide explore feed` patch ([#5856](https://github.com/ReVanced/revanced-patches/issues/5856)) ([1d65887](https://github.com/ReVanced/revanced-patches/commit/1d65887e015a067196f5a84db486fff355c96596))
## [5.37.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.2...v5.37.1-dev.3) (2025-09-15)
### Bug Fixes
* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](https://github.com/ReVanced/revanced-patches/commit/abe3943f98fd86dcd74c7e07cf65d3c7fc24fef9))
## [5.37.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.1...v5.37.1-dev.2) (2025-09-15)

View File

@@ -0,0 +1,3 @@
dependencies {
compileOnly(project(":extensions:shared:library"))
}

View File

@@ -0,0 +1 @@
<manifest/>

View File

@@ -0,0 +1,18 @@
package app.revanced.extension.instagram.feed;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
public class LimitFeedToFollowedProfiles {
/**
* Injection point.
*/
public static Map<String, String> setFollowingHeader(Map<String, String> requestHeaderMap) {
// Create new map as original is unmodifiable.
Map<String, String> patchedRequestHeaderMap = new HashMap<>(requestHeaderMap);
patchedRequestHeaderMap.put("pagination_source", "following");
return patchedRequestHeaderMap;
}
}

View File

@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;
import app.revanced.extension.music.settings.Settings;
@SuppressWarnings("unused")
public class HideCategoryBarPatch {
/**
* Injection point
*/
public static boolean hideCategoryBar() {
return Settings.HIDE_CATEGORY_BAR.get();
}
}

View File

@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;
import app.revanced.extension.music.settings.Settings;
@SuppressWarnings("unused")
public class HideGetPremiumPatch {
/**
* Injection point
*/
public static boolean hideGetPremiumLabel() {
return Settings.HIDE_GET_PREMIUM_LABEL.get();
}
}

View File

@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;
import app.revanced.extension.music.settings.Settings;
@SuppressWarnings("unused")
public class HideUpgradeButtonPatch {
/**
* Injection point
*/
public static boolean hideUpgradeButton() {
return Settings.HIDE_UPGRADE_BUTTON.get();
}
}

View File

@@ -0,0 +1,17 @@
package app.revanced.extension.music.patches;
import app.revanced.extension.music.settings.Settings;
@SuppressWarnings("unused")
public class HideVideoAdsPatch {
/**
* Injection point
*/
public static boolean showVideoAds(boolean original) {
if (Settings.HIDE_VIDEO_ADS.get()) {
return false;
}
return original;
}
}

View File

@@ -0,0 +1,14 @@
package app.revanced.extension.music.patches;
import app.revanced.extension.music.settings.Settings;
@SuppressWarnings("unused")
public class PermanentRepeatPatch {
/**
* Injection point
*/
public static boolean permanentRepeat() {
return Settings.PERMANENT_REPEAT.get();
}
}

View File

@@ -1,10 +1,13 @@
package app.revanced.extension.music.patches.spoof;
import static app.revanced.extension.music.settings.Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
import java.util.List;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
@@ -13,11 +16,13 @@ public class SpoofVideoStreamsPatch {
* Injection point.
*/
public static void setClientOrderToUse() {
ClientType[] availableClients = {
List<ClientType> availableClients = List.of(
ANDROID_VR_1_43_32,
ANDROID_VR_1_61_48,
};
VISIONOS
);
StreamingDataRequest.setClientOrderToUse(availableClients, ANDROID_VR_1_43_32);
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(
availableClients, SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
}
}

View File

@@ -0,0 +1,87 @@
package app.revanced.extension.music.settings;
import android.app.Activity;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceFragment;
import android.view.View;
import app.revanced.extension.music.settings.preference.ReVancedPreferenceFragment;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;
/**
* Hooks GoogleApiActivity to inject a custom ReVancedPreferenceFragment with a toolbar.
*/
public class GoogleApiActivityHook extends BaseActivityHook {
/**
* Injection point
* <p>
* Creates an instance of GoogleApiActivityHook for use in static initialization.
*/
@SuppressWarnings("unused")
public static GoogleApiActivityHook createInstance() {
// Must touch the Music settings to ensure the class is loaded and
// the values can be found when setting the UI preferences.
// Logging anything under non debug ensures this is set.
Logger.printInfo(() -> "Permanent repeat enabled: " + Settings.PERMANENT_REPEAT.get());
// YT Music always uses dark mode.
Utils.setIsDarkModeEnabled(true);
return new GoogleApiActivityHook();
}
/**
* Sets the fixed theme for the activity.
*/
@Override
protected void customizeActivityTheme(Activity activity) {
// Override the default YouTube Music theme to increase start padding of list items.
// Custom style located in resources/music/values/style.xml
activity.setTheme(Utils.getResourceIdentifier("Theme.ReVanced.YouTubeMusic.Settings", "style"));
}
/**
* Returns the resource ID for the YouTube Music settings layout.
*/
@Override
protected int getContentViewResourceId() {
return Utils.getResourceIdentifier("revanced_music_settings_with_toolbar", "layout");
}
/**
* Returns the fixed background color for the toolbar.
*/
@Override
protected int getToolbarBackgroundColor() {
return Utils.getResourceColor("ytm_color_black");
}
/**
* Returns the navigation icon with a color filter applied.
*/
@Override
protected Drawable getNavigationIcon() {
Drawable navigationIcon = ReVancedPreferenceFragment.getBackButtonDrawable();
navigationIcon.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
return navigationIcon;
}
/**
* Returns the click listener that finishes the activity when the navigation icon is clicked.
*/
@Override
protected View.OnClickListener getNavigationClickListener(Activity activity) {
return view -> activity.finish();
}
/**
* Creates a new ReVancedPreferenceFragment for the activity.
*/
@Override
protected PreferenceFragment createPreferenceFragment() {
return new ReVancedPreferenceFragment();
}
}

View File

@@ -0,0 +1,29 @@
package app.revanced.extension.music.settings;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static app.revanced.extension.shared.settings.Setting.parent;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.BooleanSetting;
import app.revanced.extension.shared.settings.EnumSetting;
import app.revanced.extension.shared.spoof.ClientType;
public class Settings extends BaseSettings {
// Ads
public static final BooleanSetting HIDE_VIDEO_ADS = new BooleanSetting("revanced_music_hide_video_ads", TRUE, true);
public static final BooleanSetting HIDE_GET_PREMIUM_LABEL = new BooleanSetting("revanced_music_hide_get_premium_label", TRUE, true);
public static final BooleanSetting HIDE_UPGRADE_BUTTON = new BooleanSetting("revanced_music_hide_upgrade_button", TRUE, true);
// General
public static final BooleanSetting HIDE_CATEGORY_BAR = new BooleanSetting("revanced_music_hide_category_bar", FALSE, true);
// Player
public static final BooleanSetting PERMANENT_REPEAT = new BooleanSetting("revanced_music_play_permanent_repeat", FALSE, true);
// Miscellaneous
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type",
ClientType.ANDROID_VR_1_43_32, true, parent(SPOOF_VIDEO_STREAMS));
}

View File

@@ -0,0 +1,38 @@
package app.revanced.extension.music.settings.preference;
import android.widget.Toolbar;
import app.revanced.extension.music.settings.GoogleApiActivityHook;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
/**
* Preference fragment for ReVanced settings.
*/
@SuppressWarnings({"deprecation", "NewApi"})
public class ReVancedPreferenceFragment extends ToolbarPreferenceFragment {
/**
* Initializes the preference fragment.
*/
@Override
protected void initialize() {
super.initialize();
try {
Utils.sortPreferenceGroups(getPreferenceScreen());
setPreferenceScreenToolbar(getPreferenceScreen());
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
}
/**
* Sets toolbar for all nested preference screens.
*/
@Override
protected void customizeToolbar(Toolbar toolbar) {
GoogleApiActivityHook.setToolbarLayoutParams(toolbar);
}
}

View File

@@ -1,6 +1,4 @@
package app.revanced.extension.youtube;
import androidx.annotation.NonNull;
package app.revanced.extension.shared;
import java.nio.charset.StandardCharsets;
@@ -39,7 +37,7 @@ public final class ByteTrieSearch extends TrieSearch<byte[]> {
return replacement;
}
public ByteTrieSearch(@NonNull byte[]... patterns) {
public ByteTrieSearch(byte[]... patterns) {
super(new ByteTrieNode(), patterns);
}
}

View File

@@ -1,6 +1,4 @@
package app.revanced.extension.youtube;
import androidx.annotation.NonNull;
package app.revanced.extension.shared;
/**
* Text pattern searching using a prefix tree (trie).
@@ -28,7 +26,7 @@ public final class StringTrieSearch extends TrieSearch<String> {
}
}
public StringTrieSearch(@NonNull String... patterns) {
public StringTrieSearch(String... patterns) {
super(new StringTrieNode(), patterns);
}
}

View File

@@ -1,6 +1,5 @@
package app.revanced.extension.youtube;
package app.revanced.extension.shared;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
@@ -57,11 +56,13 @@ public abstract class TrieSearch<T> {
if (searchTextLength - searchTextIndex < patternLength - patternStartIndex) {
return false; // Remaining search text is shorter than the remaining leaf pattern and they cannot match.
}
for (int i = searchTextIndex, j = patternStartIndex; j < patternLength; i++, j++) {
if (enclosingNode.getCharValue(searchText, i) != enclosingNode.getCharValue(pattern, j)) {
return false;
}
}
return callback == null || callback.patternMatched(searchText,
searchTextIndex - patternStartIndex, patternLength, callbackParameter);
}
@@ -136,7 +137,7 @@ public abstract class TrieSearch<T> {
* @param patternLength Length of the pattern.
* @param callback Callback, where a value of NULL indicates to always accept a pattern match.
*/
private void addPattern(@NonNull T pattern, int patternIndex, int patternLength,
private void addPattern(T pattern, int patternIndex, int patternLength,
@Nullable TriePatternMatchedCallback<T> callback) {
if (patternIndex == patternLength) { // Reached the end of the pattern.
if (endOfPatternCallback == null) {
@@ -145,6 +146,7 @@ public abstract class TrieSearch<T> {
endOfPatternCallback.add(callback);
return;
}
if (leaf != null) {
// Reached end of the graph and a leaf exist.
// Recursively call back into this method and push the existing leaf down 1 level.
@@ -159,6 +161,7 @@ public abstract class TrieSearch<T> {
leaf = new TrieCompressedPath<>(pattern, patternIndex, patternLength, callback);
return;
}
final char character = getCharValue(pattern, patternIndex);
final int arrayIndex = hashIndexForTableSize(children.length, character);
TrieNode<T> child = children[arrayIndex];
@@ -183,6 +186,7 @@ public abstract class TrieSearch<T> {
//noinspection unchecked
TrieNode<T>[] replacement = new TrieNode[replacementArraySize];
addNodeToArray(replacement, child);
boolean collision = false;
for (TrieNode<T> existingChild : children) {
if (existingChild != null) {
@@ -195,6 +199,7 @@ public abstract class TrieSearch<T> {
if (collision) {
continue;
}
children = replacement;
return;
}
@@ -234,6 +239,7 @@ public abstract class TrieSearch<T> {
if (leaf != null && leaf.matches(startNode, searchText, searchTextEndIndex, searchTextIndex, callbackParameter)) {
return true; // Leaf exists and it matched the search text.
}
List<TriePatternMatchedCallback<T>> endOfPatternCallback = node.endOfPatternCallback;
if (endOfPatternCallback != null) {
final int matchStartIndex = searchTextIndex - currentMatchLength;
@@ -246,6 +252,7 @@ public abstract class TrieSearch<T> {
}
}
}
TrieNode<T>[] children = node.children;
if (children == null) {
return false; // Reached a graph end point and there's no further patterns to search.
@@ -278,9 +285,11 @@ public abstract class TrieSearch<T> {
if (leaf != null) {
numberOfPointers += 4; // Number of fields in leaf node.
}
if (endOfPatternCallback != null) {
numberOfPointers += endOfPatternCallback.size();
}
if (children != null) {
numberOfPointers += children.length;
for (TrieNode<T> child : children) {
@@ -308,13 +317,13 @@ public abstract class TrieSearch<T> {
private final List<T> patterns = new ArrayList<>();
@SafeVarargs
TrieSearch(@NonNull TrieNode<T> root, @NonNull T... patterns) {
TrieSearch(TrieNode<T> root, T... patterns) {
this.root = Objects.requireNonNull(root);
addPatterns(patterns);
}
@SafeVarargs
public final void addPatterns(@NonNull T... patterns) {
public final void addPatterns(T... patterns) {
for (T pattern : patterns) {
addPattern(pattern);
}
@@ -325,7 +334,7 @@ public abstract class TrieSearch<T> {
*
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
*/
public void addPattern(@NonNull T pattern) {
public void addPattern(T pattern) {
addPattern(pattern, root.getTextLength(pattern), null);
}
@@ -333,31 +342,31 @@ public abstract class TrieSearch<T> {
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
* @param callback Callback to determine if searching should halt when a match is found.
*/
public void addPattern(@NonNull T pattern, @NonNull TriePatternMatchedCallback<T> callback) {
public void addPattern(T pattern, TriePatternMatchedCallback<T> callback) {
addPattern(pattern, root.getTextLength(pattern), Objects.requireNonNull(callback));
}
void addPattern(@NonNull T pattern, int patternLength, @Nullable TriePatternMatchedCallback<T> callback) {
void addPattern(T pattern, int patternLength, @Nullable TriePatternMatchedCallback<T> callback) {
if (patternLength == 0) return; // Nothing to match
patterns.add(pattern);
root.addPattern(pattern, 0, patternLength, callback);
}
public final boolean matches(@NonNull T textToSearch) {
public final boolean matches(T textToSearch) {
return matches(textToSearch, 0);
}
public boolean matches(@NonNull T textToSearch, @NonNull Object callbackParameter) {
public boolean matches(T textToSearch, Object callbackParameter) {
return matches(textToSearch, 0, root.getTextLength(textToSearch),
Objects.requireNonNull(callbackParameter));
}
public boolean matches(@NonNull T textToSearch, int startIndex) {
public boolean matches(T textToSearch, int startIndex) {
return matches(textToSearch, startIndex, root.getTextLength(textToSearch));
}
public final boolean matches(@NonNull T textToSearch, int startIndex, int endIndex) {
public final boolean matches(T textToSearch, int startIndex, int endIndex) {
return matches(textToSearch, startIndex, endIndex, null);
}
@@ -370,11 +379,11 @@ public abstract class TrieSearch<T> {
* @param callbackParameter Optional parameter passed to the callbacks.
* @return If any pattern matched, and it's callback halted searching.
*/
public boolean matches(@NonNull T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
public boolean matches(T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
return matches(textToSearch, root.getTextLength(textToSearch), startIndex, endIndex, callbackParameter);
}
private boolean matches(@NonNull T textToSearch, int textToSearchLength, int startIndex, int endIndex,
private boolean matches(T textToSearch, int textToSearchLength, int startIndex, int endIndex,
@Nullable Object callbackParameter) {
if (endIndex > textToSearchLength) {
throw new IllegalArgumentException("endIndex: " + endIndex

View File

@@ -0,0 +1,142 @@
package app.revanced.extension.shared.settings;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceFragment;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toolbar;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
/**
* Base class for hooking activities to inject a custom PreferenceFragment with a toolbar.
* Provides common logic for initializing the activity and setting up the toolbar.
*/
@SuppressWarnings({"deprecation", "NewApi"})
public abstract class BaseActivityHook extends Activity {
/**
* Layout parameters for the toolbar, extracted from the dummy toolbar.
*/
protected static ViewGroup.LayoutParams toolbarLayoutParams;
/**
* Sets the layout parameters for the toolbar.
*/
public static void setToolbarLayoutParams(Toolbar toolbar) {
if (toolbarLayoutParams != null) {
toolbar.setLayoutParams(toolbarLayoutParams);
}
}
/**
* Initializes the activity by setting the theme, content view and injecting a PreferenceFragment.
*/
public static void initialize(BaseActivityHook hook, Activity activity) {
try {
hook.customizeActivityTheme(activity);
activity.setContentView(hook.getContentViewResourceId());
// Sanity check.
String dataString = activity.getIntent().getDataString();
if (!"revanced_settings_intent".equals(dataString)) {
Logger.printException(() -> "Unknown intent: " + dataString);
return;
}
PreferenceFragment fragment = hook.createPreferenceFragment();
hook.createToolbar(activity, fragment);
activity.getFragmentManager()
.beginTransaction()
.replace(Utils.getResourceIdentifier("revanced_settings_fragments", "id"), fragment)
.commit();
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
}
/**
* Creates and configures a toolbar for the activity, replacing a dummy placeholder.
*/
@SuppressLint("UseCompatLoadingForDrawables")
protected void createToolbar(Activity activity, PreferenceFragment fragment) {
// Replace dummy placeholder toolbar.
// This is required to fix submenu title alignment issue with Android ASOP 15+
ViewGroup toolBarParent = activity.findViewById(
Utils.getResourceIdentifier("revanced_toolbar_parent", "id"));
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent, "revanced_toolbar");
toolbarLayoutParams = dummyToolbar.getLayoutParams();
toolBarParent.removeView(dummyToolbar);
// Sets appropriate system navigation bar color for the activity.
ToolbarPreferenceFragment.setNavigationBarColor(activity.getWindow());
Toolbar toolbar = new Toolbar(toolBarParent.getContext());
toolbar.setBackgroundColor(getToolbarBackgroundColor());
toolbar.setNavigationIcon(getNavigationIcon());
toolbar.setNavigationOnClickListener(getNavigationClickListener(activity));
toolbar.setTitle(Utils.getResourceIdentifier("revanced_settings_title", "string"));
final int margin = Utils.dipToPixels(16);
toolbar.setTitleMarginStart(margin);
toolbar.setTitleMarginEnd(margin);
TextView toolbarTextView = Utils.getChildView(toolbar, false, view -> view instanceof TextView);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
setToolbarLayoutParams(toolbar);
onPostToolbarSetup(activity, toolbar, fragment);
toolBarParent.addView(toolbar, 0);
}
/**
* Customizes the activity's theme.
*/
protected abstract void customizeActivityTheme(Activity activity);
/**
* Returns the resource ID for the content view layout.
*/
protected abstract int getContentViewResourceId();
/**
* Returns the background color for the toolbar.
*/
protected abstract int getToolbarBackgroundColor();
/**
* Returns the navigation icon drawable for the toolbar.
*/
protected abstract Drawable getNavigationIcon();
/**
* Returns the click listener for the toolbar's navigation icon.
*/
protected abstract View.OnClickListener getNavigationClickListener(Activity activity);
/**
* Creates the PreferenceFragment to be injected into the activity.
*/
protected PreferenceFragment createPreferenceFragment() {
return new ToolbarPreferenceFragment();
}
/**
* Performs additional setup after the toolbar is configured.
*
* @param activity The activity hosting the toolbar.
* @param toolbar The configured toolbar.
* @param fragment The PreferenceFragment associated with the activity.
*/
protected void onPostToolbarSetup(Activity activity, Toolbar toolbar, PreferenceFragment fragment) {}
}

View File

@@ -4,9 +4,6 @@ import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static app.revanced.extension.shared.settings.Setting.parent;
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability;
import app.revanced.extension.shared.spoof.ClientType;
/**
* Settings shared across multiple apps.
@@ -31,8 +28,4 @@ public class BaseSettings {
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability());
// Client type must be last spoof setting due to cyclic references.
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR_1_61_48, true, parent(SPOOF_VIDEO_STREAMS));
}

View File

@@ -1,9 +1,8 @@
package app.revanced.extension.youtube.settings.preference;
package app.revanced.extension.shared.settings.preference;
import android.content.Context;
import android.util.AttributeSet;
import android.preference.Preference;
import app.revanced.extension.shared.settings.preference.LogBufferManager;
/**
* A custom preference that clears the ReVanced debug log buffer when clicked.

View File

@@ -1,9 +1,8 @@
package app.revanced.extension.youtube.settings.preference;
package app.revanced.extension.shared.settings.preference;
import android.content.Context;
import android.util.AttributeSet;
import android.preference.Preference;
import app.revanced.extension.shared.settings.preference.LogBufferManager;
/**
* A custom preference that triggers exporting ReVanced debug logs to the clipboard when clicked.

View File

@@ -0,0 +1,150 @@
package app.revanced.extension.shared.settings.preference;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.graphics.Insets;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.widget.TextView;
import android.widget.Toolbar;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;
@SuppressWarnings({"deprecation", "NewApi"})
public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
/**
* Sets toolbar for all nested preference screens.
*/
protected void setPreferenceScreenToolbar(PreferenceScreen parentScreen) {
for (int i = 0, count = parentScreen.getPreferenceCount(); i < count; i++) {
Preference childPreference = parentScreen.getPreference(i);
if (childPreference instanceof PreferenceScreen) {
// Recursively set sub preferences.
setPreferenceScreenToolbar((PreferenceScreen) childPreference);
childPreference.setOnPreferenceClickListener(
childScreen -> {
Dialog preferenceScreenDialog = ((PreferenceScreen) childScreen).getDialog();
ViewGroup rootView = (ViewGroup) preferenceScreenDialog
.findViewById(android.R.id.content)
.getParent();
// Allow package-specific background customization.
customizeDialogBackground(rootView);
// Fix the system navigation bar color for submenus.
setNavigationBarColor(preferenceScreenDialog.getWindow());
// Fix edge-to-edge screen with Android 15 and YT 19.45+
// https://developer.android.com/develop/ui/views/layout/edge-to-edge#system-bars-insets
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
Insets cutoutInsets = insets.getInsets(WindowInsets.Type.displayCutout());
// Apply padding for display cutout in landscape.
int leftPadding = cutoutInsets.left;
int rightPadding = cutoutInsets.right;
int topPadding = statusInsets.top;
int bottomPadding = navInsets.bottom;
v.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
return insets;
});
}
Toolbar toolbar = new Toolbar(childScreen.getContext());
toolbar.setTitle(childScreen.getTitle());
toolbar.setNavigationIcon(getBackButtonDrawable());
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
final int margin = Utils.dipToPixels(16);
toolbar.setTitleMargin(margin, 0, margin, 0);
TextView toolbarTextView = Utils.getChildView(toolbar,
true, TextView.class::isInstance);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
// Allow package-specific toolbar customization.
customizeToolbar(toolbar);
// Allow package-specific post-toolbar setup.
onPostToolbarSetup(toolbar, preferenceScreenDialog);
rootView.addView(toolbar, 0);
return false;
}
);
}
}
}
/**
* Sets the system navigation bar color for the activity.
* Applies the background color obtained from {@link Utils#getAppBackgroundColor()} to the navigation bar.
* For Android 10 (API 29) and above, enforces navigation bar contrast to ensure visibility.
*/
public static void setNavigationBarColor(@Nullable Window window) {
if (window == null) {
Logger.printDebug(() -> "Cannot set navigation bar color, window is null");
return;
}
window.setNavigationBarColor(Utils.getAppBackgroundColor());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.setNavigationBarContrastEnforced(true);
}
}
/**
* Returns the drawable for the back button.
*/
@SuppressLint("UseCompatLoadingForDrawables")
public static Drawable getBackButtonDrawable() {
final int backButtonResource = Utils.getResourceIdentifier(
"revanced_settings_toolbar_arrow_left", "drawable");
Drawable drawable = Utils.getContext().getResources().getDrawable(backButtonResource);
customizeBackButtonDrawable(drawable);
return drawable;
}
/**
* Customizes the back button drawable.
*/
protected static void customizeBackButtonDrawable(Drawable drawable) {
drawable.setTint(Utils.getAppForegroundColor());
}
/**
* Allows subclasses to customize the dialog's root view background.
*/
protected void customizeDialogBackground(ViewGroup rootView) {
rootView.setBackgroundColor(Utils.getAppBackgroundColor());
}
/**
* Allows subclasses to customize the toolbar.
*/
protected void customizeToolbar(Toolbar toolbar) {
BaseActivityHook.setToolbarLayoutParams(toolbar);
}
/**
* Allows subclasses to perform actions after toolbar setup.
*/
protected void onPostToolbarSetup(Toolbar toolbar, Dialog preferenceScreenDialog) {}
}

View File

@@ -2,15 +2,20 @@ package app.revanced.extension.shared.spoof;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Locale;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.settings.BaseSettings;
@SuppressWarnings("ConstantLocale")
public enum ClientType {
/**
* Video not playable: Kids / Paid / Movie / Private / Age-restricted.
* This client can only be used when logged out.
*/
// https://dumps.tadiphone.dev/dumps/oculus/eureka
ANDROID_VR_1_61_48(
28,
@@ -26,30 +31,31 @@ public enum ClientType {
"132.0.6808.3",
"1.61.48",
false,
false,
"Android VR 1.61"
),
// Chromecast with Google TV 4K.
// https://dumps.tadiphone.dev/dumps/google/kirkwood
ANDROID_UNPLUGGED(
29,
"ANDROID_UNPLUGGED",
"com.google.android.apps.youtube.unplugged",
"Google",
"Google TV Streamer",
"Android",
"14",
"34",
"UTT3.240625.001.K5",
"132.0.6808.3",
"8.49.0",
true,
true,
"Android TV"
/**
* Uses non adaptive bitrate, which fixes audio stuttering with YT Music.
* Does not use AV1.
*/
ANDROID_VR_1_43_32(
ANDROID_VR_1_61_48.id,
ANDROID_VR_1_61_48.clientName,
Objects.requireNonNull(ANDROID_VR_1_61_48.packageName),
ANDROID_VR_1_61_48.deviceMake,
ANDROID_VR_1_61_48.deviceModel,
ANDROID_VR_1_61_48.osName,
ANDROID_VR_1_61_48.osVersion,
Objects.requireNonNull(ANDROID_VR_1_61_48.androidSdkVersion),
Objects.requireNonNull(ANDROID_VR_1_61_48.buildId),
"107.0.5284.2",
"1.43.32",
ANDROID_VR_1_61_48.useAuth,
"Android VR 1.43"
),
// Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
// Google Pixel 9 Pro Fold
// https://dumps.tadiphone.dev/dumps/google/barbet
/**
* Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
* <a href="https://dumps.tadiphone.dev/dumps/google/barbet">Google Pixel 9 Pro Fold</a>
*/
ANDROID_CREATOR(
14,
"ANDROID_CREATOR",
@@ -63,65 +69,47 @@ public enum ClientType {
"132.0.6779.0",
"23.47.101",
true,
true,
"Android Creator"
),
IOS_UNPLUGGED(
33,
"IOS_UNPLUGGED",
"com.google.ios.youtubeunplugged",
"Apple",
forceAVC()
// 11 Pro Max (last device with iOS 13)
? "iPhone12,5"
// 15 Pro Max
: "iPhone16,2",
"iOS",
forceAVC()
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
? "13.7.17H35"
: "18.2.22C152",
null,
null,
null,
// Version number should be a valid iOS release.
// https://www.ipa4fun.com/history/152043/
forceAVC()
// Some newer versions can also force AVC,
// but 6.45 is the last version that supports iOS 13.
? "6.45"
: "8.49",
true,
true,
forceAVC()
? "iOS TV Force AVC"
: "iOS TV"
"Android Studio"
),
/**
* Uses non adaptive bitrate, which fixes audio stuttering with YT Music.
* Uses VP9 and not AV1.
* Internal YT client for an unreleased YT client. May stop working at any time.
*/
ANDROID_VR_1_43_32(
ANDROID_VR_1_61_48.id,
ANDROID_VR_1_61_48.clientName,
ANDROID_VR_1_61_48.packageName,
ANDROID_VR_1_61_48.deviceMake,
ANDROID_VR_1_61_48.deviceModel,
ANDROID_VR_1_61_48.osName,
ANDROID_VR_1_61_48.osVersion,
ANDROID_VR_1_61_48.androidSdkVersion,
ANDROID_VR_1_61_48.buildId,
"107.0.5284.2",
"1.43.32",
ANDROID_VR_1_61_48.requiresAuth,
ANDROID_VR_1_61_48.useAuth,
"Android VR 1.43"
VISIONOS(101,
"VISIONOS",
"Apple",
"RealityDevice14,1",
"visionOS",
"1.3.21O771",
"0.1",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
false,
"visionOS"
),
/**
* The device machine id for the iPad 6th Gen (iPad7,6).
* AV1 hardware decoding is not supported.
* See [this GitHub Gist](https://gist.github.com/adamawolf/3048717) for more information.
*
* Based on Google's actions to date, PoToken may not be required on devices with very low specs.
* For example, suppose the User-Agent for a PlayStation 3 (with 256MB of RAM) is used.
* Accessing 'Web' (https://www.youtube.com) will redirect to 'TV' (https://www.youtube.com/tv).
* 'TV' target devices with very low specs, such as embedded devices, game consoles, and blu-ray players, so PoToken is not required.
*
* For this reason, the device machine id for the iPad 6th Gen (with 2GB of RAM),
* the lowest spec device capable of running iPadOS 17, was used.
*/
IPADOS(5,
"IOS",
"Apple",
"iPad7,6",
"iPadOS",
"17.7.10.21H450",
"19.22.3",
"com.google.ios.youtube/19.22.3 (iPad7,6; U; CPU iPadOS 17_7_10 like Mac OS X; " + Locale.getDefault() + ")",
false,
"iPadOS"
);
private static boolean forceAVC() {
return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
}
/**
* YouTube
* <a href="https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients">client type</a>
@@ -133,6 +121,7 @@ public enum ClientType {
/**
* App package name.
*/
@Nullable
private final String packageName;
/**
@@ -186,12 +175,6 @@ public enum ClientType {
*/
public final String clientVersion;
/**
* If this client requires authentication and does not work
* if logged out or in incognito mode.
*/
public final boolean requiresAuth;
/**
* If the client should use authentication if available.
*/
@@ -202,19 +185,20 @@ public enum ClientType {
*/
public final String friendlyName;
@SuppressWarnings("ConstantLocale")
/**
* Android constructor.
*/
ClientType(int id,
String clientName,
String packageName,
@NonNull String packageName,
String deviceMake,
String deviceModel,
String osName,
String osVersion,
@Nullable String androidSdkVersion,
@Nullable String buildId,
@Nullable String cronetVersion,
@NonNull String androidSdkVersion,
@NonNull String buildId,
@NonNull String cronetVersion,
String clientVersion,
boolean requiresAuth,
boolean useAuth,
String friendlyName) {
this.id = id;
@@ -228,36 +212,46 @@ public enum ClientType {
this.buildId = buildId;
this.cronetVersion = cronetVersion;
this.clientVersion = clientVersion;
this.requiresAuth = requiresAuth;
this.useAuth = useAuth;
this.friendlyName = friendlyName;
Locale defaultLocale = Locale.getDefault();
if (androidSdkVersion == null) {
// Convert version from '18.2.22C152' into '18_2_22'
String userAgentOsVersion = osVersion
.replaceAll("(\\d+\\.\\d+\\.\\d+).*", "$1")
.replace(".", "_");
// https://github.com/mitmproxy/mitmproxy/issues/4836
this.userAgent = String.format("%s/%s (%s; U; CPU iOS %s like Mac OS X; %s)",
packageName,
clientVersion,
deviceModel,
userAgentOsVersion,
defaultLocale
);
} else {
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
packageName,
clientVersion,
osVersion,
defaultLocale,
deviceModel,
Objects.requireNonNull(buildId),
Objects.requireNonNull(cronetVersion)
);
}
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
packageName,
clientVersion,
osVersion,
defaultLocale,
deviceModel,
Objects.requireNonNull(buildId),
Objects.requireNonNull(cronetVersion)
);
Logger.printDebug(() -> "userAgent: " + this.userAgent);
}
@SuppressWarnings("ConstantLocale")
ClientType(int id,
String clientName,
String deviceMake,
String deviceModel,
String osName,
String osVersion,
String clientVersion,
String userAgent,
boolean useAuth,
String friendlyName) {
this.id = id;
this.clientName = clientName;
this.deviceMake = deviceMake;
this.deviceModel = deviceModel;
this.osName = osName;
this.osVersion = osVersion;
this.clientVersion = clientVersion;
this.userAgent = userAgent;
this.useAuth = useAuth;
this.friendlyName = friendlyName;
this.packageName = null;
this.androidSdkVersion = null;
this.buildId = null;
this.cronetVersion = null;
}
}

View File

@@ -6,21 +6,19 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get();
private static final boolean FIX_HLS_CURRENT_TIME = SPOOF_STREAMING_DATA
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
/**
* Domain used for internet connectivity verification.
* It has an empty response body and is only used to check for a 204 response code.
@@ -36,17 +34,42 @@ public class SpoofVideoStreamsPatch {
private static final String INTERNET_CONNECTION_CHECK_URI_STRING = "https://www.google.com/gen_204";
private static final Uri INTERNET_CONNECTION_CHECK_URI = Uri.parse(INTERNET_CONNECTION_CHECK_URI_STRING);
private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get();
@Nullable
private static volatile AppLanguage languageOverride;
private static volatile ClientType preferredClient = ClientType.ANDROID_VR_1_61_48;
/**
* @return If this patch was included during patching.
*/
private static boolean isPatchIncluded() {
public static boolean isPatchIncluded() {
return false; // Modified during patching.
}
public static boolean notSpoofingToAndroid() {
return !isPatchIncluded()
|| !BaseSettings.SPOOF_VIDEO_STREAMS.get()
|| BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
@Nullable
public static AppLanguage getLanguageOverride() {
return languageOverride;
}
/**
* @param language Language override for non-authenticated requests. If this is null then
* {@link BaseSettings#SPOOF_VIDEO_STREAMS_LANGUAGE} is used.
*/
public static void setLanguageOverride(@Nullable AppLanguage language) {
languageOverride = language;
}
public static void setClientsToUse(List<ClientType> availableClients, ClientType client) {
preferredClient = Objects.requireNonNull(client);
StreamingDataRequest.setClientOrderToUse(availableClients, client);
}
public static boolean spoofingToClientWithNoMultiAudioStreams() {
return isPatchIncluded()
&& SPOOF_STREAMING_DATA
&& preferredClient != ClientType.IPADOS;
}
/**
@@ -261,17 +284,7 @@ public class SpoofVideoStreamsPatch {
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
ClientType clientType = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
&& (clientType == ClientType.ANDROID_VR_1_61_48 || clientType == ClientType.ANDROID_VR_1_43_32);
}
}
public static final class SpoofiOSAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
return BaseSettings.SPOOF_VIDEO_STREAMS.get() && !preferredClient.useAuth;
}
}
}

View File

@@ -1,5 +1,7 @@
package app.revanced.extension.shared.spoof.requests;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import org.json.JSONException;
import org.json.JSONObject;
@@ -10,8 +12,10 @@ import java.util.Locale;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.requests.Route;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
final class PlayerRoutes {
static final Route.CompiledRoute GET_STREAMING_DATA = new Route(
@@ -37,15 +41,16 @@ final class PlayerRoutes {
try {
JSONObject context = new JSONObject();
// Can override default language only if no login is used.
// Could use preferred audio for all clients that do not login,
// but if this is a fall over client it will set the language even though
// the audio language is not selectable in the UI.
ClientType userSelectedClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
Locale streamLocale = (userSelectedClient == ClientType.ANDROID_VR_1_61_48
|| userSelectedClient == ClientType.ANDROID_VR_1_43_32)
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getLocale()
: Locale.getDefault();
AppLanguage language = SpoofVideoStreamsPatch.getLanguageOverride();
if (language == null || clientType == ANDROID_VR_1_43_32) {
// Force original audio has not overrode the language.
// Or if YT has fallen over to the last unauthenticated client (VR 1.43), then
// always use the app language because forcing an audio stream of specific languages
// can sometimes fail so it's better to try and load something rather than nothing.
language = BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get();
}
//noinspection ExtractMethodRecommender
Locale streamLocale = language.getLocale();
JSONObject client = new JSONObject();
client.put("deviceMake", clientType.deviceMake);

View File

@@ -1,5 +1,6 @@
package app.revanced.extension.shared.spoof.requests;
import static app.revanced.extension.shared.ByteTrieSearch.convertStringsToBytes;
import static app.revanced.extension.shared.spoof.requests.PlayerRoutes.GET_STREAMING_DATA;
import androidx.annotation.NonNull;
@@ -13,12 +14,18 @@ import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import app.revanced.extension.shared.ByteTrieSearch;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
@@ -37,10 +44,15 @@ public class StreamingDataRequest {
private static volatile ClientType[] clientOrderToUse = ClientType.values();
public static void setClientOrderToUse(ClientType[] availableClients, ClientType preferredClient) {
Objects.requireNonNull(availableClients);
public static void setClientOrderToUse(List<ClientType> availableClients, ClientType preferredClient) {
Objects.requireNonNull(preferredClient);
clientOrderToUse = new ClientType[availableClients.length];
int availableClientSize = availableClients.size();
if (!availableClients.contains(preferredClient)) {
availableClientSize++;
}
clientOrderToUse = new ClientType[availableClientSize];
clientOrderToUse[0] = preferredClient;
int i = 1;
@@ -88,6 +100,16 @@ public class StreamingDataRequest {
}
});
/**
* Strings found in the response if the video is a livestream.
*/
private static final ByteTrieSearch liveStreamBufferSearch = new ByteTrieSearch(
convertStringsToBytes(
"yt_live_broadcast",
"yt_premiere_broadcast"
)
);
private static volatile ClientType lastSpoofedClientType;
public static String getLastSpoofedClientName() {
@@ -155,7 +177,7 @@ public class StreamingDataRequest {
}
}
if (!authHeadersIncludes && clientType.requiresAuth) {
if (!authHeadersIncludes && clientType.useAuth) {
Logger.printDebug(() -> "Skipping client since user is not logged in: " + clientType
+ " videoId: " + videoId);
return null;
@@ -216,9 +238,13 @@ public class StreamingDataRequest {
while ((bytesRead = inputStream.read(buffer)) >= 0) {
baos.write(buffer, 0, bytesRead);
}
lastSpoofedClientType = clientType;
if (clientType == ClientType.ANDROID_CREATOR && liveStreamBufferSearch.matches(buffer)) {
Logger.printDebug(() -> "Skipping Android Studio as video is a livestream: " + videoId);
} else {
lastSpoofedClientType = clientType;
return ByteBuffer.wrap(baos.toByteArray());
return ByteBuffer.wrap(baos.toByteArray());
}
}
}
} catch (IOException ex) {

View File

@@ -1,7 +1,7 @@
package app.revanced.extension.youtube.patches;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
import app.revanced.extension.youtube.settings.Settings;
@@ -11,16 +11,21 @@ public class ForceOriginalAudioPatch {
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
/**
* If the conditions to use this patch were present when the app launched.
* Injection point.
*/
public static boolean PATCH_AVAILABLE = SpoofVideoStreamsPatch.notSpoofingToAndroid();
public static final class ForceOriginalAudioAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
// Check conditions of launch and now. Otherwise if spoofing is changed
// without a restart the setting will show as available when it's not.
return PATCH_AVAILABLE && SpoofVideoStreamsPatch.notSpoofingToAndroid();
public static void setPreferredLanguage() {
if (Settings.FORCE_ORIGINAL_AUDIO.get()
&& SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
// If client spoofing does not use authentication and lacks multi-audio streams,
// then can use any language code for the request and if that requested language is
// not available YT uses the original audio language. Authenticated requests ignore
// the language code and always use the account language. Use a language that is
// not auto-dubbed by YouTube: https://support.google.com/youtube/answer/15569972
// but the language is also supported natively by the Meta Quest device that
// Android VR is spoofing.
AppLanguage override = AppLanguage.SV;
Logger.printDebug(() -> "Setting language override: " + override);
SpoofVideoStreamsPatch.setLanguageOverride(override);
}
}

View File

@@ -10,7 +10,7 @@ import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")

View File

@@ -74,6 +74,10 @@ final class ButtonsFilter extends Filter {
Settings.HIDE_ASK_BUTTON,
"yt_fill_spark"
),
new ByteArrayFilterGroup(
Settings.HIDE_SHOP_BUTTON,
"yt_outline_bag"
),
new ByteArrayFilterGroup(
Settings.HIDE_STOP_ADS_BUTTON,
"yt_outline_slash_circle_left"

View File

@@ -14,7 +14,7 @@ import java.util.regex.Pattern;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.ByteTrieSearch;
import app.revanced.extension.shared.ByteTrieSearch;
import app.revanced.extension.youtube.settings.Settings;
/**

View File

@@ -1,6 +1,6 @@
package app.revanced.extension.youtube.patches.components;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;

View File

@@ -4,7 +4,7 @@ import androidx.annotation.NonNull;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.settings.BooleanSetting;
import app.revanced.extension.youtube.ByteTrieSearch;
import app.revanced.extension.shared.ByteTrieSearch;
abstract class FilterGroup<T> {
final static class FilterGroupResult {

View File

@@ -5,9 +5,9 @@ import androidx.annotation.NonNull;
import java.util.*;
import java.util.function.Consumer;
import app.revanced.extension.youtube.ByteTrieSearch;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.youtube.TrieSearch;
import app.revanced.extension.shared.ByteTrieSearch;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.shared.TrieSearch;
abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<T> {

View File

@@ -14,9 +14,9 @@ import java.util.concurrent.atomic.AtomicReference;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.ByteTrieSearch;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.youtube.TrieSearch;
import app.revanced.extension.shared.ByteTrieSearch;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.shared.TrieSearch;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.NavigationBar;
import app.revanced.extension.youtube.shared.PlayerType;

View File

@@ -10,7 +10,7 @@ import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.youtube.patches.ChangeHeaderPatch;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.NavigationBar;

View File

@@ -8,7 +8,7 @@ import java.util.List;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.shared.StringTrieSearch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")

View File

@@ -9,13 +9,13 @@ import app.revanced.extension.youtube.shared.ShortsPlayerState;
public class PlayerFlyoutMenuItemsFilter extends Filter {
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
private static final boolean AVAILABLE_ON_LAUNCH = SpoofVideoStreamsPatch.notSpoofingToAndroid();
private static final boolean AVAILABLE_ON_LAUNCH = !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
@Override
public boolean isAvailable() {
// Check conditions of launch and now. Otherwise if spoofing is changed
// without a restart the setting will show as available when it's not.
return AVAILABLE_ON_LAUNCH && SpoofVideoStreamsPatch.notSpoofingToAndroid();
return AVAILABLE_ON_LAUNCH && !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
}
}

View File

@@ -12,7 +12,7 @@ import app.revanced.extension.youtube.patches.ReturnYouTubeDislikePatch;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.youtube.TrieSearch;
import app.revanced.extension.shared.TrieSearch;
/**
* Searches for video id's in the proto buffer of Shorts dislike.

View File

@@ -1,13 +1,15 @@
package app.revanced.extension.youtube.patches.spoof;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_CREATOR;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_UNPLUGGED;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
import static app.revanced.extension.shared.spoof.ClientType.IOS_UNPLUGGED;
import static app.revanced.extension.shared.spoof.ClientType.IPADOS;
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
import java.util.List;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
@@ -16,14 +18,15 @@ public class SpoofVideoStreamsPatch {
* Injection point.
*/
public static void setClientOrderToUse() {
ClientType[] availableClients = {
List<ClientType> availableClients = List.of(
ANDROID_VR_1_61_48,
ANDROID_UNPLUGGED,
VISIONOS,
ANDROID_CREATOR,
IOS_UNPLUGGED
};
ANDROID_VR_1_43_32,
IPADOS
);
StreamingDataRequest.setClientOrderToUse(availableClients,
BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(
availableClients, Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
}
}

View File

@@ -1,50 +1,120 @@
package app.revanced.extension.youtube.settings;
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceFragment;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.widget.TextView;
import android.view.View;
import android.widget.Toolbar;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseActivityHook;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.patches.VersionCheckPatch;
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFragment;
/**
* Hooks LicenseActivity.
* <p>
* This class is responsible for injecting our own fragment by replacing the LicenseActivity.
* Hooks LicenseActivity to inject a custom ReVancedPreferenceFragment with a toolbar and search functionality.
*/
@SuppressWarnings("unused")
public class LicenseActivityHook extends Activity {
@SuppressWarnings("deprecation")
public class LicenseActivityHook extends BaseActivityHook {
private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.
private static ViewGroup.LayoutParams toolbarLayoutParams;
/**
* Controller for managing search view components in the toolbar.
*/
@SuppressLint("StaticFieldLeak")
public static SearchViewController searchViewController;
public static void setToolbarLayoutParams(Toolbar toolbar) {
if (toolbarLayoutParams != null) {
toolbar.setLayoutParams(toolbarLayoutParams);
/**
* Injection point
* <p>
* Creates an instance of LicenseActivityHook for use in static initialization.
*/
@SuppressWarnings("unused")
public static LicenseActivityHook createInstance() {
return new LicenseActivityHook();
}
/**
* Customizes the activity theme based on dark/light mode.
*/
@Override
protected void customizeActivityTheme(Activity activity) {
final var theme = Utils.isDarkModeEnabled()
? "Theme.YouTube.Settings.Dark"
: "Theme.YouTube.Settings";
activity.setTheme(Utils.getResourceIdentifier(theme, "style"));
}
/**
* Returns the resource ID for the YouTube settings layout.
*/
@Override
protected int getContentViewResourceId() {
return Utils.getResourceIdentifier("revanced_settings_with_toolbar", "layout");
}
/**
* Returns the toolbar background color based on dark/light mode.
*/
@Override
protected int getToolbarBackgroundColor() {
final String colorName = Utils.isDarkModeEnabled()
? "yt_black3"
: "yt_white1";
return Utils.getColorFromString(colorName);
}
/**
* Returns the navigation icon drawable for the toolbar.
*/
@Override
protected Drawable getNavigationIcon() {
return ReVancedPreferenceFragment.getBackButtonDrawable();
}
/**
* Returns the click listener for the navigation icon.
*/
@Override
protected View.OnClickListener getNavigationClickListener(Activity activity) {
return null;
}
/**
* Adds search view components to the toolbar for ReVancedPreferenceFragment.
*
* @param activity The activity hosting the toolbar.
* @param toolbar The configured toolbar.
* @param fragment The PreferenceFragment associated with the activity.
*/
@Override
protected void onPostToolbarSetup(Activity activity, Toolbar toolbar, PreferenceFragment fragment) {
if (fragment instanceof ReVancedPreferenceFragment) {
searchViewController = SearchViewController.addSearchViewComponents(
activity, toolbar, (ReVancedPreferenceFragment) fragment);
}
}
/**
* Creates a new ReVancedPreferenceFragment for the activity.
*/
@Override
protected PreferenceFragment createPreferenceFragment() {
return new ReVancedPreferenceFragment();
}
/**
* Injection point.
* Overrides the ReVanced settings language.
*/
@SuppressWarnings("unused")
public static Context getAttachBaseContext(Context original) {
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
if (language == AppLanguage.DEFAULT) {
@@ -57,6 +127,7 @@ public class LicenseActivityHook extends Activity {
/**
* Injection point.
*/
@SuppressWarnings("unused")
public static boolean useCairoSettingsFragment(boolean original) {
// Early targets have layout issues and it's better to always force off.
if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
@@ -80,87 +151,6 @@ public class LicenseActivityHook extends Activity {
/**
* Injection point.
* <p>
* Hooks LicenseActivity#onCreate in order to inject our own fragment.
*/
public static void initialize(Activity licenseActivity) {
try {
setActivityTheme(licenseActivity);
ReVancedPreferenceFragment.setNavigationBarColor(licenseActivity.getWindow());
licenseActivity.setContentView(getResourceIdentifier(
"revanced_settings_with_toolbar", "layout"));
// Sanity check.
String dataString = licenseActivity.getIntent().getDataString();
if (!"revanced_settings_intent".equals(dataString)) {
Logger.printException(() -> "Unknown intent: " + dataString);
return;
}
PreferenceFragment fragment = new ReVancedPreferenceFragment();
createToolbar(licenseActivity, fragment);
//noinspection deprecation
licenseActivity.getFragmentManager()
.beginTransaction()
.replace(getResourceIdentifier("revanced_settings_fragments", "id"), fragment)
.commit();
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
}
@SuppressLint("UseCompatLoadingForDrawables")
private static void createToolbar(Activity activity, PreferenceFragment fragment) {
// Replace dummy placeholder toolbar.
// This is required to fix submenu title alignment issue with Android ASOP 15+
ViewGroup toolBarParent = activity.findViewById(
getResourceIdentifier("revanced_toolbar_parent", "id"));
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent, "revanced_toolbar");
toolbarLayoutParams = dummyToolbar.getLayoutParams();
toolBarParent.removeView(dummyToolbar);
Toolbar toolbar = new Toolbar(toolBarParent.getContext());
toolbar.setBackgroundColor(getToolbarBackgroundColor());
toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable());
toolbar.setTitle(getResourceIdentifier("revanced_settings_title", "string"));
final int margin = Utils.dipToPixels(16);
toolbar.setTitleMarginStart(margin);
toolbar.setTitleMarginEnd(margin);
TextView toolbarTextView = Utils.getChildView(toolbar, false,
view -> view instanceof TextView);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
setToolbarLayoutParams(toolbar);
// Add Search bar only for ReVancedPreferenceFragment.
if (fragment instanceof ReVancedPreferenceFragment) {
searchViewController = SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
}
toolBarParent.addView(toolbar, 0);
}
public static void setActivityTheme(Activity activity) {
final var theme = Utils.isDarkModeEnabled()
? "Theme.YouTube.Settings.Dark"
: "Theme.YouTube.Settings";
activity.setTheme(getResourceIdentifier(theme, "style"));
}
public static int getToolbarBackgroundColor() {
final String colorName = Utils.isDarkModeEnabled()
? "yt_black3"
: "yt_white1";
return Utils.getColorFromString(colorName);
}
/**
* Injection point.
*
* Updates dark/light mode since YT settings can force light/dark mode
* which can differ from the global device settings.
*/
@@ -173,6 +163,10 @@ public class LicenseActivityHook extends Activity {
}
}
/**
* Handles configuration changes, such as orientation, to update the search view.
*/
@SuppressWarnings("unused")
public static void handleConfigurationChanged(Activity activity, Configuration newConfig) {
if (searchViewController != null) {
searchViewController.handleOrientationChange(newConfig.orientation);

View File

@@ -12,7 +12,6 @@ import static app.revanced.extension.youtube.patches.ChangeHeaderPatch.HeaderLog
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.ChangeStartPageTypeAvailability;
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL;
@@ -42,6 +41,7 @@ import app.revanced.extension.shared.settings.LongSetting;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.StringSetting;
import app.revanced.extension.shared.settings.preference.SharedPrefCategory;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrowAvailability;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.ThumbnailOption;
@@ -75,7 +75,7 @@ public class Settings extends BaseSettings {
"0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true);
// Audio
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new ForceOriginalAudioAvailability());
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, true);
// Ads
public static final BooleanSetting HIDE_CREATOR_STORE_SHELF = new BooleanSetting("revanced_hide_creator_store_shelf", TRUE);
@@ -230,6 +230,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_REPORT_BUTTON = new BooleanSetting("revanced_hide_report_button", FALSE);
public static final BooleanSetting HIDE_SAVE_BUTTON = new BooleanSetting("revanced_hide_save_button", FALSE);
public static final BooleanSetting HIDE_SHARE_BUTTON = new BooleanSetting("revanced_hide_share_button", FALSE);
public static final BooleanSetting HIDE_SHOP_BUTTON = new BooleanSetting("revanced_hide_shop_button", FALSE);
public static final BooleanSetting HIDE_STOP_ADS_BUTTON = new BooleanSetting("revanced_hide_stop_ads_button", TRUE);
public static final BooleanSetting HIDE_THANKS_BUTTON = new BooleanSetting("revanced_hide_thanks_button", TRUE);
@@ -357,6 +358,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting REMOVE_TRACKING_QUERY_PARAMETER = new BooleanSetting("revanced_remove_tracking_query_parameter", TRUE);
public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true,
"revanced_spoof_device_dimensions_user_dialog_message");
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR_1_61_48, true, parent(SPOOF_VIDEO_STREAMS));
public static final BooleanSetting DEBUG_PROTOBUFFER = new BooleanSetting("revanced_debug_protobuffer", FALSE, false,
"revanced_debug_protobuffer_user_dialog_message", parent(BaseSettings.DEBUG));

View File

@@ -6,18 +6,26 @@ import android.content.Context;
import android.preference.SwitchPreference;
import android.util.AttributeSet;
import app.revanced.extension.youtube.patches.ForceOriginalAudioPatch;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings({"deprecation", "unused"})
public class ForceOriginalAudioSwitchPreference extends SwitchPreference {
// Spoof stream patch is not included, or is not currently spoofing to Android Studio.
private static final boolean available = !SpoofVideoStreamsPatch.isPatchIncluded()
|| !(Settings.SPOOF_VIDEO_STREAMS.get()
&& Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_CREATOR);
{
if (!ForceOriginalAudioPatch.PATCH_AVAILABLE) {
if (!available) {
// Show why force audio is not available.
String summary = str("revanced_force_original_audio_not_available");
setSummary(summary);
setSummaryOn(summary);
setSummaryOff(summary);
super.setSummary(summary);
super.setSummaryOn(summary);
super.setSummaryOff(summary);
super.setEnabled(false);
}
}
@@ -33,4 +41,23 @@ public class ForceOriginalAudioSwitchPreference extends SwitchPreference {
public ForceOriginalAudioSwitchPreference(Context context) {
super(context);
}
@Override
public void setEnabled(boolean enabled) {
if (!available) {
return;
}
super.setEnabled(enabled);
}
@Override
public void setSummary(CharSequence summary) {
if (!available) {
return;
}
super.setSummary(summary);
}
}

View File

@@ -12,8 +12,8 @@ import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
public class HideAudioFlyoutMenuPreference extends SwitchPreference {
{
// Audio menu is not available if spoofing to Android client type.
if (!SpoofVideoStreamsPatch.notSpoofingToAndroid()) {
// Audio menu is not available if spoofing to most client types.
if (SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
String summary = str("revanced_hide_player_flyout_audio_track_not_available");
setSummary(summary);
setSummaryOn(summary);

View File

@@ -3,11 +3,7 @@ package app.revanced.extension.youtube.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.graphics.Insets;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
@@ -17,11 +13,6 @@ import android.preference.SwitchPreference;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.BackgroundColorSpan;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.widget.TextView;
import android.widget.Toolbar;
import androidx.annotation.CallSuper;
@@ -40,16 +31,16 @@ import java.util.regex.Pattern;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
import app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
import app.revanced.extension.youtube.settings.LicenseActivityHook;
import app.revanced.extension.youtube.sponsorblock.ui.SponsorBlockPreferenceGroup;
/**
* Preference fragment for ReVanced settings.
*/
@SuppressWarnings("deprecation")
public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
@SuppressWarnings({"deprecation", "NewApi"})
public class ReVancedPreferenceFragment extends ToolbarPreferenceFragment {
/**
* The main PreferenceScreen used to display the current set of preferences.
@@ -70,31 +61,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
*/
private final List<AbstractPreferenceSearchData<?>> allPreferences = new ArrayList<>();
@SuppressLint("UseCompatLoadingForDrawables")
public static Drawable getBackButtonDrawable() {
final int backButtonResource = getResourceIdentifier("revanced_settings_toolbar_arrow_left", "drawable");
Drawable drawable = Utils.getContext().getResources().getDrawable(backButtonResource);
drawable.setTint(Utils.getAppForegroundColor());
return drawable;
}
/**
* Sets the system navigation bar color for the activity.
* Applies the background color obtained from {@link Utils#getAppBackgroundColor()} to the navigation bar.
* For Android 10 (API 29) and above, enforces navigation bar contrast to ensure visibility.
*/
public static void setNavigationBarColor(@Nullable Window window) {
if (window == null) {
Logger.printDebug(() -> "Cannot set navigation bar color, window is null");
return;
}
window.setNavigationBarColor(Utils.getAppBackgroundColor());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.setNavigationBarContrastEnforced(true);
}
}
/**
* Initializes the preference fragment, copying the original screen to allow full restoration.
*/
@@ -139,8 +105,28 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
}
}
/**
* Sets toolbar for all nested preference screens.
*/
@Override
protected void customizeToolbar(Toolbar toolbar) {
LicenseActivityHook.setToolbarLayoutParams(toolbar);
}
/**
* Perform actions after toolbar setup.
*/
@Override
protected void onPostToolbarSetup(Toolbar toolbar, Dialog preferenceScreenDialog) {
if (LicenseActivityHook.searchViewController != null
&& LicenseActivityHook.searchViewController.isSearchActive()) {
toolbar.post(() -> LicenseActivityHook.searchViewController.closeSearch());
}
}
/**
* Recursively collects all preferences from the screen or group.
*
* @param includeDepth Menu depth to start including preferences.
* A value of 0 adds all preferences.
*/
@@ -222,75 +208,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
preferenceScreen.addPreference(noResultsPreference);
}
}
/**
* Sets toolbar for all nested preference screens.
*/
private void setPreferenceScreenToolbar(PreferenceScreen parentScreen) {
for (int i = 0, count = parentScreen.getPreferenceCount(); i < count; i++) {
Preference childPreference = parentScreen.getPreference(i);
if (childPreference instanceof PreferenceScreen) {
// Recursively set sub preferences.
setPreferenceScreenToolbar((PreferenceScreen) childPreference);
childPreference.setOnPreferenceClickListener(
childScreen -> {
Dialog preferenceScreenDialog = ((PreferenceScreen) childScreen).getDialog();
ViewGroup rootView = (ViewGroup) preferenceScreenDialog
.findViewById(android.R.id.content)
.getParent();
// Fix the system navigation bar color for submenus.
setNavigationBarColor(preferenceScreenDialog.getWindow());
// Fix edge-to-edge screen with Android 15 and YT 19.45+
// https://developer.android.com/develop/ui/views/layout/edge-to-edge#system-bars-insets
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
Insets cutoutInsets = insets.getInsets(WindowInsets.Type.displayCutout());
// Apply padding for display cutout in landscape.
int leftPadding = cutoutInsets.left;
int rightPadding = cutoutInsets.right;
int topPadding = statusInsets.top;
int bottomPadding = navInsets.bottom;
v.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
return insets;
});
}
Toolbar toolbar = new Toolbar(childScreen.getContext());
toolbar.setTitle(childScreen.getTitle());
toolbar.setNavigationIcon(getBackButtonDrawable());
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
final int margin = Utils.dipToPixels(16);
toolbar.setTitleMargin(margin, 0, margin, 0);
TextView toolbarTextView = Utils.getChildView(toolbar,
true, TextView.class::isInstance);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
LicenseActivityHook.setToolbarLayoutParams(toolbar);
if (LicenseActivityHook.searchViewController != null
&& LicenseActivityHook.searchViewController.isSearchActive()) {
toolbar.post(() -> LicenseActivityHook.searchViewController.closeSearch());
}
rootView.addView(toolbar, 0);
return false;
}
);
}
}
}
}
@SuppressWarnings("deprecation")

View File

@@ -0,0 +1,57 @@
package app.revanced.extension.youtube.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import android.content.Context;
import android.util.AttributeSet;
import app.revanced.extension.shared.settings.preference.SortedListPreference;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
@SuppressWarnings({"deprecation", "unused"})
public class SpoofAudioSelectorListPreference extends SortedListPreference {
private final boolean available;
{
if (SpoofVideoStreamsPatch.getLanguageOverride() != null) {
available = false;
super.setEnabled(false);
super.setSummary(str("revanced_spoof_video_streams_language_not_available"));
} else {
available = true;
}
}
public SpoofAudioSelectorListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public SpoofAudioSelectorListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public SpoofAudioSelectorListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SpoofAudioSelectorListPreference(Context context) {
super(context);
}
@Override
public void setEnabled(boolean enabled) {
if (!available) {
return;
}
super.setEnabled(enabled);
}
@Override
public void setSummary(CharSequence summary) {
if (!available) {
return;
}
super.setSummary(summary);
}
}

View File

@@ -15,6 +15,7 @@ import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings({"deprecation", "unused"})
public class SpoofStreamingDataSideEffectsPreference extends Preference {
@@ -69,7 +70,7 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
}
private void updateUI() {
ClientType clientType = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
ClientType clientType = Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
if (currentClientType == clientType) {
return;
}
@@ -78,22 +79,25 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
Logger.printDebug(() -> "Updating spoof stream side effects preference");
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
String key = "revanced_spoof_video_streams_about_" +
(clientType == ClientType.IOS_UNPLUGGED
? "ios_tv"
: "android");
String title = str(key + "_title");
String summary = str(key + "_summary");
setTitle(str("revanced_spoof_video_streams_about_title"));
// Android VR supports AV1 but all other clients do not.
if (clientType != ClientType.ANDROID_VR_1_61_48
&& clientType != ClientType.ANDROID_VR_1_43_32) {
String summary = str(clientType == ClientType.IPADOS
? "revanced_spoof_video_streams_about_ipados_summary"
// Same base side effects for Android VR, Android Studio, and visionOS.
: "revanced_spoof_video_streams_about_android_summary");
if (clientType == ClientType.IPADOS) {
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
} else if (clientType == ClientType.VISIONOS) {
summary = str("revanced_spoof_video_streams_about_experimental")
+ '\n' + summary
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
+ '\n' + str("revanced_spoof_video_streams_about_kids_videos");
} else if (clientType == ClientType.ANDROID_CREATOR) {
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1")
+ '\n' + str("revanced_spoof_video_streams_about_kids_videos");
}
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
setTitle(title);
setSummary(summary);
}
}

View File

@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
version = 5.37.1-dev.2
version = 5.40.0-dev.3

View File

@@ -264,6 +264,14 @@ public final class app/revanced/patches/instagram/ads/HideAdsPatchKt {
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/feed/LimitFeedToFollowedProfilesKt {
public static final fun getLimitFeedToFollowedProfiles ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
public static final fun getHideExportFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/hide/navigation/HideNavigationButtonsKt {
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -272,6 +280,10 @@ public final class app/revanced/patches/instagram/hide/stories/HideStoriesKt {
public static final fun getHideStoriesPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/misc/extension/SharedExtensionPatchKt {
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -368,8 +380,9 @@ public final class app/revanced/patches/music/layout/premium/HideGetPremiumPatch
public static final fun getHideGetPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatchKt {
public static final fun getRemoveUpgradeButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public final class app/revanced/patches/music/layout/upgradebutton/HideUpgradeButtonPatchKt {
public static final fun getHideUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun getRemoveUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatchKt {
@@ -392,7 +405,21 @@ public final class app/revanced/patches/music/misc/gms/GmsCoreSupportPatchKt {
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/music/misc/spoof/SpoofVideoStreamsKt {
public final class app/revanced/patches/music/misc/settings/PreferenceScreen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen {
public static final field INSTANCE Lapp/revanced/patches/music/misc/settings/PreferenceScreen;
public fun commit (Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference;)V
public final fun getADS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getGENERAL ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getMISC ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
public final fun getPLAYER ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
}
public final class app/revanced/patches/music/misc/settings/SettingsPatchKt {
public static final fun getSettingsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun newIntent (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
}
public final class app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatchKt {
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@@ -1648,7 +1675,6 @@ public final class app/revanced/patches/youtube/misc/settings/PreferenceScreen :
}
public final class app/revanced/patches/youtube/misc/settings/SettingsPatchKt {
public static final fun addSettingPreference (Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
public static final fun getSettingsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun newIntent (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
}

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.instagram.feed
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.BytecodePatchContext
internal val mainFeedRequestClassFingerprint = fingerprint {
strings("Request{mReason=", ", mInstanceNumber=")
}
context(BytecodePatchContext)
internal val initMainFeedRequestFingerprint get() = fingerprint {
custom { method, classDef ->
method.name == "<init>" &&
classDef == mainFeedRequestClassFingerprint.classDef
}
}
internal val mainFeedHeaderMapFinderFingerprint = fingerprint {
strings("pagination_source", "FEED_REQUEST_SENT")
}

View File

@@ -0,0 +1,64 @@
package app.revanced.patches.instagram.feed
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/instagram/feed/LimitFeedToFollowedProfiles;"
@Suppress("unused")
val limitFeedToFollowedProfiles = bytecodePatch(
name = "Limit feed to followed profiles",
description = "Filters the home feed to display only content from profiles you follow.",
use = false
) {
compatibleWith("com.instagram.android")
dependsOn(sharedExtensionPatch)
execute {
/**
* Since the header field is obfuscated and there is no easy way to identify it among all the class fields,
* an additional method is fingerprinted.
* This method uses the map, so we can get the field name of the map field using this.
*/
val mainFeedRequestHeaderFieldName: String
with(mainFeedHeaderMapFinderFingerprint.method) {
mainFeedRequestHeaderFieldName = indexOfFirstInstructionOrThrow {
getReference<FieldReference>().let { ref ->
ref?.type == "Ljava/util/Map;" &&
ref.definingClass == mainFeedRequestClassFingerprint.classDef.toString()
}
}.let { instructionIndex ->
getInstruction(instructionIndex).getReference<FieldReference>()!!.name
}
}
initMainFeedRequestFingerprint.method.apply {
// Finds the instruction where the map is being initialized in the constructor
val getHeaderIndex = indexOfFirstInstructionOrThrow {
getReference<FieldReference>().let {
it?.name == mainFeedRequestHeaderFieldName
}
}
val paramHeaderRegister = getInstruction<TwoRegisterInstruction>(getHeaderIndex).registerA
// Replace the `pagination_source` header value with `following` in the feed/timeline request.
addInstructions(
getHeaderIndex,
"""
invoke-static { v$paramHeaderRegister }, $EXTENSION_CLASS_DESCRIPTOR->setFollowingHeader(Ljava/util/Map;)Ljava/util/Map;
move-result-object v$paramHeaderRegister
"""
)
}
}
}

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.instagram.hide.explore
import app.revanced.patcher.fingerprint
internal val exploreResponseJsonParserFingerprint = fingerprint {
strings("sectional_items", "ExploreTopicalFeedResponse")
custom { method, _ -> method.name == "parseFromJson" }
}

View File

@@ -0,0 +1,33 @@
package app.revanced.patches.instagram.hide.explore
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
val hideExportFeedPatch = bytecodePatch(
name = "Hide explore feed",
description = "Hides posts and reels from the explore/search page.",
use = false
) {
compatibleWith("com.instagram.android")
execute {
exploreResponseJsonParserFingerprint.method.apply {
val sectionalItemStringIndex = exploreResponseJsonParserFingerprint.stringMatches!!.first().index
val sectionalItemStringRegister = getInstruction<OneRegisterInstruction>(sectionalItemStringIndex).registerA
/**
* Replacing the JSON key we want to skip with a random string that is not a valid JSON key.
* This way the feeds array will never be populated.
* Received JSON keys that are not handled are simply ignored, so there are no side effects.
*/
replaceInstruction(
sectionalItemStringIndex,
"const-string v$sectionalItemStringRegister, \"BOGUS\""
)
}
}
}

View File

@@ -49,7 +49,7 @@ val hideNavigationButtonsPatch = bytecodePatch(
val freeRegister = findFreeRegister(insertIndex, loopIndexRegister)
val instruction = getInstruction(endIndex - 1)
var instructions = buildString {
val instructions = buildString {
if (hideCreate!!) {
appendLine(
"""

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.instagram.misc.extension
import app.revanced.patches.instagram.misc.extension.hooks.applicationInitHook
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
val sharedExtensionPatch = sharedExtensionPatch(
"instagram",
applicationInitHook,
)

View File

@@ -0,0 +1,9 @@
package app.revanced.patches.instagram.misc.extension.hooks
import app.revanced.patches.shared.misc.extension.extensionHook
internal val applicationInitHook = extensionHook {
custom { method, classDef ->
method.name == "onCreate" && classDef.endsWith("/InstagramAppShell;")
}
}

View File

@@ -1,13 +1,27 @@
package app.revanced.patches.music.ad.video
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideVideoAdsPatch;"
@Suppress("unused")
val hideVideoAdsPatch = bytecodePatch(
name = "Hide music video ads",
description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.",
description = "Adds an option to hide ads that appear while listening to or streaming music videos, podcasts, or songs.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
@@ -15,9 +29,21 @@ val hideVideoAdsPatch = bytecodePatch(
)
execute {
addResources("music", "ad.video.hideVideoAdsPatch")
PreferenceScreen.ADS.addPreferences(
SwitchPreference("revanced_music_hide_video_ads"),
)
navigate(showVideoAdsParentFingerprint.originalMethod)
.to(showVideoAdsParentFingerprint.patternMatch!!.startIndex + 1)
.stop()
.addInstruction(0, "const/4 p1, 0x0")
.addInstructions(
0,
"""
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->showVideoAds(Z)Z
move-result p1
"""
)
}
}

View File

@@ -1,6 +1,8 @@
package app.revanced.patches.music.audio.exclusiveaudio
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.util.returnEarly
@Suppress("unused")
@@ -8,6 +10,11 @@ val enableExclusiveAudioPlaybackPatch = bytecodePatch(
name = "Enable exclusive audio playback",
description = "Enables the option to play audio without video.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"

View File

@@ -4,13 +4,27 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.util.findFreeRegister
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/PermanentRepeatPatch;"
@Suppress("unused")
val permanentRepeatPatch = bytecodePatch(
name = "Permanent repeat",
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
use = false,
description = "Adds an option to always repeat even if the playlist ends or another track is played."
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
@@ -18,13 +32,27 @@ val permanentRepeatPatch = bytecodePatch(
)
execute {
addResources("music", "interaction.permanentrepeat.permanentRepeatPatch")
PreferenceScreen.PLAYER.addPreferences(
SwitchPreference("revanced_music_play_permanent_repeat"),
)
val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex
val repeatIndex = startIndex + 1
repeatTrackFingerprint.method.apply {
// Start index is at a branch, but the same
// register is clobbered in both branch paths.
val freeRegister = findFreeRegister(startIndex + 1)
addInstructionsWithLabels(
startIndex,
"goto :repeat",
"""
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->permanentRepeat()Z
move-result v$freeRegister
if-nez v$freeRegister, :repeat
""",
ExternalLabel("repeat", instructions[repeatIndex]),
)
}

View File

@@ -1,17 +1,32 @@
package app.revanced.patches.music.layout.compactheader
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.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.findFreeRegister
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideCategoryBarPatch;"
@Suppress("unused")
val hideCategoryBar = bytecodePatch(
name = "Hide category bar",
description = "Hides the category bar at the top of the homepage.",
use = false,
description = "Adds an option to hide the category bar at the top of the homepage."
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
@@ -19,16 +34,27 @@ val hideCategoryBar = bytecodePatch(
)
execute {
addResources("music", "layout.compactheader.hideCategoryBar")
PreferenceScreen.GENERAL.addPreferences(
SwitchPreference("revanced_music_hide_category_bar"),
)
constructCategoryBarFingerprint.method.apply {
val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
val freeRegister = findFreeRegister(insertIndex, register)
addInstructions(
addInstructionsWithLabels(
insertIndex,
"""
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->hideCategoryBar()Z
move-result v$freeRegister
if-eqz v$freeRegister, :show
const/16 v$freeRegister, 0x8
invoke-virtual { v$register, v$freeRegister }, Landroid/view/View;->setVisibility(I)V
:show
nop
"""
)
}

View File

@@ -1,16 +1,31 @@
package app.revanced.patches.music.layout.premium
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.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideGetPremiumPatch;"
@Suppress("unused")
val hideGetPremiumPatch = bytecodePatch(
name = "Hide 'Get Music Premium' label",
description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
name = "Hide 'Get Music Premium'",
description = "Adds an option to hide the \"Get Music Premium\" label in the settings and account menu.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
@@ -18,6 +33,12 @@ val hideGetPremiumPatch = bytecodePatch(
)
execute {
addResources("music", "layout.premium.hideGetPremiumPatch")
PreferenceScreen.ADS.addPreferences(
SwitchPreference("revanced_music_hide_get_premium_label"),
)
hideGetPremiumFingerprint.method.apply {
val insertIndex = hideGetPremiumFingerprint.patternMatch!!.endIndex
@@ -37,12 +58,17 @@ val hideGetPremiumPatch = bytecodePatch(
)
}
membershipSettingsFingerprint.method.addInstructions(
membershipSettingsFingerprint.method.addInstructionsWithLabels(
0,
"""
const/4 v0, 0x0
return-object v0
""",
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->hideGetPremiumLabel()Z
move-result v0
if-eqz v0, :show
const/4 v0, 0x0
return-object v0
:show
nop
"""
)
}
}

View File

@@ -7,17 +7,31 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.newLabel
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideUpgradeButtonPatch;"
@Suppress("unused")
val removeUpgradeButtonPatch = bytecodePatch(
name = "Remove upgrade button",
description = "Removes the upgrade tab from the pivot bar.",
val hideUpgradeButton = bytecodePatch(
name = "Hide upgrade button",
description = "Hides the upgrade tab from the pivot bar.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
@@ -25,6 +39,15 @@ val removeUpgradeButtonPatch = bytecodePatch(
)
execute {
addResources("music", "layout.upgradebutton.hideUpgradeButtonPatch")
// TODO: Add an extension patch to allow this to be enabled/disabled in app.
if (false) {
PreferenceScreen.ADS.addPreferences(
SwitchPreference("revanced_music_hide_upgrade_button")
)
}
pivotBarConstructorFingerprint.method.apply {
val pivotBarElementFieldReference =
getInstruction(pivotBarConstructorFingerprint.patternMatch!!.endIndex - 1)
@@ -77,3 +100,9 @@ val removeUpgradeButtonPatch = bytecodePatch(
}
}
}
@Deprecated("Patch was renamed", ReplaceWith("hideUpgradeButton"))
@Suppress("unused")
val removeUpgradeButton = bytecodePatch{
dependsOn(hideUpgradeButton)
}

View File

@@ -1,6 +1,8 @@
package app.revanced.patches.music.misc.androidauto
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.util.returnEarly
@Suppress("unused")
@@ -8,6 +10,11 @@ val bypassCertificateChecksPatch = bytecodePatch(
name = "Bypass certificate checks",
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"

View File

@@ -1,13 +1,20 @@
package app.revanced.patches.music.misc.backgroundplayback
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.util.returnEarly
val backgroundPlaybackPatch = bytecodePatch(
name = "Remove background playback restrictions",
description = "Removes restrictions on background playback, including playing kids videos in the background.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
@@ -20,12 +27,6 @@ val backgroundPlaybackPatch = bytecodePatch(
"return-void",
)
backgroundPlaybackDisableFingerprint.method.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
""",
)
backgroundPlaybackDisableFingerprint.method.returnEarly(true)
}
}

View File

@@ -1,12 +1,17 @@
package app.revanced.patches.music.misc.gms
import app.revanced.patcher.patch.Option
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch
import app.revanced.patches.shared.castContextFetchFingerprint
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.primeMethodFingerprint
@Suppress("unused")
@@ -33,4 +38,23 @@ private fun gmsCoreSupportResourcePatch(
toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
gmsCoreVendorGroupIdOption = gmsCoreVendorGroupIdOption,
spoofedPackageSignature = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875",
)
executeBlock = {
addResources("shared", "misc.gms.gmsCoreSupportResourcePatch")
val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
PreferenceScreen.MISC.addPreferences(
IntentPreference(
"microg_settings",
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
"$gmsCoreVendorGroupId.android.gms"
}
)
)
}
) {
dependsOn(
addResourcesPatch,
settingsPatch
)
}

View File

@@ -0,0 +1,11 @@
package app.revanced.patches.music.misc.settings
import app.revanced.patcher.fingerprint
internal val googleApiActivityFingerprint = fingerprint {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
classDef.endsWith("GoogleApiActivity;") && method.name == "onCreate"
}
}

View File

@@ -0,0 +1,176 @@
package app.revanced.patches.music.misc.settings
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.settings.preference.*
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.shared.misc.settings.settingsPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.util.MethodUtil
private const val BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/settings/BaseActivityHook;"
private const val GOOGLE_API_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/music/settings/GoogleApiActivityHook;"
private val preferences = mutableSetOf<BasePreference>()
private val settingsResourcePatch = resourcePatch {
dependsOn(
resourceMappingPatch,
settingsPatch(
IntentPreference(
titleKey = "revanced_settings_title",
summaryKey = null,
intent = newIntent("revanced_settings_intent"),
) to "settings_headers",
preferences
)
)
execute {
// TODO: Remove this when search will be abstract.
copyResources(
"settings",
ResourceGroup(
"layout",
"revanced_music_settings_with_toolbar.xml"
)
)
val targetResource = "values/styles.xml"
inputStreamFromBundledResource(
"settings/music",
targetResource,
)!!.let { inputStream ->
"resources".copyXmlNode(
document(inputStream),
document("res/$targetResource"),
).close()
}
// Remove horizontal divider from the settings Preferences.
val styleFile = get("res/values/styles.xml")
styleFile.writeText(
styleFile.readText()
.replace(
"allowDividerAbove\">true",
"allowDividerAbove\">false"
).replace(
"allowDividerBelow\">true",
"allowDividerBelow\">false"
)
)
}
}
val settingsPatch = bytecodePatch(
description = "Adds settings for ReVanced to YouTube Music.",
) {
dependsOn(
sharedExtensionPatch,
settingsResourcePatch,
addResourcesPatch,
)
execute {
addResources("music", "misc.settings.settingsPatch")
addResources("shared", "misc.debugging.enableDebuggingPatch")
// Should make a separate debugging patch, but for now include it with all installations.
PreferenceScreen.MISC.addPreferences(
PreferenceScreenPreference(
key = "revanced_debug_screen",
sorting = Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_debug"),
NonInteractivePreference(
"revanced_debug_export_logs_to_clipboard",
tag = "app.revanced.extension.shared.settings.preference.ExportLogToClipboardPreference",
selectable = true
),
NonInteractivePreference(
"revanced_debug_logs_clear_buffer",
tag = "app.revanced.extension.shared.settings.preference.ClearLogBufferPreference",
selectable = true
)
)
)
)
// Add an "About" preference to the top.
preferences += NonInteractivePreference(
key = "revanced_settings_music_screen_0_about",
summaryKey = null,
tag = "app.revanced.extension.shared.settings.preference.ReVancedAboutPreference",
selectable = true,
)
// Modify GoogleApiActivity and remove all existing layout code.
// Must modify an existing activity and cannot add a new activity to the manifest,
// as that fails for root installations.
googleApiActivityFingerprint.method.addInstructions(
1,
"""
invoke-static { }, $GOOGLE_API_ACTIVITY_HOOK_CLASS_DESCRIPTOR->createInstance()Lapp/revanced/extension/music/settings/GoogleApiActivityHook;
move-result-object v0
invoke-static { v0, p0 }, $BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->initialize(Lapp/revanced/extension/shared/settings/BaseActivityHook;Landroid/app/Activity;)V
return-void
"""
)
// Remove other methods as they will break as the onCreate method is modified above.
googleApiActivityFingerprint.classDef.apply {
methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
}
}
finalize {
PreferenceScreen.close()
}
}
/**
* Creates an intent to open ReVanced settings.
*/
fun newIntent(settingsName: String) = IntentPreference.Intent(
data = settingsName,
targetClass = "com.google.android.gms.common.api.GoogleApiActivity"
) {
// The package name change has to be reflected in the intent.
setOrGetFallbackPackageName("com.google.android.apps.youtube.music")
}
object PreferenceScreen : BasePreferenceScreen() {
val ADS = Screen(
"revanced_settings_music_screen_1_ads",
summaryKey = null
)
val GENERAL = Screen(
"revanced_settings_music_screen_2_general",
summaryKey = null
)
val PLAYER = Screen(
"revanced_settings_music_screen_3_player",
summaryKey = null
)
val MISC = Screen(
"revanced_settings_music_screen_4_misc",
summaryKey = null
)
override fun commit(screen: PreferenceScreenPreference) {
preferences += screen
}
}

View File

@@ -1,12 +1,19 @@
package app.revanced.patches.music.misc.spoof
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.music.playservice.is_7_33_or_greater
import app.revanced.patches.music.playservice.is_8_11_or_greater
import app.revanced.patches.music.playservice.is_8_15_or_greater
import app.revanced.patches.music.playservice.versionCheckPatch
import app.revanced.patches.shared.misc.settings.preference.ListPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/spoof/SpoofVideoStreamsPatch;"
@@ -16,17 +23,36 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
fixMediaFetchHotConfigAlternativeChanges = { is_8_11_or_greater && !is_8_15_or_greater },
fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater },
block = {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
versionCheckPatch,
userAgentClientSpoofPatch
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52"
)
)
dependsOn(sharedExtensionPatch, versionCheckPatch, userAgentClientSpoofPatch)
},
executeBlock = {
addResources("music", "misc.fix.playback.spoofVideoStreamsPatch")
PreferenceScreen.MISC.addPreferences(
PreferenceScreenPreference(
key = "revanced_spoof_video_streams_screen",
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
preferences = setOf(
SwitchPreference("revanced_spoof_video_streams"),
ListPreference("revanced_spoof_video_streams_client_type"),
)
)
)
musicActivityOnCreateFingerprint.method.addInstruction(
1, // Must use 1 index so context is set by extension patch.
0,
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setClientOrderToUse()V"
)
}

View File

@@ -150,7 +150,6 @@ internal val nerdsStatsVideoFormatBuilderFingerprint = fingerprint {
}
internal val patchIncludedExtensionMethodFingerprint = fingerprint {
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
returns("Z")
parameters()
custom { method, classDef ->

View File

@@ -9,8 +9,8 @@ import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.util.findFreeRegister
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
@@ -46,6 +46,8 @@ fun spoofVideoStreamsPatch(
dependsOn(addResourcesPatch)
execute {
addResources("shared", "misc.fix.playback.spoofVideoStreamsPatch")
// region Enable extension helper method used by other patches
patchIncludedExtensionMethodFingerprint.method.returnEarly(true)

View File

@@ -2,12 +2,6 @@ package app.revanced.patches.viber.ads
import app.revanced.patcher.fingerprint
internal val adsFreeFingerprint = fingerprint {
returns("I")
parameters()
custom { method, classDef ->
classDef.type.contains("com/viber/voip/feature/viberplus") &&
classDef.superclass?.contains("com/viber/voip/core/feature") == true && // Must extend com.viber.voip.core.feature.?
classDef.methods.count() == 1
}
internal val findAdStringFingerprint = fingerprint {
strings("viber_plus_debug_ads_free_flag")
}

View File

@@ -1,17 +1,41 @@
package app.revanced.patches.viber.ads
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
@Suppress("unused")
val hideAdsPatch = bytecodePatch(
name = "Hide Ads",
description = "Hides ad banners between chats.",
) {
compatibleWith("com.viber.voip"("25.9.2.0"))
compatibleWith("com.viber.voip"("25.9.2.0", "26.1.2.0"))
execute {
// Return 1 (true) indicating ads should be disabled.
adsFreeFingerprint.method.returnEarly(1)
val method = findAdStringFingerprint.method
// Find the ads free string index
val stringIndex = findAdStringFingerprint.stringMatches!!.first().index
// Search backwards from the string to find the `new-instance` (TypeReference) instruction
val typeRefIndex = method.indexOfFirstInstructionReversedOrThrow(stringIndex) { this.opcode == Opcode.NEW_INSTANCE }
// Get the class name from the TypeReference
val targetClass = method.getInstruction<ReferenceInstruction>(typeRefIndex).reference as TypeReference
// Patch the ads-free method to always return true
fingerprint {
returns("I")
parameters()
custom { method, classDef ->
classDef == targetClass
}
}.method.returnEarly(1)
}
}

View File

@@ -89,7 +89,7 @@ val downloadsPatch = bytecodePatch(
// Main activity is used to launch downloader intent.
mainActivityOnCreateFingerprint.method.addInstruction(
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
)

View File

@@ -49,6 +49,7 @@ val hideButtonsPatch = resourcePatch(
SwitchPreference("revanced_hide_report_button"),
SwitchPreference("revanced_hide_save_button"),
SwitchPreference("revanced_hide_share_button"),
SwitchPreference("revanced_hide_shop_button"),
SwitchPreference("revanced_hide_stop_ads_button"),
SwitchPreference("revanced_hide_thanks_button"),
)

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.layout.seekbar
import app.revanced.patcher.fingerprint
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
import app.revanced.util.containsLiteralInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
@@ -103,7 +104,7 @@ internal val launchScreenLayoutTypeFingerprint = fingerprint {
custom { method, _ ->
val firstParameter = method.parameterTypes.firstOrNull()
// 19.25 - 19.45
(firstParameter == "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
(firstParameter == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|| firstParameter == "Landroid/app/Activity;") // 19.46+
&& method.containsLiteralInstruction(launchScreenLayoutTypeLotteFeatureFlag)
}

View File

@@ -68,7 +68,7 @@ val shortsAutoplayPatch = bytecodePatch(
// Main activity is used to check if app is in pip mode.
mainActivityOnCreateFingerprint.method.addInstruction(
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V",
)

View File

@@ -90,8 +90,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
// Activity is used as the context to launch an Intent.
mainActivityOnCreateFingerprint.method.addInstruction(
1,
"invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->" +
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
"setMainActivity(Landroid/app/Activity;)V",
)

View File

@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.layout.theme
import app.revanced.patcher.fingerprint
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -37,6 +38,6 @@ internal val splashScreenStyleFingerprint = fingerprint {
parameters("Landroid/os/Bundle;")
literal { SPLASH_SCREEN_STYLE_FEATURE_FLAG }
custom { method, classDef ->
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}

View File

@@ -40,9 +40,7 @@ val announcementsPatch = bytecodePatch(
)
mainActivityOnCreateFingerprint.method.addInstruction(
// Insert index must be greater than the insert index used by GmsCoreSupport,
// as both patch the same method and GmsCore check should be first.
1,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V",
)
}

View File

@@ -22,6 +22,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/EnableDebuggingPatch;"
// TODO: Refactor this into a shared patch that can be used by both YT and YT Music.
// Almost all of the feature flag hooks are the same between both apps.
val enableDebuggingPatch = bytecodePatch(
name = "Enable debugging",
description = "Adds options for debugging and exporting ReVanced logs to the clipboard.",
@@ -45,6 +47,7 @@ val enableDebuggingPatch = bytecodePatch(
)
execute {
addResources("shared", "misc.debugging.enableDebuggingPatch")
addResources("youtube", "misc.debugging.enableDebuggingPatch")
PreferenceScreen.MISC.addPreferences(
@@ -58,13 +61,13 @@ val enableDebuggingPatch = bytecodePatch(
SwitchPreference("revanced_debug_toast_on_error"),
NonInteractivePreference(
"revanced_debug_export_logs_to_clipboard",
tag = "app.revanced.extension.youtube.settings.preference.ExportLogToClipboardPreference",
selectable = true,
tag = "app.revanced.extension.shared.settings.preference.ExportLogToClipboardPreference",
selectable = true
),
NonInteractivePreference(
"revanced_debug_logs_clear_buffer",
tag = "app.revanced.extension.youtube.settings.preference.ClearLogBufferPreference",
selectable = true,
tag = "app.revanced.extension.shared.settings.preference.ClearLogBufferPreference",
selectable = true
),
),
),

View File

@@ -34,12 +34,7 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
addResources("youtube", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
mainActivityOnCreateFingerprint.method.addInstruction(
// 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,
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
)
}

View File

@@ -3,4 +3,5 @@ package app.revanced.patches.youtube.misc.extension
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.extension.hooks.*
val sharedExtensionPatch = sharedExtensionPatch("youtube", applicationInitHook)
val sharedExtensionPatch = sharedExtensionPatch("youtube",
applicationInitHook, applicationInitOnCrateHook)

View File

@@ -1,11 +1,23 @@
package app.revanced.patches.youtube.misc.extension.hooks
import app.revanced.patches.shared.misc.extension.extensionHook
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
/**
* Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
*/
// Extension context is the Activity itself.
internal val applicationInitHook = extensionHook {
// Does _not_ resolve to the YouTube main activity.
// Required as some hooked code runs before the main activity is launched.
strings("Application creation", "Application.onCreate")
}
internal val applicationInitOnCrateHook = extensionHook {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}

View File

@@ -53,7 +53,7 @@ private fun gmsCoreSupportResourcePatch(
gmsCoreVendorGroupIdOption = gmsCoreVendorGroupIdOption,
spoofedPackageSignature = "24bb24c05e47e0aefa68a58a766179d9b613a600",
executeBlock = {
addResources("youtube", "misc.gms.gmsCoreSupportResourcePatch")
addResources("shared", "misc.gms.gmsCoreSupportResourcePatch")
val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
@@ -62,10 +62,14 @@ private fun gmsCoreSupportResourcePatch(
"microg_settings",
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
"$gmsCoreVendorGroupId.android.gms"
},
),
}
)
)
},
}
) {
dependsOn(settingsPatch, addResourcesPatch, accountCredentialsInvalidTextPatch)
dependsOn(
addResourcesPatch,
settingsPatch,
accountCredentialsInvalidTextPatch
)
}

View File

@@ -127,8 +127,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
// Litho filtering based on navigation tab before the tab is updated.
mainActivityOnBackPressedFingerprint.method.addInstruction(
0,
"invoke-static { p0 }, " +
"$EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V",
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V",
)
// Hook the search bar.

View File

@@ -29,7 +29,9 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
import com.android.tools.smali.dexlib2.util.MethodUtil
private const val EXTENSION_CLASS_DESCRIPTOR =
private const val BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/settings/BaseActivityHook;"
private const val LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/settings/LicenseActivityHook;"
internal var appearanceStringId = -1L
@@ -37,10 +39,6 @@ internal var appearanceStringId = -1L
private val preferences = mutableSetOf<BasePreference>()
fun addSettingPreference(screen: BasePreference) {
preferences += screen
}
private val settingsResourcePatch = resourcePatch {
dependsOn(
resourceMappingPatch,
@@ -225,7 +223,9 @@ val settingsPatch = bytecodePatch(
licenseActivityOnCreateFingerprint.method.addInstructions(
1,
"""
invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->initialize(Landroid/app/Activity;)V
invoke-static {}, $LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->createInstance()Lapp/revanced/extension/youtube/settings/LicenseActivityHook;
move-result-object v0
invoke-static { v0, p0 }, $BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->initialize(Lapp/revanced/extension/shared/settings/BaseActivityHook;Landroid/app/Activity;)V
return-void
"""
)
@@ -249,7 +249,7 @@ val settingsPatch = bytecodePatch(
).toMutable().apply {
addInstructions(
"""
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
invoke-static { p1 }, $LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
move-result-object p1
invoke-super { p0, p1 }, $superclass->attachBaseContext(Landroid/content/Context;)V
return-void
@@ -294,7 +294,7 @@ val settingsPatch = bytecodePatch(
addInstructions(
"""
invoke-super { p0, p1 }, Landroid/app/Activity;->onConfigurationChanged(Landroid/content/res/Configuration;)V
invoke-static { p0, p1 }, $EXTENSION_CLASS_DESCRIPTOR->handleConfigurationChanged(Landroid/app/Activity;Landroid/content/res/Configuration;)V
invoke-static { p0, p1 }, $LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->handleConfigurationChanged(Landroid/app/Activity;Landroid/content/res/Configuration;)V
return-void
"""
)
@@ -309,15 +309,15 @@ val settingsPatch = bytecodePatch(
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructionsAtControlFlowLabel(
index,
"invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->updateLightDarkModeStatus(Ljava/lang/Enum;)V",
"invoke-static { v$register }, ${LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR}->updateLightDarkModeStatus(Ljava/lang/Enum;)V",
)
}
}
// Add setting to force cairo settings fragment on/off.
// Add setting to force Cairo settings fragment on/off.
cairoFragmentConfigFingerprint.method.insertLiteralOverride(
CAIRO_CONFIG_LITERAL_VALUE,
"$EXTENSION_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z"
"$LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z"
)
}

View File

@@ -67,16 +67,15 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
// Language strings are declared in Setting patch.
entriesKey = "revanced_language_entries",
entryValuesKey = "revanced_language_entry_values",
tag = "app.revanced.extension.shared.settings.preference.SortedListPreference"
tag = "app.revanced.extension.youtube.settings.preference.SpoofAudioSelectorListPreference"
),
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
),
),
)
)
)
mainActivityOnCreateFingerprint.method.addInstruction(
1, // Must use 1 index so context is set by extension patch.,
0,
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setClientOrderToUse()V"
)
}

View File

@@ -4,6 +4,8 @@ import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal const val YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
internal val conversionContextFingerprintToString = fingerprint {
parameters()
strings(
@@ -48,7 +50,7 @@ internal val mainActivityConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters()
custom { _, classDef ->
classDef.endsWith("/MainActivity;")
classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}
@@ -57,7 +59,7 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint {
returns("V")
parameters()
custom { method, classDef ->
method.name == "onBackPressed" && classDef.endsWith("/MainActivity;")
method.name == "onBackPressed" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}
@@ -65,7 +67,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
}
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.video.audio
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
@@ -14,6 +15,7 @@ import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
import app.revanced.util.findMethodFromToString
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertLiteralOverride
@@ -61,6 +63,11 @@ val forceOriginalAudioPatch = bytecodePatch(
)
)
mainActivityOnCreateFingerprint.method.addInstruction(
0,
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setPreferredLanguage()V"
)
// Disable feature flag that ignores the default track flag
// and instead overrides to the user region language.
if (is_20_07_or_greater) {

View File

@@ -30,6 +30,10 @@ Second \"item\" text"</string>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -96,6 +100,7 @@ Second \"item\" text"</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>
<patch id="layout.buttons.navigation.navigationButtonsPatch">
@@ -207,8 +212,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
</patch>
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
@@ -240,6 +243,21 @@ Second \"item\" text"</string>
<patch id="interaction.seekbar.enableSlideToSeekPatch">
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
</patch>
<patch id="ad.video.hideVideoAdsPatch">
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
</patch>
<patch id="layout.compactheader.hideCategoryBar">
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
</patch>
</app>
<app id="twitch">

View File

@@ -30,6 +30,10 @@ Second \"item\" text"</string>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -96,6 +100,7 @@ Second \"item\" text"</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>
<patch id="layout.buttons.navigation.navigationButtonsPatch">
@@ -207,8 +212,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
</patch>
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
@@ -240,6 +243,21 @@ Second \"item\" text"</string>
<patch id="interaction.seekbar.enableSlideToSeekPatch">
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
</patch>
<patch id="ad.video.hideVideoAdsPatch">
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
</patch>
<patch id="layout.compactheader.hideCategoryBar">
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ Second \"item\" text"</string>
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">إعدادات GmsCore</string>
<string name="microg_settings_summary">إعدادات لـ GmsCore</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="gms_core_toast_not_installed_message">لم يتم تثبيت MicroG GmsCore. قم بتثبيته.</string>
<string name="gms_core_dialog_title">الإجراء مطلوب</string>
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
انقر فوق زر الاستمرار واسمح بتغييرات التحسين."</string>
<string name="gms_core_dialog_continue_text">متابعة</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
<string name="revanced_spoof_video_streams_screen_summary">تزييف تدفقات الفيديو الخاصة بالعميل لمنع حدوث مشكلات أثناء التشغيل</string>
<string name="revanced_spoof_video_streams_screen_title">انتحال بثوث الفيديو</string>
<string name="revanced_spoof_video_streams_screen_summary">انتحال بثوث الفيديو الخاصة بالعميل لمنع مشكلات التشغيل</string>
<string name="revanced_spoof_video_streams_title">Spoof Video Streams</string>
<string name="revanced_spoof_video_streams_summary_on">"تدفقات الفيديو مزورة
إذا كنت مستخدمًا لـ YouTube Premium، فقد لا يكون هذا الإعداد مطلوبًا"</string>
<string name="revanced_spoof_video_streams_summary_off">"لم يتم انتحال بثوث الفيديو
قد لا يعمل التشغيل"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">قد يؤدي إيقاف تشغيل هذا الإعداد إلى مشكلات في التشغيل.</string>
<string name="revanced_spoof_video_streams_client_type_title">العميل الافتراضي</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">تصحيح الأخطاء</string>
<string name="revanced_debug_screen_summary">تمكين أو تعطيل خيارات تصحيح الأخطاء</string>
<string name="revanced_debug_title">تسجيل تصحيح الأخطاء</string>
<string name="revanced_debug_summary_on">تم تمكين تسجيلات تصحيح الأخطاء</string>
<string name="revanced_debug_summary_off">تم تعطيل تسجيلات تصحيح الأخطاء</string>
<string name="revanced_debug_export_logs_to_clipboard_title">تصدير سجلات تصحيح الأخطاء</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">نسخ سجلات تصحيح أخطاء ReVanced إلى الحافظة</string>
<string name="revanced_debug_logs_disabled">تم تعطيل تسجيلات تصحيح الأخطاء</string>
<string name="revanced_debug_logs_none_found">لم يتم العثور على سجلات</string>
<string name="revanced_debug_logs_copied_to_clipboard">تم نسخ السجلات</string>
<string name="revanced_debug_logs_failed_to_export">فشل تصدير السجلات: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">مسح سجلات تصحيح الأخطاء</string>
<string name="revanced_debug_logs_clear_buffer_summary">يمسح جميع سجلات تصحيح أخطاء ReVanced المخزنة</string>
<string name="revanced_debug_logs_clear_toast">تم مسح السجلات</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
<string name="revanced_shorts_disable_background_playback_summary_off">تم تمكين تشغيل Shorts بالخلفية</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">تصحيح الأخطاء</string>
<string name="revanced_debug_screen_summary">تمكين أو تعطيل خيارات تصحيح الأخطاء</string>
<string name="revanced_debug_title">تسجيل تصحيح الأخطاء</string>
<string name="revanced_debug_summary_on">تم تمكين تسجيلات تصحيح الأخطاء</string>
<string name="revanced_debug_summary_off">تم تعطيل تسجيلات تصحيح الأخطاء</string>
<string name="revanced_debug_protobuffer_title">سجل بروتوكول التخزين المؤقت</string>
<string name="revanced_debug_protobuffer_summary_on">تتضمن سجلات التصحيح التخزين المؤقت</string>
<string name="revanced_debug_protobuffer_summary_off">لا تتضمن سجلات التصحيح التخزين المؤقت</string>
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
<string name="revanced_debug_toast_on_error_user_dialog_message">"يؤدي إيقاف تشغيل ملاحظات الأخطاء إلى إخفاء كافة إشعارات أخطاء ReVanced.
لن يتم إعلامك بأي أخطاء غير متوقعة."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">تصدير سجلات تصحيح الأخطاء</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">نسخ سجلات تصحيح أخطاء ReVanced إلى الحافظة</string>
<string name="revanced_debug_logs_disabled">تم تعطيل تسجيلات تصحيح الأخطاء</string>
<string name="revanced_debug_logs_none_found">لم يتم العثور على سجلات</string>
<string name="revanced_debug_logs_copied_to_clipboard">تم نسخ السجلات</string>
<string name="revanced_debug_logs_failed_to_export">فشل تصدير السجلات: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">مسح سجلات تصحيح الأخطاء</string>
<string name="revanced_debug_logs_clear_buffer_summary">يمسح جميع سجلات تصحيح أخطاء ReVanced المخزنة</string>
<string name="revanced_debug_logs_clear_toast">تم مسح السجلات</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">إخفاء بطاقات الألبوم</string>
@@ -602,6 +621,10 @@ Second \"item\" text"</string>
<string name="revanced_hide_clip_button_title">إخفاء المقطع</string>
<string name="revanced_hide_clip_button_summary_on">تم إخفاء زر إنشاء مقطع</string>
<string name="revanced_hide_clip_button_summary_off">يتم عرض زر إنشاء مقطع</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">إخفاء المتجر</string>
<string name="revanced_hide_shop_button_summary_on">زر المتجر مخفي</string>
<string name="revanced_hide_shop_button_summary_off">زر المتجر معروض</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">إخفاء حفظ</string>
<string name="revanced_hide_save_button_summary_on">زر الحفظ مخفي</string>
@@ -700,9 +723,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">تم إخفاء قائمة المقطع الصوتي</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">يتم عرض قائمة المقطع الصوتي</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"تم إخفاء قائمة المقطع الصوتي
<string name="revanced_hide_player_flyout_audio_track_not_available">"قائمة المسارات الصوتية مخفية
لعرض قائمة المقطع الصوتي، غيّر 'Spoof Video Streams' إلى iOS TV"</string>
لعرض قائمة المسارات الصوتية، غيّر 'تزييف تدفقات الفيديو' إلى iPadOS"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">إخفاء المشاهدة في VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">تم إخفاء قائمة المشاهدة في الوضع الافتراضي</string>
@@ -1415,10 +1438,6 @@ Second \"item\" text"</string>
يمكن أن يؤدي تفعيل هذا إلى فتح جودة أعلى للفيديو"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">قد يؤدي تمكين هذا إلى تباطؤ تشغيل الفيديو وتدهور عمر البطارية وآثار جانبية غير معروفة.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">إعدادات GmsCore</string>
<string name="microg_settings_summary">إعدادات لـ GmsCore</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">الاهتزاز عند الضغط</string>
<string name="revanced_disable_haptic_feedback_summary">تغيير الاهتزاز عند الضغط</string>
@@ -1458,7 +1477,7 @@ Second \"item\" text"</string>
<string name="revanced_force_original_audio_summary_on">استخدام لغة الصوت الأصلية</string>
<string name="revanced_force_original_audio_summary_off">استخدام الصوت الافتراضي</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">لاستخدام هذه الميزة، غيّر \'Spoof Video Streams\' إلى iOS TV</string>
<string name="revanced_force_original_audio_not_available">لاستخدام هذه الميزة، غيّر \"تزوير تدفقات الفيديو\" إلى أي عميل باستثناء Android Studio</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1532,35 +1551,54 @@ Second \"item\" text"</string>
<string name="revanced_slide_to_seek_summary_off">تم تعطيل التمرير للتقديم أو الترجيع</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
<string name="revanced_spoof_video_streams_screen_summary">تزييف تدفقات الفيديو الخاصة بالعميل لمنع حدوث مشكلات أثناء التشغيل</string>
<string name="revanced_spoof_video_streams_title">Spoof Video Streams</string>
<string name="revanced_spoof_video_streams_summary_on">يتم تزييف تدفقات الفيديو</string>
<string name="revanced_spoof_video_streams_summary_off">"لا يتم تزييف تدفقات الفيديو
قد لا يعمل تشغيل الفيديو"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">إيقاف تشغيل هذا الإعداد قد يسبب مشاكل في تشغيل الفيديو.</string>
<string name="revanced_spoof_video_streams_client_type_title">العميل الافتراضي</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">فرض iOS AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">يتم فرض ترميز فيديو على AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">يتم تحديد ترميز الفيديو تلقائيًا</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"قد يؤدي تمكين هذا إلى تحسين عمر البطارية وإصلاح تقطيع التشغيل.
AVC لديه حد أقصى للدقة 1080p، لا يتوفر ترميز الصوت Opus، وسوف يستخدم تشغيل الفيديو بيانات إنترنت أكثر من VP9 أو AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">الآثار الجانبية لمحاكاة هوية iOS</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• قد لا يتم تشغيل الأفلام أو الفيديوهات المدفوعة
• مستوى الصوت الثابت غير متوفر
• تنتهي الفيديوهات قبل ب 1 ثانية"</string>
<string name="revanced_spoof_video_streams_about_title">الآثار الجانبية للتزوير</string>
<string name="revanced_spoof_video_streams_about_android_title">الآثار الجانبية لمحاكاة هوية Android</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• قائمة المقطع الصوتي مفقودة
• مستوى الصوت الثابت غير متاح
• فرض الصوت الأصلي غير متوفر"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• قائمة المسارات الصوتية مفقودة
• مستوى الصوت المستقر غير متاح"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• قد يتوقف الفيديو عند 1:00، أو قد لا يكون متاحًا في بعض المناطق</string>
<string name="revanced_spoof_video_streams_about_experimental">• عميل تجريبي وقد يتوقف عن العمل في أي وقت</string>
<string name="revanced_spoof_video_streams_about_no_av1">• لا يوجد ترميز الفيديو AV1</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• قد لا يتم تشغيل الفيديوهات المخصصة للأطفال عند تسجيل الخروج أو عند استخدام وضع التصفح المتخفي</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">عرض في إحصاءات تقنية</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">يتم عرض نوع العميل في إحصاءات تقنية</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">تم إخفاء نوع العميل في إحصاءات تقنية</string>
<string name="revanced_spoof_video_streams_language_title">لغة البث الصوتي الافتراضية للواقع الافتراضي VR</string>
<string name="revanced_spoof_video_streams_language_title">لغة بث الصوت</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">لتحديد لغة صوتية معينة، قم بإيقاف تشغيل \"فرض لغة الصوت الأصلية\"</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">حول</string>
<string name="revanced_settings_music_screen_1_ads_title">إعلانات</string>
<string name="revanced_settings_music_screen_2_general_title">عام</string>
<string name="revanced_settings_music_screen_3_player_title">المشغل</string>
<string name="revanced_settings_music_screen_4_misc_title">متنوعة</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">إخفاء إعلانات الفيديو</string>
<string name="revanced_music_hide_video_ads_summary_on">تم إخفاء إعلانات الفيديو</string>
<string name="revanced_music_hide_video_ads_summary_off">تم عرض إعلانات الفيديو</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">تمكين التكرار الدائم</string>
<string name="revanced_music_play_permanent_repeat_summary_on">تم تمكين التكرار الدائم</string>
<string name="revanced_music_play_permanent_repeat_summary_off">تم تعطيل التكرار الدائم</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">إخفاء شريط الفئات</string>
<string name="revanced_music_hide_category_bar_summary_on">شريط الفئات مخفي</string>
<string name="revanced_music_hide_category_bar_summary_off">شريط الفئات معروض</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">إخفاء تسمية \'الحصول على Music Premium\'</string>
<string name="revanced_music_hide_get_premium_label_summary_on">التسمية مخفية</string>
<string name="revanced_music_hide_get_premium_label_summary_off">التسمية معروضة</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">إخفاء زر الترقية</string>
<string name="revanced_music_hide_upgrade_button_summary_on">الزر مخفي</string>
<string name="revanced_music_hide_upgrade_button_summary_off">الزر معروض</string>
</patch>
</app>
<app id="twitch">

View File

@@ -30,6 +30,10 @@ Second \"item\" text"</string>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -96,6 +100,7 @@ Second \"item\" text"</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>
<patch id="layout.buttons.navigation.navigationButtonsPatch">
@@ -209,8 +214,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
</patch>
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
@@ -242,6 +245,21 @@ Second \"item\" text"</string>
<patch id="interaction.seekbar.enableSlideToSeekPatch">
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
</patch>
<patch id="ad.video.hideVideoAdsPatch">
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
</patch>
<patch id="layout.compactheader.hideCategoryBar">
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ Yeni dilləri tərcümə etmək üçün translate.revanced.app 'ə daxil olun"</
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Tənzimləmələri</string>
<string name="microg_settings_summary">GmsCore üçün Tənzimləmələr</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="gms_core_toast_not_installed_message">MicroG GmsCore quraşdırılmayıb. Bunu quraşdır.</string>
<string name="gms_core_dialog_title">Fəaliyyət lazımdır</string>
@@ -84,6 +86,37 @@ MicroG üçün batareya optimallaşmasın qapatma batareya istifadəsinə mənfi
Davam et düyməsinə toxun və optimallaşdırma dəyişikliklərin qəbul et."</string>
<string name="gms_core_dialog_continue_text">Davam et</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Video yayımları saxtalaşdır</string>
<string name="revanced_spoof_video_streams_screen_summary">Oynatma problemlərin önləmək üçün qəbuledici video yayımların saxtalaşdır</string>
<string name="revanced_spoof_video_streams_screen_title">Video yayımların saxtalaşdır</string>
<string name="revanced_spoof_video_streams_screen_summary">Oynatma problemlərin önləmək üçün qəbuledici video yayımların saxtalaşdır</string>
<string name="revanced_spoof_video_streams_title">Video yayımları saxtalaşdır</string>
<string name="revanced_spoof_video_streams_summary_on">"Video yayımları saxtalaşdırılıb
Əgər YouTube Premium istifadəçisisinizsə, bu tənzimlənmə tələb olunmaya bilər"</string>
<string name="revanced_spoof_video_streams_summary_off">"Video yayımları saxtalaşmayıb
Oynatma işləməyə bilər"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Bu tənzimləməni qapatmaq oynatma problemlərinə səbəb ola bilər.</string>
<string name="revanced_spoof_video_streams_client_type_title">İlkin qəbuledici</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Sazlama</string>
<string name="revanced_debug_screen_summary">Sazlama seçimlərini aktiv/qeyri-aktiv et</string>
<string name="revanced_debug_title">Sazlama jurnalı</string>
<string name="revanced_debug_summary_on">Sazlama jurnalı işləkdir</string>
<string name="revanced_debug_summary_off">Sazlama jurnalı qeyri-aktivdir</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Sazlama qeydlərini ixrac edin</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">ReVanced sazlama qeydlərini buferə köçürür</string>
<string name="revanced_debug_logs_disabled">Sazlama qeydi qapalıdır</string>
<string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string>
<string name="revanced_debug_logs_copied_to_clipboard">Qeydlər köçürüldü</string>
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string>
<string name="revanced_debug_logs_clear_buffer_summary">Saxlanılan bütün ReVanced sazlama qeydlərini təmizləyir</string>
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ Davam et düyməsinə toxun və optimallaşdırma dəyişikliklərin qəbul et."
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts arxa plan oynatma aktivdir</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Sazlama</string>
<string name="revanced_debug_screen_summary">Sazlama seçimlərini aktiv/qeyri-aktiv et</string>
<string name="revanced_debug_title">Sazlama jurnalı</string>
<string name="revanced_debug_summary_on">Sazlama jurnalı işləkdir</string>
<string name="revanced_debug_summary_off">Sazlama jurnalı qeyri-aktivdir</string>
<string name="revanced_debug_protobuffer_title">Bufer protokol jurnalı</string>
<string name="revanced_debug_protobuffer_summary_on">Sazlama jurnallarına protokol buferi daxildir</string>
<string name="revanced_debug_protobuffer_summary_off">Sazlama jurnallarına protokol buferi daxil deyil</string>
@@ -132,15 +160,6 @@ Hər halda, bunu aktivləşdirmə IP ünvanınız kimi bəzi istifadəçi məlum
<string name="revanced_debug_toast_on_error_user_dialog_message">"Xəta ani bildirişlərin qapatmaq, bütün ReVanced xəta bildirişlərin gizlədir.
Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Sazlama qeydlərini ixrac edin</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">ReVanced sazlama qeydlərini buferə köçürür</string>
<string name="revanced_debug_logs_disabled">Sazlama qeydi qapalıdır</string>
<string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string>
<string name="revanced_debug_logs_copied_to_clipboard">Qeydlər köçürüldü</string>
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string>
<string name="revanced_debug_logs_clear_buffer_summary">Saxlanılan bütün ReVanced sazlama qeydlərini təmizləyir</string>
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">Albom kartlarını gizlət</string>
@@ -602,6 +621,10 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz
<string name="revanced_hide_clip_button_title">Kəsmə/ gizlət</string>
<string name="revanced_hide_clip_button_summary_on">Kəsmə düyməsi gizlidir</string>
<string name="revanced_hide_clip_button_summary_off">Kəsmə düyməsi göstərilir</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">Mağazanı Gizlət</string>
<string name="revanced_hide_shop_button_summary_on">Mağaza düyməsi gizlidir</string>
<string name="revanced_hide_shop_button_summary_off">Mağaza düyməsi görünür</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">Saxlayın-ı Gizlət</string>
<string name="revanced_hide_save_button_summary_on">Saxlayın düyməsi gizlidir</string>
@@ -700,9 +723,9 @@ Bu seçimi dəyişdirmə işə düşmürsə, Gizli rejimə keçməyə çalışı
<string name="revanced_hide_player_flyout_audio_track_summary_on">Səs axını menyusu gizlidir</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Səs axını menyusu göstərilir</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audio trek seçimi gizlədilib
<string name="revanced_hide_player_flyout_audio_track_not_available">"Səs trek menyusu gizlidir
Audio trek seçimin göstərmək üçün \"Video axınları saxtalaşdır\"ı iOS TV-yə dəyiş"</string>
Səs treki menyusunu göstərmək üçün \"Video yayımları saxtalaşdır\"ı iPadOS-a dəyiş"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">\"VR-da İzləni\" gizlət</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR menyusunda izləmə gizlidir</string>
@@ -1414,10 +1437,6 @@ Yüksək video keyfiyyətlər görünə bilər, ancaq video oynadılmasında qı
Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">Bunu aktivləşdirmə, video oynatma donmalarına, daha pis batareya istismarına və bilinməyən yan təsirlərə səbəb ola bilər.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Tənzimləmələri</string>
<string name="microg_settings_summary">GmsCore üçün Tənzimləmələr</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">Əks-əlaqə reaksiyası</string>
<string name="revanced_disable_haptic_feedback_summary">Əks-əlaqə reaksiyasını dəyişdir</string>
@@ -1457,7 +1476,7 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
<string name="revanced_force_original_audio_summary_on">Orijinal səs dilini istifadə</string>
<string name="revanced_force_original_audio_summary_off">İlkin səs istifadəsi</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">Bu xüsusiyyəti istifadə etmək üçün \"Saxta video yayımların\" iOS TV-yə dəyiş</string>
<string name="revanced_force_original_audio_not_available">Bu funksiyanı istifadə etmək üçün \"Video yayımları saxtalaşdırı\" Android Studio savayı istənilən qəbulediciyə dəyiş</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1531,35 +1550,54 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
<string name="revanced_slide_to_seek_summary_off">Axtarmaq üçün sürüşdürmə aktiv deyil</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Video yayımları saxtalaşdır</string>
<string name="revanced_spoof_video_streams_screen_summary">Oynatma problemlərin önləmək üçün qəbuledici video yayımların saxtalaşdır</string>
<string name="revanced_spoof_video_streams_title">Video yayımları saxtalaşdır</string>
<string name="revanced_spoof_video_streams_summary_on">Video yayımları saxtalaşdırılır</string>
<string name="revanced_spoof_video_streams_summary_off">"Video yayımlar saxtalaşdırılmır
Video oynatma işləməyə bilər"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Bu seçimi bağlamaq, video oynatma problemlərinə səbəb olar.</string>
<string name="revanced_spoof_video_streams_client_type_title">İlkin qəbuledici</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">IOS-da AVC (H.264)-ni məcbur et</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video kodlama AVC (H.264)-yə məcbur edilir</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video kodlayıcı avtomatik müəyyən edilir</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Bunu aktivləşdirmə, batareya ömrün yaxşılaşdıra və oynatma qırılmasın düzəldə bilər.
AVC maksimum 1080p görüntü imkanına malikdir, Opus audio kodlama olmur və video oynatma VP9 və ya AV1-dən daha çox internet məlumatı sərf edəcək."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS saxtalaşdırma yan təsirləri</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Filmlər və ya ödənişli videolar oynadıla bilməz
• Stabil səs səviyyəsi mövcud deyil
• Videolar 1 saniyə tez bitir"</string>
<string name="revanced_spoof_video_streams_about_title">Saxtakarlıq yan təsirləri</string>
<string name="revanced_spoof_video_streams_about_android_title">Android saxtalaşdırma yan təsirləri</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Səs treki menyusu yoxdur
• Sabit səs səviyyəsi yoxdur
• İlkin səsi məcbur etmə mümkün deyil"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Səs treki menyusu əlçatmazdır
• Sabit səs səviyyəsi yoxdur"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• Video 01:00-da dayana bilər və ya bəzi bölgələrdə mövcud olmaya bilər</string>
<string name="revanced_spoof_video_streams_about_experimental">• Təcrübi qəbuledici və hər vaxt işləməyi dayandıra bilər</string>
<string name="revanced_spoof_video_streams_about_no_av1">• AV1 video kodlayıcı yoxdur</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Giriş edilməyəndə və ya gizli rejimdə uşaq videoları oynadıla bilməz</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">İstək üçün Statistikada göstər</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Qəbuledici növü İstək üçün statistikada göstərilir</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Qəbuledici nerd üçün Statistikada gizlidir</string>
<string name="revanced_spoof_video_streams_language_title">VR-da ilkin səs yayımı dili</string>
<string name="revanced_spoof_video_streams_language_title">Səs yayım dili</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Xüsusi səs dilini seçmək üçün \"Orijinal səs dilini zorlanı\" qapat</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">Haqqında</string>
<string name="revanced_settings_music_screen_1_ads_title">Reklamlar</string>
<string name="revanced_settings_music_screen_2_general_title">Ümumi</string>
<string name="revanced_settings_music_screen_3_player_title">Oynadıcı</string>
<string name="revanced_settings_music_screen_4_misc_title">Çoxvariantlı</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">Video reklamlarını gizlət</string>
<string name="revanced_music_hide_video_ads_summary_on">Video reklamları gizlidir</string>
<string name="revanced_music_hide_video_ads_summary_off">Video reklamları görünür</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">Kəsintisiz təkrarlamanı aktivləşdir</string>
<string name="revanced_music_play_permanent_repeat_summary_on">Kəsintisiz təkrarlama aktivdir</string>
<string name="revanced_music_play_permanent_repeat_summary_off">Kəsintisiz təkrarlama qapalıdır</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">Kateqoriya cizgisin gizlət</string>
<string name="revanced_music_hide_category_bar_summary_on">Kateqoriya cizgisi gizlidir</string>
<string name="revanced_music_hide_category_bar_summary_off">Kateqoriya cizgisi görünür</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title"> \'Musiqi Premiumu Əldə et\' etiketini gizlət</string>
<string name="revanced_music_hide_get_premium_label_summary_on">Etiket gizlidir</string>
<string name="revanced_music_hide_get_premium_label_summary_off">Etiket görünür</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">Təkmilləşdirmə düyməsini gizlət</string>
<string name="revanced_music_hide_upgrade_button_summary_on">Düymə gizlidir</string>
<string name="revanced_music_hide_upgrade_button_summary_off">Düymə görünür</string>
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ Second \"item\" text"</string>
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">Налады GmsCore</string>
<string name="microg_settings_summary">Налады для GmsCore</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="gms_core_toast_not_installed_message">MicroG GmsCore не ўсталяваны. Усталюйце яго.</string>
<string name="gms_core_dialog_title">Патрабуецца дзеянне</string>
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
Націсніце кнопку \"Працягнуць\" і дазвольце змяніць аптымізацыю."</string>
<string name="gms_core_dialog_continue_text">Працягнуць</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Подделывать потоки видео</string>
<string name="revanced_spoof_video_streams_screen_summary">Имитируйте потоки видео клиентов, чтобы предотвратить проблемы с воспроизведением</string>
<string name="revanced_spoof_video_streams_screen_title">Падмена відэапатокаў</string>
<string name="revanced_spoof_video_streams_screen_summary">Падмена відэапатокаў кліента для прадухілення праблем з прайграваннем</string>
<string name="revanced_spoof_video_streams_title">Подделывать потоки видео</string>
<string name="revanced_spoof_video_streams_summary_on">"Відэаструмені падроблены
Калі вы карыстаецеся YouTube Premium, гэтая налада можа не спатрэбіцца"</string>
<string name="revanced_spoof_video_streams_summary_off">"Відэапатокі не падменены
Прайграванне можа не працаваць"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Адключэнне гэтай налады можа выклікаць праблемы з прайграваннем.</string>
<string name="revanced_spoof_video_streams_client_type_title">Клиент по умолчанию</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Адладка</string>
<string name="revanced_debug_screen_summary">Уключыць або выключыць параметры адладкі</string>
<string name="revanced_debug_title">Запіс адладкі</string>
<string name="revanced_debug_summary_on">Журналы адладкі ўключаны</string>
<string name="revanced_debug_summary_off">Журналы адладкі адключаны</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Экспартаваць адладачныя лагі</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Капіруе адладачныя лагі ReVanced у буфер абмену</string>
<string name="revanced_debug_logs_disabled">Адладачнае лагаванне адключана</string>
<string name="revanced_debug_logs_none_found">Лагі не знойдзены</string>
<string name="revanced_debug_logs_copied_to_clipboard">Лагі скапіяваны</string>
<string name="revanced_debug_logs_failed_to_export">Не ўдалося экспартаваць журналы: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Ачысціць адладачныя лагі</string>
<string name="revanced_debug_logs_clear_buffer_summary">Ачышчае ўсе захаваныя адладачныя лагі ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Лагі ачышчаны</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Фоновый плейлист Shorts включен</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Адладка</string>
<string name="revanced_debug_screen_summary">Уключыць або выключыць параметры адладкі</string>
<string name="revanced_debug_title">Запіс адладкі</string>
<string name="revanced_debug_summary_on">Журналы адладкі ўключаны</string>
<string name="revanced_debug_summary_off">Журналы адладкі адключаны</string>
<string name="revanced_debug_protobuffer_title">Буфер пратаколу часопіса</string>
<string name="revanced_debug_protobuffer_summary_on">Журналы адладкі ўключаюць пратабуфер</string>
<string name="revanced_debug_protobuffer_summary_off">Журналы адладкі не ўключаюць пратабуфер</string>
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
<string name="revanced_debug_toast_on_error_user_dialog_message">"Адключэнне паведамленняў пра памылкі схавае ўсе апавяшчэнні ReVanced пра памылкі.
Вы не будзеце атрымліваць апавяшчэнні пра нечаканыя падзеі."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Экспартаваць адладачныя лагі</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Капіруе адладачныя лагі ReVanced у буфер абмену</string>
<string name="revanced_debug_logs_disabled">Адладачнае лагаванне адключана</string>
<string name="revanced_debug_logs_none_found">Лагі не знойдзены</string>
<string name="revanced_debug_logs_copied_to_clipboard">Лагі скапіяваны</string>
<string name="revanced_debug_logs_failed_to_export">Не ўдалося экспартаваць журналы: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Ачысціць адладачныя лагі</string>
<string name="revanced_debug_logs_clear_buffer_summary">Ачышчае ўсе захаваныя адладачныя лагі ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Лагі ачышчаны</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">Схаваць карты альбома</string>
@@ -602,6 +621,10 @@ Second \"item\" text"</string>
<string name="revanced_hide_clip_button_title">Схаваць кліп</string>
<string name="revanced_hide_clip_button_summary_on">Кнопка кліпа схавана</string>
<string name="revanced_hide_clip_button_summary_off">Паказана кнопка кліпа</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">Схаваць Краму</string>
<string name="revanced_hide_shop_button_summary_on">Кнопка \"Крама\" схавана</string>
<string name="revanced_hide_shop_button_summary_off">Кнопка \"Крама\" паказана</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">Схаваць \"Захаваць\"</string>
<string name="revanced_hide_save_button_summary_on">Кнопка \"Захаваць\" схавана</string>
@@ -702,7 +725,7 @@ Second \"item\" text"</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Меню аўдыядарожкі схавана
Каб паказаць меню аўдыядарожкі, змяніце \"Падробка відэаструменяў\" на iOS TV"</string>
Каб паказаць меню аўдыядарожкі, змяніце \"Падмена відэапатокаў\" на iPadOS"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">Схаваць гадзіннік у VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Меню прагляду ў VR схавана</string>
@@ -1416,10 +1439,6 @@ Second \"item\" text"</string>
Уключэнне гэтага можа разблакаваць больш высокія якасці відэа"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">Уключэнне гэтага можа прывесці да прыпынкаў прайгравання відэа, пагаршэння тэрміну службы батарэі і невядомых пабочных эфектаў.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">Налады GmsCore</string>
<string name="microg_settings_summary">Налады для GmsCore</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">Тактыльная зваротная сувязь</string>
<string name="revanced_disable_haptic_feedback_summary">Змяніць тактыльную зваротную сувязь</string>
@@ -1459,7 +1478,7 @@ Second \"item\" text"</string>
<string name="revanced_force_original_audio_summary_on">Выкарыстоўваць арыгінальную мову аўдыя</string>
<string name="revanced_force_original_audio_summary_off">Выкарыстанне аўдыё па змаўчанні</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">Каб выкарыстоўваць гэту функцыю, змяніце параметр \"Падрабляць відэаструмені\" на iOS TV</string>
<string name="revanced_force_original_audio_not_available">Каб выкарыстаць гэтую функцыю, змяніце \'Падмена відэаструменяў\' на любога кліента, акрамя Android Studio</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1533,35 +1552,54 @@ Second \"item\" text"</string>
<string name="revanced_slide_to_seek_summary_off">Слайд для пошуку не ўключаны</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Подделывать потоки видео</string>
<string name="revanced_spoof_video_streams_screen_summary">Имитируйте потоки видео клиентов, чтобы предотвратить проблемы с воспроизведением</string>
<string name="revanced_spoof_video_streams_title">Подделывать потоки видео</string>
<string name="revanced_spoof_video_streams_summary_on">Потоки видео подделаны</string>
<string name="revanced_spoof_video_streams_summary_off">"Відэаструм не падроблены
Прайграванне відэа можа не працаваць"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Адключэнне гэтай налады можа выклікаць праблемы з прайграваннем відэа.</string>
<string name="revanced_spoof_video_streams_client_type_title">Клиент по умолчанию</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">Вымусіць iOS AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Відэакaдэк зафіксаваны ў AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Відэакaдэк вызначаецца аўтаматычна</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Уключэнне гэтага можа палепшыць час аўтаномнай працы і выправіць заіканне прайгравання.
AVC мае максімальнае дазвол 1080p, аўдыёкадэк Opus недаступны, а прайграванне відэа будзе выкарыстоўваць больш інтэрнэт-даных, чым VP9 або AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">Пабочныя эфекты падробкі iOS</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Фільмы або платныя відэа могуць не прайгравацца
• Стабільная гучнасць недаступная
• Відэа заканчваюцца на 1 секунду раней"</string>
<string name="revanced_spoof_video_streams_about_title">Пабочныя эфекты падробкі</string>
<string name="revanced_spoof_video_streams_about_android_title">Побічныя эфекты падробкі Android</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Меню гукавой дарожкі адсутнічае
• Стабільны гук недаступны
• Прымусовае арыгінальнае аўдыё недаступна"</string>
• Стабільная гучнасць недаступна"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• Відэа можа спыніцца на 1:00, ці можа быць недаступным у некаторых рэгіёнах</string>
<string name="revanced_spoof_video_streams_about_experimental">• Эксперыментальны кліент і можа спыніць працу ў любы час</string>
<string name="revanced_spoof_video_streams_about_no_av1">• Няма відэакідавання AV1</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Дзіцячыя відэа могуць не прайгравацца ў стане выхаду з акаўнта або ў рэжыме інкогніта</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Паказаць у статыстыцы для спецыялістаў</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Тып кліента адлюстроўваецца ў статыстыцы для спецыялістаў</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Кліент схаваны ў статыстыцы для спецыялістаў</string>
<string name="revanced_spoof_video_streams_language_title">Мова гукавой дарожкі па змаўчанні для VR</string>
<string name="revanced_spoof_video_streams_language_title">Мова аўдыяпатоку</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Каб выбраць пэўную мову аўдыё, адключыце \'Прымусовая арыгінальная мова аўдыё\'</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">Пра</string>
<string name="revanced_settings_music_screen_1_ads_title">Рэклама</string>
<string name="revanced_settings_music_screen_2_general_title">Агульныя</string>
<string name="revanced_settings_music_screen_3_player_title">Плэер</string>
<string name="revanced_settings_music_screen_4_misc_title">Рознае</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">Схаваць відэарэкламу</string>
<string name="revanced_music_hide_video_ads_summary_on">Відэарэклама схаваная</string>
<string name="revanced_music_hide_video_ads_summary_off">Відэарэклама паказаная</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">Уключыць пастаянны паўтор</string>
<string name="revanced_music_play_permanent_repeat_summary_on">Пастаянны паўтор уключаны</string>
<string name="revanced_music_play_permanent_repeat_summary_off">Пастаянны паўтор адключаны</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">Схаваць панэль катэгорый</string>
<string name="revanced_music_hide_category_bar_summary_on">Панэль катэгорый схаваная</string>
<string name="revanced_music_hide_category_bar_summary_off">Панэль катэгорый паказаная</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">Схаваць надпіс \"Атрымаць Music Premium\"</string>
<string name="revanced_music_hide_get_premium_label_summary_on">Надпіс схаваны</string>
<string name="revanced_music_hide_get_premium_label_summary_off">Надпіс паказаны</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">Схаваць кнопку абнаўлення</string>
<string name="revanced_music_hide_upgrade_button_summary_on">Кнопка схаваная</string>
<string name="revanced_music_hide_upgrade_button_summary_off">Кнопка паказаная</string>
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ Second \"item\" text"</string>
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Настройки</string>
<string name="microg_settings_summary">Настройки на GmsCore</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="gms_core_toast_not_installed_message">GmsCore не е инсталиран. Инсталирайте го.</string>
<string name="gms_core_dialog_title">Нужно е действие</string>
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
Докоснете бутона за продължаване и разрешете промени в оптимизацията."</string>
<string name="gms_core_dialog_continue_text">Продължи</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Подправяне на видео потоци</string>
<string name="revanced_spoof_video_streams_screen_summary">Подправете клиентските видео потоци, за да предотвратите проблеми с възпроизвеждането</string>
<string name="revanced_spoof_video_streams_screen_title">Имитиране на видео потоци</string>
<string name="revanced_spoof_video_streams_screen_summary">Имитирайте видео потоците на клиента, за да предотвратите проблеми с възпроизвеждането</string>
<string name="revanced_spoof_video_streams_title">Подправяне на видео потоци</string>
<string name="revanced_spoof_video_streams_summary_on">"Видео потоците са подменени
Ако сте потребител на YouTube Premium, тази настройка може да не е необходима"</string>
<string name="revanced_spoof_video_streams_summary_off">"Видеопотоците не са подправени
Възпроизвеждането може да не работи"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Изключването на тази настройка може да причини проблеми с възпроизвеждането.</string>
<string name="revanced_spoof_video_streams_client_type_title">Клиент по подразбиране</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Отстраняване на грешки</string>
<string name="revanced_debug_screen_summary">Активиране или деактивиране на отстраняването на грешки</string>
<string name="revanced_debug_title">Дневник на отстраняването на грешки</string>
<string name="revanced_debug_summary_on">Дневникът за остраняване на грешки е активиран</string>
<string name="revanced_debug_summary_off">Дневникът за остраняване на грешки е деактивиран</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Експортиране на логове за отстраняване на грешки</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Копира логовете за отстраняване на грешки на ReVanced в клипборда</string>
<string name="revanced_debug_logs_disabled">Отстраняването на грешки е деактивирано</string>
<string name="revanced_debug_logs_none_found">Не са намерени логове</string>
<string name="revanced_debug_logs_copied_to_clipboard">Логовете са копирани</string>
<string name="revanced_debug_logs_failed_to_export">Неуспешно експортиране на логове: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Изчистване на логовете за отстраняване на грешки</string>
<string name="revanced_debug_logs_clear_buffer_summary">Изчиства всички съхранени логове за отстраняване на грешки на ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Логовете са изчистени</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Фоновото възпроизвеждане на Shorts е активирано</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Отстраняване на грешки</string>
<string name="revanced_debug_screen_summary">Активиране или деактивиране на отстраняването на грешки</string>
<string name="revanced_debug_title">Дневник на отстраняването на грешки</string>
<string name="revanced_debug_summary_on">Дневникът за остраняване на грешки е активиран</string>
<string name="revanced_debug_summary_off">Дневникът за остраняване на грешки е деактивиран</string>
<string name="revanced_debug_protobuffer_title">Буфер на протокола за дневника</string>
<string name="revanced_debug_protobuffer_summary_on">Файлове с дневници за грешки включват буфера</string>
<string name="revanced_debug_protobuffer_summary_off">Файлове с дневници за грешки не включват буфера</string>
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
<string name="revanced_debug_toast_on_error_user_dialog_message">"Изключването на изскачащи съобщения за грешки крие всички известия за грешки на ReVanced.
Няма да бъдете уведомени за неочаквани събития."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Експортиране на логове за отстраняване на грешки</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Копира логовете за отстраняване на грешки на ReVanced в клипборда</string>
<string name="revanced_debug_logs_disabled">Отстраняването на грешки е деактивирано</string>
<string name="revanced_debug_logs_none_found">Не са намерени логове</string>
<string name="revanced_debug_logs_copied_to_clipboard">Логовете са копирани</string>
<string name="revanced_debug_logs_failed_to_export">Неуспешно експортиране на логове: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Изчистване на логовете за отстраняване на грешки</string>
<string name="revanced_debug_logs_clear_buffer_summary">Изчиства всички съхранени логове за отстраняване на грешки на ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Логовете са изчистени</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">\"Карти на албумите\"</string>
@@ -602,6 +621,10 @@ Second \"item\" text"</string>
<string name="revanced_hide_clip_button_title">Бутон за създаване на клип</string>
<string name="revanced_hide_clip_button_summary_on">Бутона за клип е скрит</string>
<string name="revanced_hide_clip_button_summary_off">Бутона за клип се показва</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">Скрий магазин</string>
<string name="revanced_hide_shop_button_summary_on">Бутонът за магазин е скрит</string>
<string name="revanced_hide_shop_button_summary_off">Бутонът за магазин е показан</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">Скриване на Запазване</string>
<string name="revanced_hide_save_button_summary_on">Бутонът за запазване е скрит</string>
@@ -700,9 +723,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Менюто за избор на Аудио е скрито</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Менюто за избор на Аудио се показва</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Менюто за аудио тракове е скрито
<string name="revanced_hide_player_flyout_audio_track_not_available">"Менюто за аудиозапис е скрито
За да покажете менюто за аудио тракове, променете \"Подмяна на видео потоци\" на iOS TV"</string>
За да покажете менюто за аудиозапис, променете Подправяне на видео потоци на iPadOS"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">Гледайте във VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Менюто за гледане в VR е скрито</string>
@@ -1415,10 +1438,6 @@ Second \"item\" text"</string>
Активирането на това може да отключи по-високи видео качества"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">Разрешаването на това може да причини прекъсване на възпроизвеждането на видео, влошен живот на батерията и неизвестни странични ефекти.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Настройки</string>
<string name="microg_settings_summary">Настройки на GmsCore</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">Вибрационна обратна връзка</string>
<string name="revanced_disable_haptic_feedback_summary">Промяна на вибрационната обратна връзка</string>
@@ -1458,7 +1477,7 @@ Second \"item\" text"</string>
<string name="revanced_force_original_audio_summary_on">Използване на оригиналния език на аудиото</string>
<string name="revanced_force_original_audio_summary_off">Използване на аудио по подразбиране</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">За да използвате тази функция, сменете Фалшифициране на видео потоци на iOS TV</string>
<string name="revanced_force_original_audio_not_available">За да използвате тази функция, променете \'Фалшифициране на видео потоци\' на всеки клиент, освен Android Studio</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1532,35 +1551,54 @@ Second \"item\" text"</string>
<string name="revanced_slide_to_seek_summary_off">Слайд за превъртане е деактивиран</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Подправяне на видео потоци</string>
<string name="revanced_spoof_video_streams_screen_summary">Подправете клиентските видео потоци, за да предотвратите проблеми с възпроизвеждането</string>
<string name="revanced_spoof_video_streams_title">Подправяне на видео потоци</string>
<string name="revanced_spoof_video_streams_summary_on">Видео потоците са подправени</string>
<string name="revanced_spoof_video_streams_summary_off">"Потоците на видеоклипове не са фалшифицирани
Възпроизвеждането на видеоклипове може да не работи"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Деактивирането на тази настройка ще доведе до проблеми с възпроизвеждането на видео.</string>
<string name="revanced_spoof_video_streams_client_type_title">Клиент по подразбиране</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">Принудително използване на AVC (H.264) на iOS</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Видео кодекът е принудително зададен на AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Видео кодекът се определя автоматично</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Включването на това може да подобри живота на батерията и да поправи заекването при възпроизвеждане.
AVC има максимална резолюция от 1080p, Opus аудио кодек не е наличен и възпроизвеждането на видео ще използва повече интернет данни от VP9 или AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">Ефекти на измамата в iOS</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Филми или платени видеоклипове може да не се възпроизвеждат
• Стабилен звук не е наличен
• Видеоклиповете завършват 1 секунда по-рано"</string>
<string name="revanced_spoof_video_streams_about_title">Странични ефекти от подменянето</string>
<string name="revanced_spoof_video_streams_about_android_title">Strani4ni efekti na fal6ivoto predstavqne na Android</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Lipsva menju za audio pisti
Ne e nali4na stabilna glasnost
• Ne e nali4na forsirana originalna audio pista"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Липсва менюто за аудиозаписи
Стабилен звук не е наличен"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• Видеото може да спре на 1:00 или може да не е налично в някои региони</string>
<string name="revanced_spoof_video_streams_about_experimental">• Експериментален клиент и може да спре да работи по всяко време</string>
<string name="revanced_spoof_video_streams_about_no_av1">• Без AV1 видео кодек</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Детските видеоклипове може да не се възпроизвеждат, когато сте излезли от профила си или в режим \"инкогнито\"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Poka6i v Statistiki za nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Tipът na klienta se poka6va v Statistiki za nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klientът e skriт v Statistiki za nerds</string>
<string name="revanced_spoof_video_streams_language_title">Ezik po подразбиране za audio potok v VR</string>
<string name="revanced_spoof_video_streams_language_title">Език на аудио потока</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">За да изберете конкретен аудио език, изключете \'Принудително оригинален аудио език\'</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">Относно</string>
<string name="revanced_settings_music_screen_1_ads_title">Реклами</string>
<string name="revanced_settings_music_screen_2_general_title">Общи</string>
<string name="revanced_settings_music_screen_3_player_title">Плейър</string>
<string name="revanced_settings_music_screen_4_misc_title">Разни</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">Скриване на видеореклами</string>
<string name="revanced_music_hide_video_ads_summary_on">Видеорекламите са скрити</string>
<string name="revanced_music_hide_video_ads_summary_off">Видеорекламите са показани</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">Активиране на постоянно повтаряне</string>
<string name="revanced_music_play_permanent_repeat_summary_on">Постоянното повтаряне е активирано</string>
<string name="revanced_music_play_permanent_repeat_summary_off">Постоянното повтаряне е деактивирано</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">Скриване на лентата с категории</string>
<string name="revanced_music_hide_category_bar_summary_on">Лентата с категории е скрита</string>
<string name="revanced_music_hide_category_bar_summary_off">Лентата с категории е показана</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">Скриване на етикета „Вземете Music Premium“</string>
<string name="revanced_music_hide_get_premium_label_summary_on">Етикетът е скрит</string>
<string name="revanced_music_hide_get_premium_label_summary_off">Етикетът е показан</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">Скриване на бутона за надстройка</string>
<string name="revanced_music_hide_upgrade_button_summary_on">Бутонът е скрит</string>
<string name="revanced_music_hide_upgrade_button_summary_off">Бутонът е показан</string>
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ Second \"item\" text"</string>
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore সেটিং</string>
<string name="microg_settings_summary">GmsCore এর জন্য সেটিং</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="gms_core_toast_not_installed_message">MicroG GmsCore ইনস্টল করা হয়নি। ইনস্টল করুন।</string>
<string name="gms_core_dialog_title">পদক্ষেপ প্রয়োজন</string>
@@ -84,6 +86,37 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
চালিয়ে যান বোতামটি ট্যাপ করুন এবং অপ্টিমাইজেশন পরিবর্তনগুলি অনুমোদন করুন।"</string>
<string name="gms_core_dialog_continue_text">এগিয়ে যান</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_screen_summary">প্লেব্যাক সমস্যা প্রতিরোধ করতে ক্লায়েন্ট ভিডিও স্ট্রিম স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_screen_title">ভিডিও স্ট্রিম স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_screen_summary">প্লেব্যাক সংক্রান্ত সমস্যা রোধ করতে ক্লায়েন্টের ভিডিও স্ট্রিমগুলি স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_summary_on">"ভিডিও স্ট্রিম স্পুফ করা হয়েছে
আপনি যদি YouTube Premium ব্যবহারকারী হন, তাহলে এই সেটিংটির প্রয়োজন নাও হতে পারে"</string>
<string name="revanced_spoof_video_streams_summary_off">"ভিডিও স্ট্রিম স্পুফ করা হয়নি
প্লেব্যাক কাজ নাও করতে পারে"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">এই সেটিং বন্ধ করলে প্লেব্যাক সমস্যা হতে পারে।</string>
<string name="revanced_spoof_video_streams_client_type_title">ডিফল্ট ক্লায়েন্ট</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">ডিবাগিং</string>
<string name="revanced_debug_screen_summary">ডিবাগিং অপশন সক্রিয় বা নিষ্ক্রিয় করুন</string>
<string name="revanced_debug_title">ডিবাগ লগিং</string>
<string name="revanced_debug_summary_on">ডিবাগ লগ সক্রিয় হয়েছে</string>
<string name="revanced_debug_summary_off">ডিবাগ লগ নিষ্ক্রিয় হয়েছে</string>
<string name="revanced_debug_export_logs_to_clipboard_title">ডিবাগ লগগুলি রফতানি করুন</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">ক্লিপবোর্ডে ReVanced ডিবাগ লগগুলি অনুলিপি করে</string>
<string name="revanced_debug_logs_disabled">ডিবাগ লগিং নিষ্ক্রিয় করা হয়েছে</string>
<string name="revanced_debug_logs_none_found">কোনো লগ পাওয়া যায়নি</string>
<string name="revanced_debug_logs_copied_to_clipboard">লগ অনুলিপি করা হয়েছে</string>
<string name="revanced_debug_logs_failed_to_export">লগ এক্সপোর্ট করা যায়নি: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">ডিবাগ লগগুলি সাফ করুন</string>
<string name="revanced_debug_logs_clear_buffer_summary">সমস্ত সঞ্চিত ReVanced ডিবাগ লগ সাফ করে</string>
<string name="revanced_debug_logs_clear_toast">লগ সাফ করা হয়েছে</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts ব্যাকগ্রাউন্ড প্লে সক্ষম করা হয়েছে</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">ডিবাগিং</string>
<string name="revanced_debug_screen_summary">ডিবাগিং অপশন সক্রিয় বা নিষ্ক্রিয় করুন</string>
<string name="revanced_debug_title">ডিবাগ লগিং</string>
<string name="revanced_debug_summary_on">ডিবাগ লগ সক্রিয় হয়েছে</string>
<string name="revanced_debug_summary_off">ডিবাগ লগ নিষ্ক্রিয় হয়েছে</string>
<string name="revanced_debug_protobuffer_title">প্রটোকল বাফার লগ</string>
<string name="revanced_debug_protobuffer_summary_on">ডিবাগ লগ প্রটোকল বাফার সংযুক্ত করবে</string>
<string name="revanced_debug_protobuffer_summary_off">ডিবাগ লগ প্রটোকল বাফার সংযুক্ত করবে না</string>
@@ -128,15 +156,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_debug_toast_on_error_user_dialog_message">"ত্রুটি \"toast\" বন্ধ করে ReVanced ত্রুটি বিজ্ঞপ্তিগুলি লুকানো হয়।
আপনি কোনও অপ্রত্যাশিত ঘটনার বিষয়ে অবহিত হবেন না।"</string>
<string name="revanced_debug_export_logs_to_clipboard_title">ডিবাগ লগগুলি রফতানি করুন</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">ক্লিপবোর্ডে ReVanced ডিবাগ লগগুলি অনুলিপি করে</string>
<string name="revanced_debug_logs_disabled">ডিবাগ লগিং নিষ্ক্রিয় করা হয়েছে</string>
<string name="revanced_debug_logs_none_found">কোনো লগ পাওয়া যায়নি</string>
<string name="revanced_debug_logs_copied_to_clipboard">লগ অনুলিপি করা হয়েছে</string>
<string name="revanced_debug_logs_failed_to_export">লগ এক্সপোর্ট করা যায়নি: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">ডিবাগ লগগুলি সাফ করুন</string>
<string name="revanced_debug_logs_clear_buffer_summary">সমস্ত সঞ্চিত ReVanced ডিবাগ লগ সাফ করে</string>
<string name="revanced_debug_logs_clear_toast">লগ সাফ করা হয়েছে</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">অ্যালবাম কার্ড লুকান</string>
@@ -598,6 +617,10 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_clip_button_title">ক্লিপ লুকান</string>
<string name="revanced_hide_clip_button_summary_on">ক্লিপ বোতাম লুকিয়ে রয়েছে</string>
<string name="revanced_hide_clip_button_summary_off">ক্লিপ বোতাম প্রদর্শিত হয়েছে</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">শপ লুকান</string>
<string name="revanced_hide_shop_button_summary_on">শপ বাটন লুকানো আছে</string>
<string name="revanced_hide_shop_button_summary_off">শপ বাটন দেখানো আছে</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">সংরক্ষণ লুকান</string>
<string name="revanced_hide_save_button_summary_on">সংরক্ষণ বোতাম লুকানো আছে</string>
@@ -698,7 +721,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"অডিও ট্র্যাক মেনু লুকানো আছে
অডিও ট্র্যাক মেনু দেখাতে, 'স্পুফ ভিডিও স্ট্রিম' পরিবর্তনে iOS TV করুন"</string>
অডিও ট্র্যাক মেনু দেখানোর জন্য, 'ভিডিও স্ট্রিম স্পুফ করুন' কে iPadOS এ পরিবর্তন করুন"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">ভিআর-এ ঘড়ি লুকান</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">ভিআর মেনুতে দেখুন লুকানো আছে</string>
@@ -1411,10 +1434,6 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
এটি সক্রিয় করা উচ্চ ভিডিও গুণমানগুলি আনলক করতে পারে"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">এটি সক্রিয় করার ফলে আপনি ভিডিও চলার ক্ষেত্রে আটকে চলা, খারাপ ব্যাটারি লাইফ এবং অজানা পার্শ্ব-প্রতিক্রিয়ার সম্মুখিন হতে পারেন।</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore সেটিং</string>
<string name="microg_settings_summary">GmsCore এর জন্য সেটিং</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">কম্পন প্রতিক্রিয়া</string>
<string name="revanced_disable_haptic_feedback_summary">কম্পন প্রতিক্রিয়া পরিবর্তন করুন</string>
@@ -1454,7 +1473,7 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
<string name="revanced_force_original_audio_summary_on">মূল অডিও ভাষা ব্যবহার করা হচ্ছে</string>
<string name="revanced_force_original_audio_summary_off">ডিফল্ট অডিও ব্যবহার করছে</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">এই বৈশিষ্ট্যটি ব্যবহার করতে, \'স্পুফ ভিডিও স্ট্রীম\' কে iOS TV-তে পরিবর্তন করুন</string>
<string name="revanced_force_original_audio_not_available">এই বৈশিষ্ট্যটি ব্যবহার করতে, \'ভিডিও স্ট্রিম স্পুফ করুন\' অ্যান্ড্রয়েড স্টুডিও ছাড়া অন্য কোনো ক্লায়েন্টে পরিবর্তন করুন</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1528,35 +1547,54 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
<string name="revanced_slide_to_seek_summary_off">ভিডিওর নির্দিষ্ট অংশে যেতে টানুন সক্রিয় করা হয়নি</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_screen_summary">প্লেব্যাক সমস্যা প্রতিরোধ করতে ক্লায়েন্ট ভিডিও স্ট্রিম স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
<string name="revanced_spoof_video_streams_summary_on">ভিডিও স্ট্রিম স্পুফ করা হয়েছে</string>
<string name="revanced_spoof_video_streams_summary_off">"ভিডিও স্ট্রিম ভুয়া নয়
ভিডিও প্লেব্যাক কাজ নাও করতে পারে"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">এই সেটিংটি বন্ধ করার ফলে ভিডিও প্লেব্যাক ত্রুটি হতে পারে।</string>
<string name="revanced_spoof_video_streams_client_type_title">ডিফল্ট ক্লায়েন্ট</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) বাধ্যতামূলক করুন</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ভিডিও কোডেক AVC (H.264) এ বাধ্যতামূলক করা হয়েছে</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ভিডিও কোডেক স্বয়ংক্রিয়ভাবে নির্ধারিত হয়</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"এটি সক্ষম করলে ব্যাটারি লাইফ উন্নত হতে পারে এবং প্লেব্যাক স্টাটারিং সমস্যা সমাধান হতে পারে।
AVC-এর সর্বোচ্চ রেজোলিউশন হল 1080p, Opus অডিও কোডেক পাওয়া যায় না এবং VP9 বা AV1-এর তুলনায় ভিডিও প্লেব্যাকে বেশি ইন্টারনেট ডেটা ব্যবহার করা হবে。"</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">আইওএস স্পুফিংয়ের পার্শ্ব প্রতিক্রিয়া</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• মুভি বা অর্থ প্রদানের ভিডিও চালু নাও হতে পারে
• স্থির ভলিউম পাওয়া যায় না
• ভিডিওগুলি 1 সেকেন্ড আগে শেষ হয়ে যায়"</string>
<string name="revanced_spoof_video_streams_about_title">স্পুফিংয়ের পার্শ্বপ্রতিক্রিয়া</string>
<string name="revanced_spoof_video_streams_about_android_title">Android স্পুফিংয়ের পার্শ্বপ্রতিক্রিয়া</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• অডিও ট্র্যাক মেনু নেই
• স্থি ভলিউম পাওয়া যায় না
• মূল অডিও জোর করে চালু করা যায় না"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• অডিও ট্র্যাক মেনু অনুপস্থিত
• স্থিতিশীল ভলিউম উপলব্ধ নেই"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• ভিডিও ১: মিনিটে বন্ধ হতে পারে, অথবা কিছু অঞ্চলে উপলব্ধ নাও হতে পারে</string>
<string name="revanced_spoof_video_streams_about_experimental">• পরীক্ষামূলক ক্লায়েন্ট এবং যেকোনো সময় কাজ করা বন্ধ করতে পারে</string>
<string name="revanced_spoof_video_streams_about_no_av1">• কোনো AV1 ভিডিও কোডেক নেই</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• লগআউট করা হলে বা ছদ্মবেশী মোডে বাচ্চাদের ভিডিও চলতে নাও পারে</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">স্ট্যাটস ফর নার্ডসে দেখান</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">স্ট্যাটস ফর নার্ডসে ক্লায়েন্ট প্রকার দেখানো হবে</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">স্ট্যাটস ফর নার্ডসে ক্লায়েন্ট লুকানো হবে</string>
<string name="revanced_spoof_video_streams_language_title">VR ডিফল্ট অডিও স্ট্রিম ভাষা</string>
<string name="revanced_spoof_video_streams_language_title">অডিও স্ট্রিম ভাষা</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">একটি নির্দিষ্ট অডিও ভাষা নির্বাচন করতে, \'মূল অডিও ভাষা জোর করে চালু রাখুন\' বন্ধ করুন</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">সম্পর্কে</string>
<string name="revanced_settings_music_screen_1_ads_title">বিজ্ঞাপন</string>
<string name="revanced_settings_music_screen_2_general_title">সাধারণ</string>
<string name="revanced_settings_music_screen_3_player_title">প্লেয়ার</string>
<string name="revanced_settings_music_screen_4_misc_title">বিবিধ</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">ভিডিও বিজ্ঞাপন লুকান</string>
<string name="revanced_music_hide_video_ads_summary_on">ভিডিও বিজ্ঞাপন লুকানো আছে</string>
<string name="revanced_music_hide_video_ads_summary_off">ভিডিও বিজ্ঞাপন দেখানো আছে</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">স্থায়ী পুনরাবৃত্তি সক্ষম করুন</string>
<string name="revanced_music_play_permanent_repeat_summary_on">স্থায়ী পুনরাবৃত্তি সক্ষম করা হয়েছে</string>
<string name="revanced_music_play_permanent_repeat_summary_off">স্থায়ী পুনরাবৃত্তি অক্ষম করা হয়েছে</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">ক্যাটাগরি বার লুকান</string>
<string name="revanced_music_hide_category_bar_summary_on">ক্যাটাগরি বার লুকানো আছে</string>
<string name="revanced_music_hide_category_bar_summary_off">ক্যাটাগরি বার দেখানো আছে</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">\'গেট মিউজিক প্রিমিয়াম\' লেবেল লুকান</string>
<string name="revanced_music_hide_get_premium_label_summary_on">লেবেল লুকানো আছে</string>
<string name="revanced_music_hide_get_premium_label_summary_off">লেবেল দেখানো আছে</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">আপগ্রেড বাটন লুকান</string>
<string name="revanced_music_hide_upgrade_button_summary_on">বাটন লুকানো আছে</string>
<string name="revanced_music_hide_upgrade_button_summary_off">বাটন দেখানো আছে</string>
</patch>
</app>
<app id="twitch">

View File

@@ -30,6 +30,10 @@ Second \"item\" text"</string>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -96,6 +100,7 @@ Second \"item\" text"</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>
<patch id="layout.buttons.navigation.navigationButtonsPatch">
@@ -207,8 +212,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
</patch>
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
@@ -240,6 +243,21 @@ Second \"item\" text"</string>
<patch id="interaction.seekbar.enableSlideToSeekPatch">
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
</patch>
<patch id="ad.video.hideVideoAdsPatch">
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
</patch>
<patch id="layout.compactheader.hideCategoryBar">
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
</patch>
</app>
<app id="twitch">

View File

@@ -30,6 +30,10 @@ Second \"item\" text"</string>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -96,6 +100,7 @@ Second \"item\" text"</string>
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
This button only shows if the user ip is from specific region such as the USA or EU. -->
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
</patch>
<patch id="layout.buttons.navigation.navigationButtonsPatch">
@@ -207,8 +212,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
</patch>
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
@@ -240,6 +243,21 @@ Second \"item\" text"</string>
<patch id="interaction.seekbar.enableSlideToSeekPatch">
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
</patch>
<patch id="ad.video.hideVideoAdsPatch">
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
</patch>
<patch id="layout.compactheader.hideCategoryBar">
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ Nové jazyky přeložíte na translate.revanced.app"</string>
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">Nastavení GmsCore</string>
<string name="microg_settings_summary">Nastavení pro GmsCore</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="gms_core_toast_not_installed_message">MicroG GmsCore není nainstalován. Nainstalujte jej.</string>
<string name="gms_core_dialog_title">Požadovaná akce</string>
@@ -84,6 +86,37 @@ Zakázání optimalizace baterie pro MicroG nebude mít negativní vliv na spot
Klepněte na tlačítko Pokračovat a povolte změny optimalizace."</string>
<string name="gms_core_dialog_continue_text">Pokračovat</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Napodobovat video streamy</string>
<string name="revanced_spoof_video_streams_screen_summary">Napodobovat klientské video streamy, aby se zabránilo problémům s přehráváním</string>
<string name="revanced_spoof_video_streams_screen_title">Falšovat video streamy</string>
<string name="revanced_spoof_video_streams_screen_summary">Falšovat video streamy klienta, aby se předešlo problémům s přehráváním.</string>
<string name="revanced_spoof_video_streams_title">Napodobovat video streamy</string>
<string name="revanced_spoof_video_streams_summary_on">"Video streamy jsou maskovány
Pokud jste uživatelem YouTube Premium, toto nastavení nemusí být vyžadováno."</string>
<string name="revanced_spoof_video_streams_summary_off">"Video streamy nejsou falšované
Přehrávání nemusí fungovat"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Vypnutí tohoto nastavení může způsobit problémy s přehráváním.</string>
<string name="revanced_spoof_video_streams_client_type_title">Výchozí klient</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Debugování</string>
<string name="revanced_debug_screen_summary">Povolit nebo zakázat debugovací možnosti</string>
<string name="revanced_debug_title">Debugovací záznamy</string>
<string name="revanced_debug_summary_on">Debugovací záznamy jsou zapnuty</string>
<string name="revanced_debug_summary_off">Debugovací záznamy jsou vypnuty</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Exportovat ladicí protokoly</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Zkopíruje ladicí protokoly ReVanced do schránky</string>
<string name="revanced_debug_logs_disabled">Ladění je vypnuto</string>
<string name="revanced_debug_logs_none_found">Nebyly nalezeny žádné protokoly</string>
<string name="revanced_debug_logs_copied_to_clipboard">Protokoly zkopírovány</string>
<string name="revanced_debug_logs_failed_to_export">Nepodařilo se exportovat protokoly: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Vymazat ladicí protokoly</string>
<string name="revanced_debug_logs_clear_buffer_summary">Vymaže všechny uložené ladicí protokoly ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Protokoly vymazány</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ Klepněte na tlačítko Pokračovat a povolte změny optimalizace."</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Přehrávání Shorts v pozadí je povoleno</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Debugování</string>
<string name="revanced_debug_screen_summary">Povolit nebo zakázat debugovací možnosti</string>
<string name="revanced_debug_title">Debugovací záznamy</string>
<string name="revanced_debug_summary_on">Debugovací záznamy jsou zapnuty</string>
<string name="revanced_debug_summary_off">Debugovací záznamy jsou vypnuty</string>
<string name="revanced_debug_protobuffer_title">Záznam bufferu protokolu</string>
<string name="revanced_debug_protobuffer_summary_on">Debugovací záznamy obsahují proto buffer</string>
<string name="revanced_debug_protobuffer_summary_off">Debugovací záznamy neobsahují proto buffer</string>
@@ -132,15 +160,6 @@ Povolením této možnosti se však budou zaznamenávat i některá uživatelsk
<string name="revanced_debug_toast_on_error_user_dialog_message">"Vypnutí chybových toastů skryje všechna chybová oznámení ReVanced.
Nebudete informováni o žádné neočekávané události."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Exportovat ladicí protokoly</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Zkopíruje ladicí protokoly ReVanced do schránky</string>
<string name="revanced_debug_logs_disabled">Ladění je vypnuto</string>
<string name="revanced_debug_logs_none_found">Nebyly nalezeny žádné protokoly</string>
<string name="revanced_debug_logs_copied_to_clipboard">Protokoly zkopírovány</string>
<string name="revanced_debug_logs_failed_to_export">Nepodařilo se exportovat protokoly: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Vymazat ladicí protokoly</string>
<string name="revanced_debug_logs_clear_buffer_summary">Vymaže všechny uložené ladicí protokoly ReVanced</string>
<string name="revanced_debug_logs_clear_toast">Protokoly vymazány</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">Skrýt karty alb</string>
@@ -602,6 +621,10 @@ Hlasitost se upravuje svislým přejetím po pravé straně obrazovky"</string>
<string name="revanced_hide_clip_button_title">Skrýt Klip</string>
<string name="revanced_hide_clip_button_summary_on">Tlačítko Klip je skryto</string>
<string name="revanced_hide_clip_button_summary_off">Tlačítko Klip je zobrazeno</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">Skrýt Obchod</string>
<string name="revanced_hide_shop_button_summary_on">Tlačítko Obchod je skryté</string>
<string name="revanced_hide_shop_button_summary_off">Tlačítko Obchod je zobrazené</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">Skrýt Uložit</string>
<string name="revanced_hide_save_button_summary_on">Tlačítko Uložit je skryté</string>
@@ -700,9 +723,9 @@ Pokud změna tohoto nastavení nemá žádný účinek, zkuste přepnout do rež
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menu Zvuková stopa je skryto</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Menu Zvuková stopa je zobrazeno</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Nabídka zvukové stopy je skrytá.
<string name="revanced_hide_player_flyout_audio_track_not_available">"Nabídka zvukové stopy je skryta
Chcete-li zobrazit nabídku zvukové stopy, změňte možnost „Zfalšovat streamy videa na iOS TV"</string>
Chcete-li zobrazit nabídku zvukové stopy, změňte 'Zfalšovat streamy videa' na iPadOS"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">Skrýt Sledovat ve VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu Sledovat ve VR je skryto</string>
@@ -1415,10 +1438,6 @@ Mohou být odemčeny vyšší kvality videa, ale může dojít k zadrhávání p
Povolením této funkce lze odemknout vyšší kvality videa"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">Povolení může způsobit zasekávání přehrávání, zhoršenou výdrž baterie a neznámé vedlejší účinky.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">Nastavení GmsCore</string>
<string name="microg_settings_summary">Nastavení pro GmsCore</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">Haptická odezva</string>
<string name="revanced_disable_haptic_feedback_summary">Změnit haptickou odezvu</string>
@@ -1458,7 +1477,7 @@ Povolením této funkce lze odemknout vyšší kvality videa"</string>
<string name="revanced_force_original_audio_summary_on">Použít původní jazyk zvuku</string>
<string name="revanced_force_original_audio_summary_off">Používání výchozího zvuku</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">Chcete-li používat tuto funkci, změňte možnost „Zfalšovat datové proudy videa“ na iOS TV</string>
<string name="revanced_force_original_audio_not_available">Chcete-li použít tuto funkci, změňte \'Zfalšovat video streamy\' na libovolného klienta kromě Android Studia</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1532,35 +1551,54 @@ Povolením této funkce lze odemknout vyšší kvality videa"</string>
<string name="revanced_slide_to_seek_summary_off">Posun pro hledání není povolen</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Napodobovat video streamy</string>
<string name="revanced_spoof_video_streams_screen_summary">Napodobovat klientské video streamy, aby se zabránilo problémům s přehráváním</string>
<string name="revanced_spoof_video_streams_title">Napodobovat video streamy</string>
<string name="revanced_spoof_video_streams_summary_on">Video streamy jsou napodobeny</string>
<string name="revanced_spoof_video_streams_summary_off">"Video streamy nejsou zfalšovány
Přehrávání videa nemusí fungovat"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Vypnutí tohoto nastavení může způsobit problémy s přehráváním videa.</string>
<string name="revanced_spoof_video_streams_client_type_title">Výchozí klient</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">Vynucení kodeku iOS AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Kodek videa je vynucen na AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Kodek videa je určen automaticky</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Povolení této funkce může zlepšit výdrž baterie a opravit sekání videa.
AVC má maximální rozlišení 1080p, zvukový kodek Opus není dostupný a přehrávání videa bude používat více dat než VP9 nebo AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS spoofing vedlejší účinky</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Filmy nebo placená videa se nemusí přehrávat
• Stabilní hlasitost není k dispozici
• Videa končí o 1 sekundu dříve"</string>
<string name="revanced_spoof_video_streams_about_title">Vedlejší účinky maskování</string>
<string name="revanced_spoof_video_streams_about_android_title">Vedlejší účinky spoofingu Androidu</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Chybí nabídka zvukových stop
Není k dispozici stabilní hlasitost
• Není k dispozici možnost vynucení originálního zvuku"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Chybí nabídka zvukové stopy
Stabilní hlasitost není k dispozici"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• Video se může zastavit v 1:00 nebo nemusí být dostupné v některých oblastech</string>
<string name="revanced_spoof_video_streams_about_experimental">• Experimentální klient a může kdykoli přestat fungovat</string>
<string name="revanced_spoof_video_streams_about_no_av1">• Žádný video kodek AV1</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Dětská videa se nemusí přehrávat, když jste odhlášení nebo v anonymním režimu</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Zobrazit ve statistikách pro nadšence</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Typ klienta se zobrazuje ve statistikách pro nadšence</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klient je skrytý ve statistikách pro nadšence</string>
<string name="revanced_spoof_video_streams_language_title">Výchozí jazyk zvukového streamu ve VR</string>
<string name="revanced_spoof_video_streams_language_title">Jazyk zvukového streamu</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Chcete-li vybrat konkrétní zvukový jazyk, vypněte „Vynutit původní zvukový jazyk“</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">O aplikaci</string>
<string name="revanced_settings_music_screen_1_ads_title">Reklamy</string>
<string name="revanced_settings_music_screen_2_general_title">Obecné</string>
<string name="revanced_settings_music_screen_3_player_title">Přehrávač</string>
<string name="revanced_settings_music_screen_4_misc_title">Různé</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">Skrýt videoreklamy</string>
<string name="revanced_music_hide_video_ads_summary_on">Videoreklamy jsou skryty</string>
<string name="revanced_music_hide_video_ads_summary_off">Videoreklamy jsou zobrazeny</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">Povolit trvalé opakování</string>
<string name="revanced_music_play_permanent_repeat_summary_on">Trvalé opakování je povoleno</string>
<string name="revanced_music_play_permanent_repeat_summary_off">Trvalé opakování je zakázáno</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">Skrýt panel kategorií</string>
<string name="revanced_music_hide_category_bar_summary_on">Panel kategorií je skryt</string>
<string name="revanced_music_hide_category_bar_summary_off">Panel kategorií je zobrazen</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">Skrýt štítek \"Získat Music Premium\"</string>
<string name="revanced_music_hide_get_premium_label_summary_on">Štítek je skryt</string>
<string name="revanced_music_hide_get_premium_label_summary_off">Štítek je zobrazen</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">Skrýt tlačítko pro upgrade</string>
<string name="revanced_music_hide_upgrade_button_summary_on">Tlačítko je skryto</string>
<string name="revanced_music_hide_upgrade_button_summary_off">Tlačítko je zobrazeno</string>
</patch>
</app>
<app id="twitch">

View File

@@ -68,6 +68,8 @@ For at oversætte til nye sprog skal du besøge translate.revanced.app"</string>
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Indstillinger</string>
<string name="microg_settings_summary">Indstillinger for GmsCore</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="gms_core_toast_not_installed_message">MicroG GmsCore er ikke installeret. Installer det.</string>
<string name="gms_core_dialog_title">Handling påkrævet</string>
@@ -84,6 +86,37 @@ Deaktivering af batterioptimeringer for MicroG vil ikke påvirke batteriforbruge
Tap på knappen Fortsæt, og tillad optimeringsændringer."</string>
<string name="gms_core_dialog_continue_text">Fortsæt</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Spoof videostreams</string>
<string name="revanced_spoof_video_streams_screen_summary">Spoof klienten video streams for at forhindre afspilning problemer</string>
<string name="revanced_spoof_video_streams_screen_title">Simuler videostreams</string>
<string name="revanced_spoof_video_streams_screen_summary">Simuler klientens videostreams for at forhindre afspilningsproblemer</string>
<string name="revanced_spoof_video_streams_title">Spoof videostreams</string>
<string name="revanced_spoof_video_streams_summary_on">"Videostreams er spoofede
Hvis du er en YouTube Premium-bruger, er denne indstilling muligvis ikke påkrævet"</string>
<string name="revanced_spoof_video_streams_summary_off">"Videostreams simuleres ikke
Afspilning fungerer muligvis ikke"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Deaktivering af denne indstilling kan forårsage afspilningsproblemer.</string>
<string name="revanced_spoof_video_streams_client_type_title">Standard klient</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Fejlfinding</string>
<string name="revanced_debug_screen_summary">Aktivér eller deaktiver fejlfindingsindstillinger</string>
<string name="revanced_debug_title">Fejlfindingslogning</string>
<string name="revanced_debug_summary_on">Fejlfindingslogge er aktiveret</string>
<string name="revanced_debug_summary_off">Fejlfindingslogge er deaktiveret</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Eksportér fejlsøgningslogfiler</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopierer ReVanced-fejlsøgningslogfiler til udklipsholderen</string>
<string name="revanced_debug_logs_disabled">Fejlsøgningslogning er deaktiveret</string>
<string name="revanced_debug_logs_none_found">Ingen logfiler fundet</string>
<string name="revanced_debug_logs_copied_to_clipboard">Logfiler kopieret</string>
<string name="revanced_debug_logs_failed_to_export">Kunne ikke eksportere logfiler: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Ryd fejlsøgningslogfiler</string>
<string name="revanced_debug_logs_clear_buffer_summary">Rydder alle gemte ReVanced-fejlsøgningslogfiler</string>
<string name="revanced_debug_logs_clear_toast">Logfiler ryddet</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -110,11 +143,6 @@ Tap på knappen Fortsæt, og tillad optimeringsændringer."</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Baggrundsafspilning af Shorts er aktiveret</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Fejlfinding</string>
<string name="revanced_debug_screen_summary">Aktivér eller deaktiver fejlfindingsindstillinger</string>
<string name="revanced_debug_title">Fejlfindingslogning</string>
<string name="revanced_debug_summary_on">Fejlfindingslogge er aktiveret</string>
<string name="revanced_debug_summary_off">Fejlfindingslogge er deaktiveret</string>
<string name="revanced_debug_protobuffer_title">Logprotokolbuffer</string>
<string name="revanced_debug_protobuffer_summary_on">Fejlfindingslogge inkluderer protobuffer</string>
<string name="revanced_debug_protobuffer_summary_off">Fejlfindingslogge inkluderer ikke protobuffer</string>
@@ -132,15 +160,6 @@ Aktivering af dette vil dog også logge nogle brugerdata, såsom din IP-adresse.
<string name="revanced_debug_toast_on_error_user_dialog_message">"Hvis du deaktiverer fejl-toasts, skjules alle ReVanced-fejlmeddelelser.
Du modtager ikke notifikationer om uventede hændelser."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Eksportér fejlsøgningslogfiler</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopierer ReVanced-fejlsøgningslogfiler til udklipsholderen</string>
<string name="revanced_debug_logs_disabled">Fejlsøgningslogning er deaktiveret</string>
<string name="revanced_debug_logs_none_found">Ingen logfiler fundet</string>
<string name="revanced_debug_logs_copied_to_clipboard">Logfiler kopieret</string>
<string name="revanced_debug_logs_failed_to_export">Kunne ikke eksportere logfiler: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Ryd fejlsøgningslogfiler</string>
<string name="revanced_debug_logs_clear_buffer_summary">Rydder alle gemte ReVanced-fejlsøgningslogfiler</string>
<string name="revanced_debug_logs_clear_toast">Logfiler ryddet</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">Skjul albumkort</string>
@@ -602,6 +621,10 @@ Juster lydstyrken ved at swipe lodret i højre side af skærmen"</string>
<string name="revanced_hide_clip_button_title">Skjul klip</string>
<string name="revanced_hide_clip_button_summary_on">Klip knappen er skjult</string>
<string name="revanced_hide_clip_button_summary_off">Klip knappen er vist</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">Skjul butik</string>
<string name="revanced_hide_shop_button_summary_on">Butiksknappen er skjult</string>
<string name="revanced_hide_shop_button_summary_off">Butiksknappen vises</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">Skjul Gem</string>
<string name="revanced_hide_save_button_summary_on">Knappen \"Gem\" er skjult</string>
@@ -700,9 +723,9 @@ Hvis ændring af denne indstilling ikke træder i kraft, kan du prøve at skifte
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menuen for lydspor er skjult</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Menuen Lydspor vises</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Lydspormenuen er skjult
<string name="revanced_hide_player_flyout_audio_track_not_available">"Lydsporsmenuen er skjult
For at vise lydspormenuen skal du ændre \"Spoof videostream\" til iOS TV"</string>
For at vise lydsporsmenuen, skift 'Spoof videostreams' til iPadOS"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">Skjul vagt i VR</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Se i VR-menuen er skjult</string>
@@ -1417,10 +1440,6 @@ Højere videokvalitet kan låses op, men du kan opleve videoafspilningshakkethed
Aktivering af dette kan låse op for højere videokvalitet"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">Aktivering af dette kan forårsage videoafspilning stuttering, værre batterilevetid og ukendte bivirkninger.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Indstillinger</string>
<string name="microg_settings_summary">Indstillinger for GmsCore</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">Haptisk feedback</string>
<string name="revanced_disable_haptic_feedback_summary">Skift haptisk feedback</string>
@@ -1460,7 +1479,7 @@ Aktivering af dette kan låse op for højere videokvalitet"</string>
<string name="revanced_force_original_audio_summary_on">Bruger originalt lydsprog</string>
<string name="revanced_force_original_audio_summary_off">Brug standard lyd</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">For at bruge denne funktion skal du ændre \"Spoof videostreams\" til iOS TV</string>
<string name="revanced_force_original_audio_not_available">For at bruge denne funktion skal du ændre \"Forfalsk videostreams\" til en hvilken som helst klient undtagen Android Studio</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1534,33 +1553,54 @@ Aktivering af dette kan låse op for højere videokvalitet"</string>
<string name="revanced_slide_to_seek_summary_off">Dias til søgning er ikke aktiveret</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Spoof videostreams</string>
<string name="revanced_spoof_video_streams_screen_summary">Spoof klienten video streams for at forhindre afspilning problemer</string>
<string name="revanced_spoof_video_streams_title">Spoof videostreams</string>
<string name="revanced_spoof_video_streams_summary_on">Video streams er spoofed</string>
<string name="revanced_spoof_video_streams_summary_off">"Videostreams forfalskes ikke
Videoafspilning virker muligvis ikke"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">At slå denne indstilling fra kan forårsage problemer med videoafspilning.</string>
<string name="revanced_spoof_video_streams_client_type_title">Standard klient</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">Forceer iOS AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Videokodec er tvunget til AVC (H.264)</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Videokodec bestemmes automatisk</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Aktivering af dette kan forbedre batterilevetiden og rette afspilningshakken.\n\nAVC har en maksimal opløsning på 1080p, Opus-lydkodec er ikke tilgængelig, og videoafspilning vil bruge mere internetdata end VP9 eller AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS-spoofing kan have følgende bivirkninger</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Film eller betalte videoer afspilles muligvis ikke
• Stabil lydstyrke er ikke tilgængelig
• Videoer slutter 1 sekund for tidligt"</string>
<string name="revanced_spoof_video_streams_about_title">Bivirkninger ved spoofing</string>
<string name="revanced_spoof_video_streams_about_android_title">Bivirkninger ved Android-spoofing</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Lydspormenu mangler
• Stabil lydstyrke er ikke tilgængelig
• Gennemtving original lyd er ikke tilgængelig"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Lydsporsmenuen mangler
• Stabil lydstyrke er ikke tilgængelig"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• Videoen kan stoppe ved 1:00, eller er muligvis ikke tilgængelig i visse regioner</string>
<string name="revanced_spoof_video_streams_about_experimental">• Eksperimentel klient og kan stoppe med at fungere når som helst</string>
<string name="revanced_spoof_video_streams_about_no_av1">• Intet AV1-videokodek</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Videoer til børn afspilles muligvis ikke, når du er logget ud eller i inkognitotilstand</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Vis i Statistik for nørder</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Klienttypen vises i Statistik for nørder</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klienten er skjult i Statistik for nørder</string>
<string name="revanced_spoof_video_streams_language_title">VR-standardsprog for lydstrømme</string>
<string name="revanced_spoof_video_streams_language_title">Lydstreamsprog</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">For at vælge et specifikt lydsprog, slå \'Gennemtving originalt lydsprog\' fra</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">Om</string>
<string name="revanced_settings_music_screen_1_ads_title">Annoncer</string>
<string name="revanced_settings_music_screen_2_general_title">Generelt</string>
<string name="revanced_settings_music_screen_3_player_title">Afspiller</string>
<string name="revanced_settings_music_screen_4_misc_title">Diverse</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">Skjul videoannoncer</string>
<string name="revanced_music_hide_video_ads_summary_on">Videoannoncer er skjult</string>
<string name="revanced_music_hide_video_ads_summary_off">Videoannoncer vises</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">Aktiver permanent gentagelse</string>
<string name="revanced_music_play_permanent_repeat_summary_on">Permanent gentagelse er aktiveret</string>
<string name="revanced_music_play_permanent_repeat_summary_off">Permanent gentagelse er deaktiveret</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">Skjul kategorilinje</string>
<string name="revanced_music_hide_category_bar_summary_on">Kategorilinjen er skjult</string>
<string name="revanced_music_hide_category_bar_summary_off">Kategorilinjen vises</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">Skjul \'Få Music Premium\'-etiket</string>
<string name="revanced_music_hide_get_premium_label_summary_on">Etiketten er skjult</string>
<string name="revanced_music_hide_get_premium_label_summary_off">Etiketten vises</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">Skjul opgraderingsknap</string>
<string name="revanced_music_hide_upgrade_button_summary_on">Knappen er skjult</string>
<string name="revanced_music_hide_upgrade_button_summary_off">Knappen vises</string>
</patch>
</app>
<app id="twitch">

View File

@@ -61,13 +61,15 @@ Um neue Sprachen zu übersetzen, besuchen Sie translate.revanced.app"</string>
<string name="revanced_pref_import_export_summary">ReVanced-Einstellungen importieren/exportieren</string>
<!-- Settings about dialog. -->
<string name="revanced_settings_about_links_body">Sie verwenden ReVanced-Patches Version &lt;i&gt;%s&lt;/i&gt;</string>
<string name="revanced_settings_about_links_dev_header">Notiz</string>
<string name="revanced_settings_about_links_dev_header">Hinweis</string>
<string name="revanced_settings_about_links_dev_body">Diese Version ist eine Vorabversion, es kann zu unerwarteten Problemen kommen</string>
<string name="revanced_settings_about_links_header">Offizielle Links</string>
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
and changes made here must also be made there. -->
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Einstellungen</string>
<string name="microg_settings_summary">Einstellungen für GmsCore</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="gms_core_toast_not_installed_message">MicroG GmsCore ist nicht installiert. Installieren Sie es.</string>
<string name="gms_core_dialog_title">Aktion notwendig</string>
@@ -77,11 +79,44 @@ Folgen Sie der Anleitung \"Don't kill my app\" für Ihr Gerät und wenden Sie di
Dies ist erforderlich, damit die App funktioniert."</string>
<string name="gms_core_dialog_open_website_text">Website öffnen</string>
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Die Batterieoptimierung von MicroG GmsCore muss deaktiviert werden, um Probleme zu vermeiden.
Die Deaktivierung der Batterieoptimierung für MicroG hat keinen negativen Einfluss auf den Batterieverbrauch.
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Die Akku-Optimierung muss für MicroG GmsCore deaktiviert werden, um Probleme zu vermeiden.
Die Deaktivierung der Akku-Optimierung für MicroG hat keinen negativen Einfluss auf den Akkuverbrauch.
Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierungsänderungen."</string>
<string name="gms_core_dialog_continue_text">Weiter</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Spoofe Video-Streams</string>
<string name="revanced_spoof_video_streams_screen_summary">Spoofe die Client-Videostreams um Wiedergabeprobleme zu verhindern</string>
<string name="revanced_spoof_video_streams_screen_title">Spoofe Video-Streams</string>
<string name="revanced_spoof_video_streams_screen_summary">Spoofe die Client-Video-Streams, um Wiedergabeprobleme zu verhindern</string>
<string name="revanced_spoof_video_streams_title">Spoofe Video-Streams</string>
<string name="revanced_spoof_video_streams_summary_on">"Videostreams werden gespooft
Wenn Sie ein YouTube Premium-Nutzer sind, ist diese Einstellung möglicherweise nicht erforderlich"</string>
<string name="revanced_spoof_video_streams_summary_off">"Video-Streams werden nicht gespooft
Die Wiedergabe funktioniert möglicherweise nicht"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Das Deaktivieren dieser Einstellung kann Wiedergabeprobleme verursachen.</string>
<string name="revanced_spoof_video_streams_client_type_title">Standard-Client</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Fehlerbehebung</string>
<string name="revanced_debug_screen_summary">Aktiviert oder deaktiviert Debugging-Optionen</string>
<string name="revanced_debug_title">Debug-Protokollierung</string>
<string name="revanced_debug_summary_on">Debug-Protokolle sind aktiviert</string>
<string name="revanced_debug_summary_off">Debug-Protokolle sind deaktiviert</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Debug-Protokolle exportieren</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopiert ReVanced-Debug-Protokolle in die Zwischenablage</string>
<string name="revanced_debug_logs_disabled">Debug-Protokollierung ist deaktiviert</string>
<string name="revanced_debug_logs_none_found">Keine Protokolle gefunden</string>
<string name="revanced_debug_logs_copied_to_clipboard">Protokolle kopiert</string>
<string name="revanced_debug_logs_failed_to_export">Fehler beim Exportieren der Protokolle: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Debug-Protokolle löschen</string>
<string name="revanced_debug_logs_clear_buffer_summary">Löscht alle gespeicherten ReVanced-Debug-Protokolle</string>
<string name="revanced_debug_logs_clear_toast">Protokolle gelöscht</string>
</patch>
</app>
<app id="youtube">
<patch id="misc.settings.settingsPatch">
@@ -103,16 +138,11 @@ Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierung
<string name="revanced_settings_search_history_summary_off">Der Suchverlauf der Einstellungen wird nicht angezeigt</string>
</patch>
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
<string name="revanced_shorts_disable_background_playback_title">Shorts-Hintergrundwiedergabe deaktivieren</string>
<string name="revanced_shorts_disable_background_playback_summary_on">Shorts-Hintergrundwiedergabe ist deaktiviert</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts-Hintergrundwiedergabe ist aktiviert</string>
<string name="revanced_shorts_disable_background_playback_title">Hintergrundwiedergabe von Shorts deaktivieren</string>
<string name="revanced_shorts_disable_background_playback_summary_on">Hintergrundwiedergabe von Shorts ist deaktiviert</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Hintergrundwiedergabe von Shorts ist aktiviert</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Fehlerbehebung</string>
<string name="revanced_debug_screen_summary">Aktiviert oder deaktiviert Debugging-Optionen</string>
<string name="revanced_debug_title">Debug-Protokollierung</string>
<string name="revanced_debug_summary_on">Debug-Protokolle sind aktiviert</string>
<string name="revanced_debug_summary_off">Debug-Protokolle sind deaktiviert</string>
<string name="revanced_debug_protobuffer_title">Protokollpuffer protokollieren</string>
<string name="revanced_debug_protobuffer_summary_on">Debug-Protokolle enthalten Protokollpuffer</string>
<string name="revanced_debug_protobuffer_summary_off">Debug-Protokolle enthalten kein Protokollpuffer</string>
@@ -126,29 +156,20 @@ Wenn Sie dies aktivieren, werden jedoch auch einige Benutzerdaten wie Ihre IP-Ad
<string name="revanced_debug_stacktrace_summary_off">Debug-Logs enthalten keine Stack-Traces</string>
<string name="revanced_debug_toast_on_error_title">Toast bei ReVanced Fehler anzeigen</string>
<string name="revanced_debug_toast_on_error_summary_on">Ein Toast wird angezeigt, wenn ein Fehler auftritt</string>
<string name="revanced_debug_toast_on_error_summary_off">Es wird keine Toast-Nachricht angezeigt, wenn ein Fehler Auftritt</string>
<string name="revanced_debug_toast_on_error_summary_off">Es wird keine Toast-Nachricht angezeigt, wenn ein Fehler auftritt</string>
<string name="revanced_debug_toast_on_error_user_dialog_message">"Das Ausschalten von Fehler-Toasts blendet alle Benachrichtigungen über Fehler in ReVanced aus.
Sie werden nicht über unerwartete Ereignisse informiert."</string>
<string name="revanced_debug_export_logs_to_clipboard_title">Debug-Protokolle exportieren</string>
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopiert ReVanced-Debug-Protokolle in die Zwischenablage</string>
<string name="revanced_debug_logs_disabled">Debug-Protokollierung ist deaktiviert</string>
<string name="revanced_debug_logs_none_found">Keine Protokolle gefunden</string>
<string name="revanced_debug_logs_copied_to_clipboard">Protokolle kopiert</string>
<string name="revanced_debug_logs_failed_to_export">Fehler beim Exportieren der Protokolle: %s</string>
<string name="revanced_debug_logs_clear_buffer_title">Debug-Protokolle löschen</string>
<string name="revanced_debug_logs_clear_buffer_summary">Löscht alle gespeicherten ReVanced-Debug-Protokolle</string>
<string name="revanced_debug_logs_clear_toast">Protokolle gelöscht</string>
</patch>
<patch id="layout.hide.general.hideLayoutComponentsPatch">
<string name="revanced_hide_album_cards_title">Albumkarten ausblenden</string>
<string name="revanced_hide_album_cards_summary_on">Albumkarten sind ausgeblendet</string>
<string name="revanced_hide_album_cards_summary_on">Albumkarten werden ausgeblendet</string>
<string name="revanced_hide_album_cards_summary_off">Albumkarten werden angezeigt</string>
<string name="revanced_hide_artist_cards_title">Interpretenkarten ausblenden</string>
<string name="revanced_hide_artist_cards_summary_on">Künstlerkarten sind ausgeblendet</string>
<string name="revanced_hide_artist_cards_summary_on">Interpretenkarten sind ausgeblendet</string>
<string name="revanced_hide_artist_cards_summary_off">Interpretenkarten werden angezeigt</string>
<string name="revanced_hide_chips_shelf_title">Chips ausblenden</string>
<string name="revanced_hide_chips_shelf_summary_on">Chips sind ausgeblendet</string>
<string name="revanced_hide_chips_shelf_summary_on">Chips werden ausgeblendet</string>
<string name="revanced_hide_chips_shelf_summary_off">Chips werden angezeigt</string>
<string name="revanced_hide_community_posts_title">Communitybeiträge ausblenden</string>
<string name="revanced_hide_community_posts_summary_on">Communitybeiträge sind ausgeblendet</string>
@@ -161,10 +182,10 @@ Sie werden nicht über unerwartete Ereignisse informiert."</string>
<string name="revanced_hide_crowdfunding_box_summary_off">Crowdfunding-Box wird angezeigt</string>
<string name="revanced_hide_expandable_card_title">Ausklappbare Karte ausblenden</string>
<string name="revanced_hide_expandable_card_summary_on">Ausklappbare Karte unter Videos ist ausgeblendet</string>
<string name="revanced_hide_expandable_card_summary_off">Ausklappbare Karte unter Videos ist angezeigt</string>
<string name="revanced_hide_floating_microphone_button_title">Schwebende Mikrofon-Taste ausblenden</string>
<string name="revanced_hide_floating_microphone_button_summary_on">Schwebende Mikrofonschaltfläche in der Suche ist ausgeblendet</string>
<string name="revanced_hide_floating_microphone_button_summary_off">Der schwebende Mikrofon-Button in der Suche wird angezeigt</string>
<string name="revanced_hide_expandable_card_summary_off">Ausklappbare Karte unter Videos wird angezeigt</string>
<string name="revanced_hide_floating_microphone_button_title">Schwebende Mikrofon-Schaltfläche ausblenden</string>
<string name="revanced_hide_floating_microphone_button_summary_on">Schwebende Mikrofon-Schaltfläche wird in der Suche ausgeblendet</string>
<string name="revanced_hide_floating_microphone_button_summary_off">Schwebende Mikrofon-Schaltfläche wird in der Suche angezeigt</string>
<string name="revanced_hide_horizontal_shelves_title">Horizontale Reihe ausblenden</string>
<string name="revanced_hide_horizontal_shelves_summary_on">"Horizontale Regale sind ausgeblendet, wie zum Beispiel:
• Aktuelle Nachrichten
@@ -178,29 +199,29 @@ Sie werden nicht über unerwartete Ereignisse informiert."</string>
<string name="revanced_hide_image_shelf_summary_on">Bild-Regal in den Suchergebnissen ist ausgeblendet</string>
<string name="revanced_hide_image_shelf_summary_off">Bild-Regal in den Suchergebnissen ist angezeigt</string>
<string name="revanced_hide_latest_posts_title">Neueste Beiträge ausblenden</string>
<string name="revanced_hide_latest_posts_summary_on">Neueste Beiträge sind ausgeblendet</string>
<string name="revanced_hide_latest_posts_summary_on">Neueste Beiträge werden ausgeblendet</string>
<string name="revanced_hide_latest_posts_summary_off">Neueste Beiträge werden angezeigt</string>
<string name="revanced_hide_mix_playlists_title">Mix-Wiedergabelisten ausblenden</string>
<string name="revanced_hide_mix_playlists_summary_on">Mix-Wiedergabelisten sind ausgeblendet</string>
<string name="revanced_hide_mix_playlists_summary_on">Mix-Wiedergabelisten werden ausgeblendet</string>
<string name="revanced_hide_mix_playlists_summary_off">Mix-Wiedergabelisten werden angezeigt</string>
<string name="revanced_hide_movies_section_title">Filme-Bereich ausblenden</string>
<string name="revanced_hide_movies_section_summary_on">Film Abschnitt ist ausgeblendet</string>
<string name="revanced_hide_movies_section_summary_off">Film Bereich wird angezeigt</string>
<string name="revanced_hide_movies_section_title">Film-Bereich ausblenden</string>
<string name="revanced_hide_movies_section_summary_on">Film-Bereich wird ausgeblendet</string>
<string name="revanced_hide_movies_section_summary_off">Film-Bereich wird angezeigt</string>
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
<string name="revanced_hide_notify_me_button_title">\'Benachrichtigungen\' Button ausblenden</string>
<string name="revanced_hide_notify_me_button_summary_on">Schaltfläche \"Benachrichtige mich\" ist ausgeblendet</string>
<string name="revanced_hide_notify_me_button_title">Schaltfläche \"Benachrichtige mich\" ausblenden</string>
<string name="revanced_hide_notify_me_button_summary_on">Schaltfläche \"Benachrichtige mich\" wird ausgeblendet</string>
<string name="revanced_hide_notify_me_button_summary_off">Schaltfläche \"Benachrichtige mich\" wird angezeigt</string>
<string name="revanced_hide_playables_title">Playables ausblenden</string>
<string name="revanced_hide_playables_summary_on">Spiele sind ausgeblendet</string>
<string name="revanced_hide_playables_summary_off">Spielbare werden angezeigt</string>
<string name="revanced_hide_playables_summary_on">Playables sind ausgeblendet</string>
<string name="revanced_hide_playables_summary_off">Playables werden angezeigt</string>
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
This button usually appears when searching for a YT creator. -->
<string name="revanced_hide_show_more_button_title">\'Mehr anzeigen\' Button ausblenden</string>
<string name="revanced_hide_show_more_button_summary_on">Schaltfläche \"Mehr anzeigen\" in den Suchergebnissen ist ausgeblendet</string>
<string name="revanced_hide_show_more_button_summary_off">Schaltfläche \"Mehr anzeigen\" in den Suchergebnissen wird angezeigt</string>
<string name="revanced_hide_surveys_title">Umfragen ausblenden</string>
<string name="revanced_hide_surveys_summary_on">Umfragen sind ausgeblendet</string>
<string name="revanced_hide_surveys_summary_on">Umfragen werden ausgeblendet</string>
<string name="revanced_hide_surveys_summary_off">Umfragen werden angezeigt</string>
<string name="revanced_hide_ticket_shelf_title">Ticket-Reihe ausblenden</string>
<string name="revanced_hide_ticket_shelf_summary_on">Ticket-Reihe ist ausgeblendet</string>
@@ -402,14 +423,14 @@ Diese Funktion ist nur für ältere Geräte verfügbar"</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_fullscreen_ads_feature_not_available_toast">Vollbild-Werbung ausblenden funktioniert nur mit älteren Geräten</string>
<string name="revanced_hide_general_ads_title">Allgemeine Werbung ausblenden</string>
<string name="revanced_hide_general_ads_summary_on">Allgemeine Anzeigen sind ausgeblendet</string>
<string name="revanced_hide_general_ads_summary_off">Allgemeine Anzeigen werden angezeigt</string>
<string name="revanced_hide_general_ads_summary_on">Allgemeine Werbung werden ausgeblendet</string>
<string name="revanced_hide_general_ads_summary_off">Allgemeine Werbung werden angezeigt</string>
<string name="revanced_hide_merchandise_banners_title">Merchandise-Banner ausblenden</string>
<string name="revanced_hide_merchandise_banners_summary_on">Merchandise-Banner sind ausgeblendet</string>
<string name="revanced_hide_merchandise_banners_summary_off">Warenbanner werden angezeigt</string>
<string name="revanced_hide_paid_promotion_label_title">Bezahltes Werbe-Label ausblenden</string>
<string name="revanced_hide_paid_promotion_label_summary_on">Bezahltes Werbelabel ist ausgeblendet</string>
<string name="revanced_hide_paid_promotion_label_summary_off">Bezahltes Werbe-Label wird angezeigt</string>
<string name="revanced_hide_paid_promotion_label_title">\"Enthält bezahlte Werbung\"-Hinweis ausblenden</string>
<string name="revanced_hide_paid_promotion_label_summary_on">\"Enthält bezahlte Werbung\"-Hinweis wird ausgeblendet</string>
<string name="revanced_hide_paid_promotion_label_summary_off">\"Enthält bezahlte Werbung\"-Hinweis wird angezeigt</string>
<string name="revanced_hide_self_sponsor_ads_title">Selbst gesponserte Karten ausblenden</string>
<string name="revanced_hide_self_sponsor_ads_summary_on">Selbst gesponserte Karten sind ausgeblendet</string>
<string name="revanced_hide_self_sponsor_ads_summary_off">Selbstgesponserte Karten werden angezeigt</string>
@@ -597,6 +618,10 @@ Passen Sie die Helligkeit an, indem Sie auf der linken Seite des Bildschirms ver
<string name="revanced_hide_clip_button_title">Clip ausblenden</string>
<string name="revanced_hide_clip_button_summary_on">Clip-Button ist ausgeblendet</string>
<string name="revanced_hide_clip_button_summary_off">Clip-Taste wird angezeigt</string>
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_shop_button_title">Shop ausblenden</string>
<string name="revanced_hide_shop_button_summary_on">Shop-Button ist ausgeblendet</string>
<string name="revanced_hide_shop_button_summary_off">Shop-Button wird angezeigt</string>
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
<string name="revanced_hide_save_button_title">Speichern ausblenden</string>
<string name="revanced_hide_save_button_summary_on">Schaltfläche \"Speichern\" ist ausgeblendet</string>
@@ -695,9 +720,9 @@ Wenn diese Änderung nicht wirksam wird, versuchen Sie, in den Inkognito-Modus z
<string name="revanced_hide_player_flyout_audio_track_summary_on">Audiospur-Menü ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Audiospurmenü wird angezeigt</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Das Audiotrack-Menü ist ausgeblendet.
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audiotrack-Menü ist ausgeblendet
Um das Audiotrack-Menü anzuzeigen, ändere \"Video-Streams fälschen\" zu iOS TV"</string>
Um das Audiotrack-Menü anzuzeigen, ändern Sie \"Video-Streams fälschen\" zu iPadOS"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">Überwachung in VR ausblenden</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Im VR-Menü beobachten ist ausgeblendet</string>
@@ -979,22 +1004,22 @@ Diese Funktion funktioniert am besten mit einer Videoqualität von 720p oder nie
</patch>
<patch id="layout.sponsorblock.sponsorBlockResourcePatch">
<string name="revanced_sb_enable_sb">SponsorBlock aktivieren</string>
<string name="revanced_sb_enable_sb_sum">SponsorBlock ist ein Crowdsourcing-System zum Überspringen von nervigen Teilen von YouTube-Videos</string>
<string name="revanced_sb_enable_sb_sum">SponsorBlock ist ein Crowdsourcing-System zum Überspringen von nervigen Segmenten von YouTube-Videos</string>
<string name="revanced_sb_appearance_category">Darstellung</string>
<string name="revanced_sb_enable_voting">Stimmen-Button anzeigen</string>
<string name="revanced_sb_enable_voting_sum_on">Segmentstimmen Button wird angezeigt</string>
<string name="revanced_sb_enable_voting_sum_off">Segmentstimmen Button wird nicht angezeigt</string>
<string name="revanced_sb_square_layout">Quadratisches Layout verwenden</string>
<string name="revanced_sb_enable_voting">Like-Button anzeigen</string>
<string name="revanced_sb_enable_voting_sum_on">Segmentbewertungs-Button wird angezeigt</string>
<string name="revanced_sb_enable_voting_sum_off">Segmentbewertungs-Button wird nicht angezeigt</string>
<string name="revanced_sb_square_layout">Quadratische Bedienelemente verwenden</string>
<string name="revanced_sb_square_layout_sum_on">Schaltflächen und Steuerelemente sind quadratisch</string>
<string name="revanced_sb_square_layout_sum_off">Schaltflächen und Bedienelemente sind abgerundet</string>
<!-- Translations should use language similar to 'revanced_ryd_compact_layout_title'. -->
<string name="revanced_sb_enable_compact_skip_button">Kompakten Überspringen-Button verwenden</string>
<string name="revanced_sb_enable_compact_skip_button_sum_on">Überspringe Taste für minimale Breite</string>
<string name="revanced_sb_enable_compact_skip_button_sum_off">Überspringen-Button für beste Darstellung gestaltet</string>
<string name="revanced_sb_enable_compact_skip_button_sum_on">Überspringen-Button wird mit minimale Breite angezeigt</string>
<string name="revanced_sb_enable_compact_skip_button_sum_off">Überspringen-Button wird mit bestem Aussehen angezeigt</string>
<string name="revanced_sb_enable_auto_hide_skip_segment_button">Überspringen-Button automatisch ausblenden</string>
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_on">Überspringe Taste verbirgt sich nach ein paar Sekunden</string>
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_off">Die Schaltfläche \"Überspringen\" wird für das gesamte Segment angezeigt</string>
<string name="revanced_sb_auto_hide_skip_button_duration">Dauer des Überspringen-Buttons</string>
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_on">Überspringen-Button wird nach ein paar Sekunden ausgeblendet</string>
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_off">Überspringen-Button wird während des ganzen Segmentes angezeigt</string>
<string name="revanced_sb_auto_hide_skip_button_duration">Anzeigedauer des Überspringen-Buttons</string>
<string name="revanced_sb_auto_hide_skip_button_duration_sum">Wie lange die Schaltflächen zum Überspringen und zum Hervorheben angezeigt werden sollen, bevor sie automatisch ausgeblendet werden</string>
<string name="revanced_sb_general_skiptoast">Toast zum Rückgängigmachen des Überspringens anzeigen</string>
<string name="revanced_sb_general_skiptoast_sum_on">Ein Toast wird angezeigt, wenn ein Segment automatisch übersprungen wird. Tippen Sie auf die Toast-Benachrichtigung, um das Überspringen rückgängig zu machen</string>
@@ -1059,25 +1084,25 @@ Ihre Benutzer-ID ist wie ein Passwort und sollte niemals weitergegeben werden.
<string name="revanced_sb_settings_revanced_export_user_id_warning_dismiss">Nicht wieder anzeigen</string>
<string name="revanced_sb_diff_segments">Segmentverhalten ändern</string>
<string name="revanced_sb_segments_sponsor">Sponsor</string>
<string name="revanced_sb_segments_sponsor_sum">Bezahlte Förderung, bezahlte Empfehlungen und direkte Werbung. Nicht für Selbstwerbung oder kostenlose Shoutouts an Ursachen/Webseiten/Produkte, die ihnen gefallen</string>
<string name="revanced_sb_segments_selfpromo">Unbezahlt/Eigenwerbung</string>
<string name="revanced_sb_segments_sponsor_sum">Bezahlte Werbung, bezahlte Empfehlungen und direkte Werbung. Nicht für Eigenwerbung oder kostenlose Shoutouts an Zwecke/Webseiten/Produkte, die ihnen gefallen</string>
<string name="revanced_sb_segments_selfpromo">Unbezahlte oder Eigenwerbung</string>
<string name="revanced_sb_segments_selfpromo_sum">Ähnlich wie Sponsor, jedoch für unbezahlte oder Eigenwerbung. Enthält Abschnitte über Merchandise, Spenden oder Informationen darüber, mit wem sie zusammengearbeitet haben</string>
<string name="revanced_sb_segments_interaction">Interaktionserinnerung (Abonnieren)</string>
<string name="revanced_sb_segments_interaction_sum">Eine kurze Erinnerung, sie in der Mitte des Inhalts zu zitieren, zu abonnieren oder zu verfolgen. Wenn es lang ist oder etwas Konkretes ist, sollte es stattdessen unter Selbstförderung stehen</string>
<string name="revanced_sb_segments_highlight">Hervorheben</string>
<string name="revanced_sb_segments_interaction_sum">Eine kurze Erinnerung, sie in der Mitte des Inhalts zu liken, abonnieren oder folgen. Wenn er lang ist oder es um etwas Bestimmtes geht, sollte es stattdessen als Eigenwerbung gekennzeichnet sein</string>
<string name="revanced_sb_segments_highlight">Highlight</string>
<string name="revanced_sb_segments_highlight_sum">Der Teil des Videos, nach dem die meisten Menschen suchen</string>
<string name="revanced_sb_segments_intro">Unterbrechung/Introanimation</string>
<string name="revanced_sb_segments_intro_sum">Ein Intervall ohne aktuellen Inhalt. Kann eine Pause, ein statischer Rahmen oder eine Wiederholung der Animation sein. Enthält keine Übergänge mit Informationen</string>
<string name="revanced_sb_segments_outro">Endkarten / Credits</string>
<string name="revanced_sb_segments_outro_sum">Credits oder wenn die YouTube-Endkarten erscheinen. Nicht für Schlussfolgerungen mit Informationen</string>
<string name="revanced_sb_segments_intro_sum">Ein Intervall ohne aktuellen Inhalt. Kann eine Pause, ein statischer Frame oder eine wiederholende Animation sein. Enthält keine Übergänge mit Informationen</string>
<string name="revanced_sb_segments_outro">Endkarte / Credits</string>
<string name="revanced_sb_segments_outro_sum">Credits oder wenn die YouTube-Endkarten erscheinen. Nicht für Fazite mit Informationen</string>
<string name="revanced_sb_segments_hook">Hook / Begrüßungen</string>
<string name="revanced_sb_segments_hook_sum">Erzählte Trailer für das kommende Video, Begrüßungen und Verabschiedungen. Enthält keine Abschnitte, die zusätzlichen Inhalt hinzufügen</string>
<string name="revanced_sb_segments_hook_sum">Erzählte Trailer für das kommende Video, Begrüßungen und Verabschiedungen. Enthält keine Segmente, die zusätzlichen Inhalt hinzufügen</string>
<string name="revanced_sb_segments_preview">Vorschau / Rückblick</string>
<string name="revanced_sb_segments_preview_sum">Sammlung von Clips, die zeigen, was im Video oder in anderen Videos einer Serie vor sich geht, wo alle Informationen andernorts wiederholt werden</string>
<string name="revanced_sb_segments_preview_sum">Sammlung von Clips, die zeigen, was im Video oder in anderen Videos einer Serie passiert ist, wo alle Informationen andernorts wiederholt werden</string>
<string name="revanced_sb_segments_filler">Abschweifung / Witze</string>
<string name="revanced_sb_segments_filler_sum">Tangentiale Szenen oder Witze, die nicht erforderlich sind, um den Hauptinhalt des Videos zu verstehen. Dies sollte keine Segmente enthalten, die Kontext oder Hintergrunddetails liefern</string>
<string name="revanced_sb_segments_nomusic">Musik: Nicht-Musik-Sektion</string>
<string name="revanced_sb_segments_nomusic_sum">Nur für die Verwendung in Musikvideos. Abschnitte von Musikvideos ohne Musik, die noch nicht von einer anderen Kategorie abgedeckt sind</string>
<string name="revanced_sb_segments_filler_sum">Tangentiale Szenen oder Witze, die nicht erforderlich sind, um den Hauptinhalt des Videos zu verstehen. Enthält keine Segmente, die Kontext oder Hintergrunddetails liefern</string>
<string name="revanced_sb_segments_nomusic">Musikvideos: Nicht-Musik-Passagen</string>
<string name="revanced_sb_segments_nomusic_sum">Nur für die Verwendung in Musikvideos. Abschnitte von Musikvideos ohne Musik, die noch nicht von einer anderen Kategorie abgedeckt werden</string>
<string name="revanced_sb_skip_button_compact">Überspringen</string>
<string name="revanced_sb_skip_button_compact_highlight">Hervorheben</string>
<string name="revanced_sb_skip_button_sponsor">Sponsor überspringen</string>
@@ -1352,29 +1377,29 @@ Durch Aktivieren dieser Option können fehlende Bilder behoben werden, die in ei
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays for the Subscriptions tab. -->
<string name="revanced_alt_thumbnail_subscription_title">Abos-Tab</string>
<!-- 'You' should be translated using the same localized wording YouTube displays for the You (Library) tab. -->
<string name="revanced_alt_thumbnail_library_title">Tab</string>
<string name="revanced_alt_thumbnail_library_title">Mein YouTube-Tab</string>
<string name="revanced_alt_thumbnail_player_title">Player-Wiedergabelisten &amp; Empfehlungen</string>
<string name="revanced_alt_thumbnail_search_title">Suchergebnisse</string>
<string name="revanced_alt_thumbnail_options_entry_1">Original-Miniaturansichten</string>
<string name="revanced_alt_thumbnail_options_entry_2">Pfeil &amp; Original-Miniaturansichten</string>
<string name="revanced_alt_thumbnail_options_entry_3">Pfeil &amp; immer noch erfasst</string>
<string name="revanced_alt_thumbnail_options_entry_4">Noch Aufnahmen</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow bietet von der Community bereitgestellte Miniaturansichten für YouTube-Videos. Diese Miniaturansichten sind oft relevanter als die von YouTube bereitgestellten.
<string name="revanced_alt_thumbnail_options_entry_1">Original-Vorschaubilder</string>
<string name="revanced_alt_thumbnail_options_entry_2">Pfeil &amp; Original-Vorschaubilder</string>
<string name="revanced_alt_thumbnail_options_entry_3">Pfeil &amp; Standbild</string>
<string name="revanced_alt_thumbnail_options_entry_4">Standbild</string>
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow bietet von der Community bereitgestellte Vorschaubilder für YouTube-Videos. Diese Vorschaubilder sind oft relevanter als die von YouTube bereitgestellten.
Wenn diese Option aktiviert ist, werden Video-URLs an den API-Server gesendet und keine anderen Daten werden gesendet. Wenn ein Video keine DeArrow-Miniaturansichten hat, werden die Original- oder Still-Captures angezeigt.
Wenn diese Option aktiviert ist, werden Video-URLs an den API-Server gesendet und keine anderen Daten werden gesendet. Wenn ein Video keine DeArrow-Vorschaubilder hat, wird das originale Vorschaubild oder ein Standbild angezeigt.
Tippen Sie hier, um mehr über DeArrow zu erfahren"</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">Einen Toast anzeigen, wenn die API nicht verfügbar ist</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">Toast wird angezeigt, wenn der Pfeil nicht verfügbar ist</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">Toast wird nicht angezeigt, wenn der Pfeil nicht verfügbar ist</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_title">Ein Toast anzeigen, wenn die API nicht verfügbar ist</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_on">Toast wird angezeigt, wenn DeArrow nicht verfügbar ist</string>
<string name="revanced_alt_thumbnail_dearrow_connection_toast_summary_off">Toast wird nicht angezeigt, wenn DeArrow nicht verfügbar ist</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_title">DeArrow API-Endpunkt</string>
<string name="revanced_alt_thumbnail_dearrow_api_url_summary">Die URL des Cache Endpunkts der DeArrow Thumbnails</string>
<string name="revanced_alt_thumbnail_stills_about_title">Noch Videoaufnahmen</string>
<string name="revanced_alt_thumbnail_stills_about_summary">Die Aufnahmen werden immer noch von Anfang an / Mitte / Ende jedes Videos übernommen. Diese Bilder sind in YouTube eingebaut und es wird keine externe API verwendet</string>
<string name="revanced_alt_thumbnail_stills_fast_title">Schnelle Stand-Captures verwenden</string>
<string name="revanced_alt_thumbnail_stills_fast_summary_on">Die Verwendung von mittlerer Qualität bleibt erhalten. Die Vorschaubilder werden schneller geladen, aber Live-Streams, unveröffentlichte oder sehr alte Videos können leere Thumbnails anzeigen</string>
<string name="revanced_alt_thumbnail_stills_fast_summary_off">Verwendung hoher Qualität immer noch Captures</string>
<string name="revanced_alt_thumbnail_stills_time_title">Videozeitr Aufnahmen von</string>
<string name="revanced_alt_thumbnail_stills_about_title">Standbilder</string>
<string name="revanced_alt_thumbnail_stills_about_summary">Die Standbilder werden vom Anfang / Mitte / Ende jedes Videos erstellt. Diese Bilder stammen von YouTube und es wird keine externe API verwendet</string>
<string name="revanced_alt_thumbnail_stills_fast_title">Schnelle Standbilder verwenden</string>
<string name="revanced_alt_thumbnail_stills_fast_summary_on">Standbilder in mittlerer Qualität verwenden. Die Vorschaubilder werden schneller geladen, aber Livestreams, unveröffentlichte oder sehr alte Videos können leere Vorschaubilder anzeigen.</string>
<string name="revanced_alt_thumbnail_stills_fast_summary_off">Standbilder in hoher Qualität verwenden</string>
<string name="revanced_alt_thumbnail_stills_time_title">Videozeitpunkt von dem Standbilder aufgenommen werden</string>
<string name="revanced_alt_thumbnail_stills_time_entry_1">Beginn des Videos</string>
<string name="revanced_alt_thumbnail_stills_time_entry_2">Mitte des Videos</string>
<string name="revanced_alt_thumbnail_stills_time_entry_3">Ende des Videos</string>
@@ -1410,10 +1435,6 @@ Höhere Videoqualitäten können freigeschaltet werden, aber es kann zu Stottern
Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet werden"</string>
<string name="revanced_spoof_device_dimensions_user_dialog_message">Aktivieren kann dazu führen, dass Videowiedergabe blockiert, die Batterielebensdauer verschlechtert und unbekannte Nebeneffekte entstehen.</string>
</patch>
<patch id="misc.gms.gmsCoreSupportResourcePatch">
<string name="microg_settings_title">GmsCore Einstellungen</string>
<string name="microg_settings_summary">Einstellungen für GmsCore</string>
</patch>
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
<string name="revanced_disable_haptic_feedback_title">Haptisches Feedback</string>
<string name="revanced_disable_haptic_feedback_summary">Haptisches Feedback ändern</string>
@@ -1453,7 +1474,7 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w
<string name="revanced_force_original_audio_summary_on">Original-Audiosprache verwenden</string>
<string name="revanced_force_original_audio_summary_off">Standardaudio verwenden</string>
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<string name="revanced_force_original_audio_not_available">Um diese Funktion zu nutzen, ändere \"Video-Streams fälschen\" zu iOS TV</string>
<string name="revanced_force_original_audio_not_available">Um diese Funktion zu nutzen, ändere \"Video-Streams fälschen\" auf einen beliebigen Client außer Android Studio</string>
</patch>
<patch id="video.quality.rememberVideoQualityPatch">
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
@@ -1527,35 +1548,54 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w
<string name="revanced_slide_to_seek_summary_off">Slide zum Suchen ist nicht aktiviert</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<string name="revanced_spoof_video_streams_screen_title">Spoof-Video-Streams</string>
<string name="revanced_spoof_video_streams_screen_summary">Spoof der Client-Videostreams um Wiedergabeprobleme zu verhindern</string>
<string name="revanced_spoof_video_streams_title">Spoof-Video-Streams</string>
<string name="revanced_spoof_video_streams_summary_on">Video-Streams sind gefälscht</string>
<string name="revanced_spoof_video_streams_summary_off">"Videoströme werden nicht gefälscht
Die Videowiedergabe funktioniert möglicherweise nicht"</string>
<string name="revanced_spoof_video_streams_user_dialog_message">Das Deaktivieren dieser Einstellung kann zu Videowiedergabeproblemen führen.</string>
<string name="revanced_spoof_video_streams_client_type_title">Standard-Client</string>
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) erzwingen</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Der Videocodec ist auf AVC (H.264) erzwungen.</string>
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Der Videocodec wird automatisch bestimmt.</string>
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Aktivieren Sie dies, um die Akkulaufzeit zu verbessern und Ruckeln bei der Wiedergabe zu beheben.
AVC hat eine maximale Auflösung von 1080p, Opus-Audiocodec ist nicht verfügbar und die Videowiedergabe verbraucht mehr Internetdaten als VP9 oder AV1."</string>
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS-Spoofing-Nebenwirkungen</string>
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Filme oder kostenpflichtige Videos können möglicherweise nicht abgespielt werden
• Eine stabile Lautstärke ist nicht verfügbar
• Videos enden 1 Sekunde zu früh"</string>
<string name="revanced_spoof_video_streams_about_title">Nebenwirkungen des Spoofings</string>
<string name="revanced_spoof_video_streams_about_android_title">Android-Spoofing-Nebenwirkungen</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Audiospur-Menü fehlt
• Stabile Lautstärke ist nicht verfügbar
• Original-Audio erzwingen ist nicht verfügbar"</string>
<string name="revanced_spoof_video_streams_about_android_summary">"• Audiotrack-Menü fehlt
• Stabile Lautstärke ist nicht verfügbar"</string>
<string name="revanced_spoof_video_streams_about_ipados_summary">• Video kann um 1:00 Uhr stoppen oder ist möglicherweise in einigen Regionen nicht verfügbar</string>
<string name="revanced_spoof_video_streams_about_experimental">• Experimenteller Client und kann jederzeit aufhören zu funktionieren</string>
<string name="revanced_spoof_video_streams_about_no_av1">• Kein AV1-Videocodec</string>
<string name="revanced_spoof_video_streams_about_kids_videos">• Kinder-Videos werden möglicherweise nicht abgespielt, wenn du abgemeldet bist oder den Inkognito-Modus verwendest.</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">In Statistiken für Nerds anzeigen</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Der Client-Typ wird in den Statistiken für Nerds angezeigt</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Der Client wird in den Statistiken für Nerds ausgeblendet</string>
<string name="revanced_spoof_video_streams_language_title">Standard-Audiostreamsprache für VR</string>
<string name="revanced_spoof_video_streams_language_title">Audiodatenstromsprache</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Um eine bestimmte Audiosprache auszuwählen, deaktivieren Sie „Original-Audiosprache erzwingen“</string>
</patch>
</app>
<app id="music">
<patch id="misc.settings.settingsPatch">
<string name="revanced_settings_music_screen_0_about_title">Über</string>
<string name="revanced_settings_music_screen_1_ads_title">Werbung</string>
<string name="revanced_settings_music_screen_2_general_title">Allgemein</string>
<string name="revanced_settings_music_screen_3_player_title">Spieler</string>
<string name="revanced_settings_music_screen_4_misc_title">Sonstiges</string>
</patch>
<patch id="ad.video.hideVideoAdsPatch">
<string name="revanced_music_hide_video_ads_title">Videoanzeigen ausblenden</string>
<string name="revanced_music_hide_video_ads_summary_on">Videoanzeigen sind ausgeblendet</string>
<string name="revanced_music_hide_video_ads_summary_off">Videoanzeigen werden angezeigt</string>
</patch>
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
<string name="revanced_music_play_permanent_repeat_title">Dauerwiederholung aktivieren</string>
<string name="revanced_music_play_permanent_repeat_summary_on">Dauerwiederholung ist aktiviert</string>
<string name="revanced_music_play_permanent_repeat_summary_off">Dauerwiederholung ist deaktiviert</string>
</patch>
<patch id="layout.compactheader.hideCategoryBar">
<string name="revanced_music_hide_category_bar_title">Kategorieleiste ausblenden</string>
<string name="revanced_music_hide_category_bar_summary_on">Kategorieleiste ist ausgeblendet</string>
<string name="revanced_music_hide_category_bar_summary_off">Kategorieleiste wird angezeigt</string>
</patch>
<patch id="layout.premium.hideGetPremiumPatch">
<string name="revanced_music_hide_get_premium_label_title">\"Music Premium holen\"-Label ausblenden</string>
<string name="revanced_music_hide_get_premium_label_summary_on">Label ist ausgeblendet</string>
<string name="revanced_music_hide_get_premium_label_summary_off">Label wird angezeigt</string>
</patch>
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
<string name="revanced_music_hide_upgrade_button_title">Upgrade-Button ausblenden</string>
<string name="revanced_music_hide_upgrade_button_summary_on">Button ist ausgeblendet</string>
<string name="revanced_music_hide_upgrade_button_summary_off">Button wird angezeigt</string>
</patch>
</app>
<app id="twitch">

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