mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 18:03:55 +01:00
Compare commits
11 Commits
v5.23.0-de
...
v5.23.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
639850471b | ||
|
|
796c118fe1 | ||
|
|
edf20e397d | ||
|
|
5f0541407c | ||
|
|
56b7ba9ba7 | ||
|
|
f8bdf744ab | ||
|
|
f4f36ff273 | ||
|
|
5028c1acb3 | ||
|
|
555c9a5823 | ||
|
|
777957e2d0 | ||
|
|
b3316a5915 |
34
CHANGELOG.md
34
CHANGELOG.md
@@ -1,3 +1,37 @@
|
||||
# [5.23.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.23.0-dev.6...v5.23.0-dev.7) (2025-05-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix incorrect fingerprints ([#4917](https://github.com/ReVanced/revanced-patches/issues/4917)) ([49ca329](https://github.com/ReVanced/revanced-patches/commit/49ca3290a726cdba7bc9b62ffcd8d46e6f04778e))
|
||||
|
||||
# [5.23.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.23.0-dev.5...v5.23.0-dev.6) (2025-05-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Correct incorrect fingerprint ([c3bab89](https://github.com/ReVanced/revanced-patches/commit/c3bab89fc4189e38c10eee0caa36289de7e29dfa))
|
||||
|
||||
# [5.23.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.23.0-dev.4...v5.23.0-dev.5) (2025-05-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Unlock Spotify Premium:** Remove pop up premium ads ([#4842](https://github.com/ReVanced/revanced-patches/issues/4842)) ([00aa200](https://github.com/ReVanced/revanced-patches/commit/00aa2000ba2eef15a0dd827c2bd84c2e85c412e0))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Pandora:** Add `Disable audio ads` and `Unlimited skips` patch ([#4841](https://github.com/ReVanced/revanced-patches/issues/4841)) ([0cf7a4c](https://github.com/ReVanced/revanced-patches/commit/0cf7a4c6be615ed0a52a6bacf87592f5f43ff575))
|
||||
* **Prime Video:** Add `Skip ads` patch ([#4824](https://github.com/ReVanced/revanced-patches/issues/4824)) ([bb672c4](https://github.com/ReVanced/revanced-patches/commit/bb672c4674ddc201b8b2648c3906cfc31ef43f10))
|
||||
|
||||
# [5.23.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.23.0-dev.3...v5.23.0-dev.4) (2025-05-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Spotify:** Add `Sanitize sharing links` patch ([#4829](https://github.com/ReVanced/revanced-patches/issues/4829)) ([2e3511d](https://github.com/ReVanced/revanced-patches/commit/2e3511d03c8198bbdb9336888df038a33fb3ab8c))
|
||||
|
||||
# [5.23.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.23.0-dev.2...v5.23.0-dev.3) (2025-05-05)
|
||||
|
||||
|
||||
|
||||
4
extensions/primevideo/build.gradle.kts
Normal file
4
extensions/primevideo/build.gradle.kts
Normal file
@@ -0,0 +1,4 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:primevideo:stub"))
|
||||
}
|
||||
1
extensions/primevideo/src/main/AndroidManifest.xml
Normal file
1
extensions/primevideo/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,36 @@
|
||||
package app.revanced.extension.primevideo.ads;
|
||||
|
||||
import com.amazon.avod.fsm.SimpleTrigger;
|
||||
import com.amazon.avod.media.ads.AdBreak;
|
||||
import com.amazon.avod.media.ads.internal.state.AdBreakTrigger;
|
||||
import com.amazon.avod.media.ads.internal.state.AdEnabledPlayerTriggerType;
|
||||
import com.amazon.avod.media.playback.VideoPlayer;
|
||||
import com.amazon.avod.media.ads.internal.state.ServerInsertedAdBreakState;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class SkipAdsPatch {
|
||||
public static void enterServerInsertedAdBreakState(ServerInsertedAdBreakState state, AdBreakTrigger trigger, VideoPlayer player) {
|
||||
try {
|
||||
AdBreak adBreak = trigger.getBreak();
|
||||
|
||||
// There are two scenarios when entering the original method:
|
||||
// 1. Player naturally entered an ad break while watching a video.
|
||||
// 2. User is skipped/scrubbed to a position on the timeline. If seek position is past an ad break,
|
||||
// user is forced to watch an ad before continuing.
|
||||
//
|
||||
// Scenario 2 is indicated by trigger.getSeekStartPosition() != null, so skip directly to the scrubbing
|
||||
// target. Otherwise, just calculate when the ad break should end and skip to there.
|
||||
if (trigger.getSeekStartPosition() != null)
|
||||
player.seekTo(trigger.getSeekTarget().getTotalMilliseconds());
|
||||
else
|
||||
player.seekTo(player.getCurrentPosition() + adBreak.getDurationExcludingAux().getTotalMilliseconds());
|
||||
|
||||
// Send "end of ads" trigger to state machine so everything doesn't get whacky.
|
||||
state.doTrigger(new SimpleTrigger(AdEnabledPlayerTriggerType.NO_MORE_ADS_SKIP_TRANSITION));
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Failed skipping ads", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
extensions/primevideo/stub/build.gradle.kts
Normal file
17
extensions/primevideo/stub/build.gradle.kts
Normal file
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
id(libs.plugins.android.library.get().pluginId)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
1
extensions/primevideo/stub/src/main/AndroidManifest.xml
Normal file
1
extensions/primevideo/stub/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.amazon.avod.fsm;
|
||||
|
||||
public final class SimpleTrigger<T> implements Trigger<T> {
|
||||
public SimpleTrigger(T triggerType) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.amazon.avod.fsm;
|
||||
|
||||
public abstract class StateBase<S, T> {
|
||||
// This method orginally has protected access (modified in patch code).
|
||||
public void doTrigger(Trigger<T> trigger) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.amazon.avod.fsm;
|
||||
|
||||
public interface Trigger<T> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.amazon.avod.media;
|
||||
|
||||
public final class TimeSpan {
|
||||
public long getTotalMilliseconds() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.amazon.avod.media.ads;
|
||||
|
||||
import com.amazon.avod.media.TimeSpan;
|
||||
|
||||
public interface AdBreak {
|
||||
TimeSpan getDurationExcludingAux();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.amazon.avod.media.ads.internal.state;
|
||||
|
||||
public abstract class AdBreakState extends AdEnabledPlaybackState {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.amazon.avod.media.ads.internal.state;
|
||||
|
||||
import com.amazon.avod.media.ads.AdBreak;
|
||||
import com.amazon.avod.media.TimeSpan;
|
||||
|
||||
public class AdBreakTrigger {
|
||||
public AdBreak getBreak() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public TimeSpan getSeekTarget() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public TimeSpan getSeekStartPosition() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.amazon.avod.media.ads.internal.state;
|
||||
|
||||
import com.amazon.avod.fsm.StateBase;
|
||||
import com.amazon.avod.media.playback.state.PlayerStateType;
|
||||
import com.amazon.avod.media.playback.state.trigger.PlayerTriggerType;
|
||||
|
||||
public class AdEnabledPlaybackState extends StateBase<PlayerStateType, PlayerTriggerType> {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.amazon.avod.media.ads.internal.state;
|
||||
|
||||
public enum AdEnabledPlayerTriggerType {
|
||||
NO_MORE_ADS_SKIP_TRANSITION
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.amazon.avod.media.ads.internal.state;
|
||||
|
||||
public class ServerInsertedAdBreakState extends AdBreakState {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.amazon.avod.media.playback;
|
||||
|
||||
public interface VideoPlayer {
|
||||
long getCurrentPosition();
|
||||
|
||||
void seekTo(long positionMs);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.amazon.avod.media.playback.state;
|
||||
|
||||
public interface PlayerStateType {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.amazon.avod.media.playback.state.trigger;
|
||||
|
||||
public interface PlayerTriggerType {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package app.revanced.extension.spotify.misc.privacy;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class SanitizeSharingLinksPatch {
|
||||
|
||||
/**
|
||||
* Parameters that are considered undesirable and should be stripped away.
|
||||
*/
|
||||
private static final List<String> SHARE_PARAMETERS_TO_REMOVE = List.of(
|
||||
"si", // Share tracking parameter.
|
||||
"utm_source" // Share source, such as "copy-link".
|
||||
);
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static String sanitizeUrl(String url) {
|
||||
try {
|
||||
Uri uri = Uri.parse(url);
|
||||
Uri.Builder builder = uri.buildUpon().clearQuery();
|
||||
|
||||
for (String paramName : uri.getQueryParameterNames()) {
|
||||
if (!SHARE_PARAMETERS_TO_REMOVE.contains(paramName)) {
|
||||
for (String value : uri.getQueryParameters(paramName)) {
|
||||
builder.appendQueryParameter(paramName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build().toString();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "sanitizeUrl failure", ex);
|
||||
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.23.0-dev.3
|
||||
version = 5.23.0-dev.7
|
||||
|
||||
@@ -380,6 +380,14 @@ public final class app/revanced/patches/openinghours/misc/fix/crash/FixCrashPatc
|
||||
public static final fun getFixCrashPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/pandora/ads/DisableAudioAdsPatchKt {
|
||||
public static final fun getDisableAudioAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/pandora/misc/EnableUnlimitedSkipsPatchKt {
|
||||
public static final fun getEnableUnlimitedSkipsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/photomath/detection/deviceid/SpoofDeviceIdPatchKt {
|
||||
public static final fun getGetDeviceIdPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -412,6 +420,14 @@ public final class app/revanced/patches/pixiv/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/primevideo/ads/SkipAdsPatchKt {
|
||||
public static final fun getSkipAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/primevideo/misc/extension/ExtensionPatchKt {
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/protonmail/signature/RemoveSentFromSignaturePatchKt {
|
||||
public static final fun getRemoveSentFromSignaturePatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
@@ -852,6 +868,10 @@ public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
|
||||
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatchKt {
|
||||
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/navbar/PremiumNavbarTabPatchKt {
|
||||
public static final fun getPremiumNavbarTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package app.revanced.patches.pandora.ads
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.pandora.shared.constructUserDataFingerprint
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
val disableAudioAdsPatch = bytecodePatch(
|
||||
name = "Disable audio ads",
|
||||
) {
|
||||
compatibleWith("com.pandora.android")
|
||||
|
||||
execute {
|
||||
constructUserDataFingerprint.method.apply {
|
||||
// First match is "hasAudioAds".
|
||||
val hasAudioAdsStringIndex = constructUserDataFingerprint.stringMatches!!.first().index
|
||||
val moveResultIndex = indexOfFirstInstructionOrThrow(hasAudioAdsStringIndex, Opcode.MOVE_RESULT)
|
||||
val hasAudioAdsRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
moveResultIndex + 1,
|
||||
"const/4 v$hasAudioAdsRegister, 0"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package app.revanced.patches.pandora.misc
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.pandora.shared.constructUserDataFingerprint
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
val enableUnlimitedSkipsPatch = bytecodePatch(
|
||||
name = "Enable unlimited skips",
|
||||
) {
|
||||
compatibleWith("com.pandora.android")
|
||||
|
||||
execute {
|
||||
constructUserDataFingerprint.method.apply {
|
||||
// Last match is "skipLimitBehavior".
|
||||
val skipLimitBehaviorStringIndex = constructUserDataFingerprint.stringMatches!!.last().index
|
||||
val moveResultObjectIndex =
|
||||
indexOfFirstInstructionOrThrow(skipLimitBehaviorStringIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||
val skipLimitBehaviorRegister = getInstruction<OneRegisterInstruction>(moveResultObjectIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
moveResultObjectIndex + 1,
|
||||
"const-string v$skipLimitBehaviorRegister, \"unlimited\""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.pandora.shared
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val constructUserDataFingerprint = fingerprint {
|
||||
strings("hasAudioAds", "skipLimitBehavior")
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package app.revanced.patches.primevideo.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val enterServerInsertedAdBreakStateFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
parameters("Lcom/amazon/avod/fsm/Trigger;")
|
||||
returns("V")
|
||||
opcodes(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.CONST_4
|
||||
)
|
||||
custom { method, classDef ->
|
||||
method.name == "enter" && classDef.type == "Lcom/amazon/avod/media/ads/internal/state/ServerInsertedAdBreakState;"
|
||||
}
|
||||
}
|
||||
|
||||
internal val doTriggerFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED)
|
||||
returns("V")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
custom { method, classDef ->
|
||||
method.name == "doTrigger" && classDef.type == "Lcom/amazon/avod/fsm/StateBase;"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.patches.primevideo.ads
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.primevideo.misc.extension.sharedExtensionPatch
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
val skipAdsPatch = bytecodePatch(
|
||||
name = "Skip ads",
|
||||
description = "Automatically skips video stream ads.",
|
||||
) {
|
||||
compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.403.257"))
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
// Skip all the logic in ServerInsertedAdBreakState.enter(), which plays all the ad clips in this
|
||||
// ad break. Instead, force the video player to seek over the entire break and reset the state machine.
|
||||
execute {
|
||||
// Force doTrigger() access to public so we can call it from our extension.
|
||||
doTriggerFingerprint.method.accessFlags = AccessFlags.PUBLIC.value;
|
||||
|
||||
val getPlayerIndex = enterServerInsertedAdBreakStateFingerprint.patternMatch!!.startIndex
|
||||
enterServerInsertedAdBreakStateFingerprint.method.apply {
|
||||
// Get register that stores VideoPlayer:
|
||||
// invoke-virtual ->getPrimaryPlayer()
|
||||
// move-result-object { playerRegister }
|
||||
val playerRegister = getInstruction<OneRegisterInstruction>(getPlayerIndex + 1).registerA
|
||||
|
||||
// Reuse the params from the original method:
|
||||
// p0 = ServerInsertedAdBreakState
|
||||
// p1 = AdBreakTrigger
|
||||
addInstructions(
|
||||
getPlayerIndex + 2,
|
||||
"""
|
||||
invoke-static { p0, p1, v$playerRegister }, Lapp/revanced/extension/primevideo/ads/SkipAdsPatch;->enterServerInsertedAdBreakState(Lcom/amazon/avod/media/ads/internal/state/ServerInsertedAdBreakState;Lcom/amazon/avod/media/ads/internal/state/AdBreakTrigger;Lcom/amazon/avod/media/playback/VideoPlayer;)V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package app.revanced.patches.primevideo.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||
|
||||
val sharedExtensionPatch = sharedExtensionPatch("primevideo", applicationInitHook)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.primevideo.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
|
||||
internal val applicationInitHook = extensionHook {
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.endsWith("/SplashScreenActivity;")
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,12 @@ package app.revanced.patches.spotify.misc
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
|
||||
internal val accountAttributeFingerprint = fingerprint {
|
||||
custom { _, classDef ->
|
||||
@@ -15,7 +19,7 @@ internal val accountAttributeFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val productStateProtoFingerprint = fingerprint {
|
||||
internal val productStateProtoGetMapFingerprint = fingerprint {
|
||||
returns("Ljava/util/Map;")
|
||||
custom { _, classDef ->
|
||||
classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
||||
@@ -56,16 +60,40 @@ internal val readPlayerOptionOverridesFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
internal val homeSectionFingerprint = fingerprint {
|
||||
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
|
||||
}
|
||||
|
||||
internal val protobufListsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
custom { method, _ -> method.name == "emptyProtobufList" }
|
||||
}
|
||||
|
||||
internal val homeStructureFingerprint = fingerprint {
|
||||
opcodes(Opcode.IGET_OBJECT, Opcode.RETURN_OBJECT)
|
||||
custom { _, classDef -> classDef.endsWith("homeapi/proto/HomeStructure;") }
|
||||
internal val protobufListRemoveFingerprint = fingerprint {
|
||||
custom { method, _ -> method.name == "remove" }
|
||||
}
|
||||
|
||||
internal val homeSectionFingerprint = fingerprint {
|
||||
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
|
||||
}
|
||||
|
||||
internal val homeStructureGetSectionsFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("homeapi/proto/HomeStructure;") && method.indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.name == "sections_"
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun reactivexFunctionApplyWithClassInitFingerprint(className: String) = fingerprint {
|
||||
returns("Ljava/lang/Object;")
|
||||
parameters("Ljava/lang/Object;")
|
||||
custom { method, _ -> method.name == "apply" && method.indexOfFirstInstruction {
|
||||
opcode == Opcode.NEW_INSTANCE && getReference<TypeReference>()?.type?.endsWith(className) == true
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal const val PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME = "FetchMessageRequest;"
|
||||
internal val pendragonJsonFetchMessageRequestFingerprint =
|
||||
reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME)
|
||||
|
||||
internal const val PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME = "FetchMessageListRequest;"
|
||||
internal val pendragonProtoFetchMessageListRequestFingerprint =
|
||||
reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME)
|
||||
|
||||
@@ -60,4 +60,4 @@ val spoofPackageInfoPatch = bytecodePatch(
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.revanced.patches.spotify.misc.privacy
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val shareCopyUrlFingerprint = fingerprint {
|
||||
returns("Ljava/lang/Object;")
|
||||
parameters("Ljava/lang/Object;")
|
||||
strings("clipboard", "Spotify Link")
|
||||
custom { method, _ ->
|
||||
method.name == "invokeSuspend"
|
||||
}
|
||||
}
|
||||
|
||||
internal val shareCopyUrlLegacyFingerprint = fingerprint {
|
||||
returns("Ljava/lang/Object;")
|
||||
parameters("Ljava/lang/Object;")
|
||||
strings("clipboard", "createNewSession failed")
|
||||
custom { method, _ ->
|
||||
method.name == "apply"
|
||||
}
|
||||
}
|
||||
|
||||
internal val formatAndroidShareSheetUrlFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters("L", "Ljava/lang/String;")
|
||||
literal {
|
||||
'\n'.code.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
internal val formatAndroidShareSheetUrlLegacyFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;")
|
||||
literal {
|
||||
'\n'.code.toLong()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package app.revanced.patches.spotify.misc.privacy
|
||||
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
|
||||
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/spotify/misc/privacy/SanitizeSharingLinksPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val sanitizeSharingLinksPatch = bytecodePatch(
|
||||
name = "Sanitize sharing links",
|
||||
description = "Removes the tracking query parameters from links before they are shared.",
|
||||
) {
|
||||
compatibleWith("com.spotify.music")
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
execute {
|
||||
val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;"
|
||||
|
||||
val copyFingerprint = if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
||||
shareCopyUrlLegacyFingerprint
|
||||
} else {
|
||||
shareCopyUrlFingerprint
|
||||
}
|
||||
|
||||
copyFingerprint.method.apply {
|
||||
val newPlainTextInvokeIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "newPlainText"
|
||||
}
|
||||
val register = getInstruction<FiveRegisterInstruction>(newPlainTextInvokeIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
newPlainTextInvokeIndex,
|
||||
"""
|
||||
invoke-static { v$register }, $extensionMethodDescriptor
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// Android native share sheet is used for all other quick share types (X, WhatsApp, etc).
|
||||
val shareUrlParameter : String
|
||||
val shareSheetFingerprint : Fingerprint
|
||||
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
||||
shareSheetFingerprint = formatAndroidShareSheetUrlLegacyFingerprint
|
||||
shareUrlParameter = "p2"
|
||||
} else {
|
||||
shareSheetFingerprint = formatAndroidShareSheetUrlFingerprint
|
||||
shareUrlParameter = "p1"
|
||||
}
|
||||
|
||||
shareSheetFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { $shareUrlParameter }, $extensionMethodDescriptor
|
||||
move-result-object $shareUrlParameter
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -14,4 +14,4 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
|
||||
method.name == "onCreate" && (classDef.type == SPOTIFY_MAIN_ACTIVITY
|
||||
|| classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.util.InstructionUtils.Companion.branchOpcodes
|
||||
import app.revanced.util.InstructionUtils.Companion.returnOpcodes
|
||||
import app.revanced.util.InstructionUtils.Companion.writeOpcodes
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.Opcode.*
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
@@ -169,6 +170,15 @@ internal val Instruction.isBranchInstruction: Boolean
|
||||
internal val Instruction.isReturnInstruction: Boolean
|
||||
get() = this.opcode in returnOpcodes
|
||||
|
||||
/**
|
||||
* Adds public [AccessFlags] and removes private and protected flags (if present).
|
||||
*/
|
||||
internal fun Int.toPublicAccessFlags() : Int {
|
||||
return this.or(AccessFlags.PUBLIC.value)
|
||||
.and(AccessFlags.PROTECTED.value.inv())
|
||||
.and(AccessFlags.PRIVATE.value.inv())
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
|
||||
*
|
||||
@@ -494,7 +504,7 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): I
|
||||
* @see indexOfFirstInstructionOrThrow
|
||||
*/
|
||||
fun Method.indexOfFirstInstruction(startIndex: Int = 0, filter: Instruction.() -> Boolean): Int {
|
||||
var instructions = this.implementation!!.instructions
|
||||
var instructions = this.implementation?.instructions ?: return -1
|
||||
if (startIndex != 0) {
|
||||
instructions = instructions.drop(startIndex)
|
||||
}
|
||||
@@ -560,7 +570,7 @@ fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode
|
||||
* @see indexOfFirstInstructionReversedOrThrow
|
||||
*/
|
||||
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, filter: Instruction.() -> Boolean): Int {
|
||||
var instructions = this.implementation!!.instructions
|
||||
var instructions = this.implementation?.instructions ?: return -1
|
||||
if (startIndex != null) {
|
||||
instructions = instructions.take(startIndex + 1)
|
||||
}
|
||||
|
||||
@@ -460,15 +460,29 @@ Säädä äänenvoimakkuutta pyyhkäisemällä pystysuoraan näytön oikealta pu
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_on">Automaattinen kirkkaus otetaan käyttöön pyyhkäisemällä alhaisimpaan arvoon</string>
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_off">Pienimpään arvoon alas pyyhkäiseminen ei ota käyttöön automaattista kirkkautta</string>
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_overlay_text">Automaattinen</string>
|
||||
<string name="revanced_swipe_overlay_timeout_title">Pyyhkäisyikkunan aikakatkaisu</string>
|
||||
<string name="revanced_swipe_overlay_timeout_title">Pyyhkäisypeittokuvan aikakatkaisu</string>
|
||||
<string name="revanced_swipe_overlay_timeout_summary">Kuinka monta millisekuntia ikkuna on näkyvissä</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_title">Pyyhkäisypeittokuvan taustan läpinäkymättömyys</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_summary">Läpinäkymättömyysarvo 0–100 välillä</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Pyyhkäisyn läpinäkymättömyyden on oltava välillä 0–100</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Pyyhkäisypeittokuvan läpinäkymättömyyden tulee olla 0–100 välillä</string>
|
||||
<string name="revanced_swipe_overlay_progress_color_title">Pyyhkäisypeittokuvan edistymispalkin väri</string>
|
||||
<string name="revanced_swipe_overlay_progress_color_summary">Äänenvoimakkuuden ja kirkkauden säätimien edistymispalkin väri</string>
|
||||
<string name="revanced_swipe_overlay_progress_color_invalid_toast">Virheellinen edistymispalkin väri</string>
|
||||
<string name="revanced_swipe_text_overlay_size_title">Pyyhkäisypeittokuvan tekstin koko</string>
|
||||
<string name="revanced_swipe_text_overlay_size_summary">Pyyhkäisypeittokuvan tekstin koko 1–30 välillä</string>
|
||||
<string name="revanced_swipe_text_overlay_size_invalid_toast">Tekstin koon tulee olla 1–30 välillä</string>
|
||||
<string name="revanced_swipe_threshold_title">Pyyhkäisyn kynnysraja</string>
|
||||
<string name="revanced_swipe_threshold_summary">Pyyhkäisyä varten tarvittavan kynnyksen määrä</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_title">Äänenvoimakkuuden pyyhkäisyn herkkyys</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_summary">Kuinka paljon äänenvoimakkuus muuttuu pyyhkäisyä kohden</string>
|
||||
<string name="revanced_swipe_overlay_style_title">Pyyhkäisypeittokuvan tyyli</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_1">Vaakasuuntainen peittokuva</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_2">Vaakasuuntainen peittokuva (minimaalinen – ylhäällä)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_3">Vaakasuuntainen peittokuva (minimaalinen – keskellä)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_4">Pyöreä peittokuva</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_5">Pyöreä peittokuva (minimaalinen)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_6">Pystysuuntainen peittokuva</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_7">Pystysuuntainen peittokuva (minimaalinen)</string>
|
||||
<string name="revanced_swipe_change_video_title">Ota videon vaihto pyyhkäisemällä käyttöön</string>
|
||||
<string name="revanced_swipe_change_video_summary_on">Pyyhkäisemällä kokoruututilassa siirrytään seuraavaan/edelliseen videoon</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">Pyyhkäisemällä kokoruututilassa ei siirrytä seuraavaan/edelliseen videoon</string>
|
||||
@@ -802,7 +816,7 @@ Asetukset → Toisto → Toista seuraava video automaattisesti"</string>
|
||||
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
|
||||
<string name="revanced_player_overlay_opacity_title">Soittimen peittokuvan läpinäkymättömyys</string>
|
||||
<string name="revanced_player_overlay_opacity_summary">Läpinäkymättömyysarvo välillä 0–100, jossa 0 on läpinäkyvä</string>
|
||||
<string name="revanced_player_overlay_opacity_invalid_toast">Soittimen peittokuvan läpinäkymättömyyden on oltava välillä 0–100</string>
|
||||
<string name="revanced_player_overlay_opacity_invalid_toast">Soittimen peittokuvan läpinäkymättömyyden tulee olla 0–100 välillä</string>
|
||||
</patch>
|
||||
<patch id="layout.returnyoutubedislike.returnYouTubeDislikePatch">
|
||||
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
|
||||
@@ -903,7 +917,7 @@ Tämä ominaisuus toimii parhaiten, kun videon laatu on 720p tai alhaisempi ja k
|
||||
<string name="revanced_sb_enable_create_segment_sum_off">Luo uusi osio -painiketta ei näytetä</string>
|
||||
<string name="revanced_sb_general_adjusting">Uuden osion ajoituksen säätö</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">Kuinka monta millisekuntia ajansäätöpainikkeet liikkuvat uusia osioita luotaessa</string>
|
||||
<string name="revanced_sb_general_adjusting_invalid">Arvon on oltava positiivinen luku</string>
|
||||
<string name="revanced_sb_general_adjusting_invalid">Arvon tulee olla positiivinen luku</string>
|
||||
<string name="revanced_sb_guidelines_preference_title">Näytä ohjeet</string>
|
||||
<string name="revanced_sb_guidelines_preference_sum">Ohjeet sisältävät sääntöjä ja vinkkejä uusien osioiden luomiseen</string>
|
||||
<string name="revanced_sb_guidelines_popup_title">Noudata ohjeita</string>
|
||||
@@ -1201,10 +1215,10 @@ Pyyhkäise laajentaaksesi tai sulkeaksesi"</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_off">Eteenpäin ja taaksepäin näytetään</string>
|
||||
<string name="revanced_miniplayer_width_dip_title">Aloituskoko</string>
|
||||
<string name="revanced_miniplayer_width_dip_summary">Alkuperäinen näyttökoko pikseleinä</string>
|
||||
<string name="revanced_miniplayer_width_dip_invalid_toast">Pikselikoon on oltava välillä %1$s ja %2$s</string>
|
||||
<string name="revanced_miniplayer_width_dip_invalid_toast">Pikselikoon tulee olla %1$s ja %2$s välillä</string>
|
||||
<string name="revanced_miniplayer_opacity_title">Peittokuvan läpinäkymättömyys</string>
|
||||
<string name="revanced_miniplayer_opacity_summary">Läpinäkymättömyysarvo välillä 0–100, jossa 0 on läpinäkyvä</string>
|
||||
<string name="revanced_miniplayer_opacity_invalid_toast">Minisoittimen peittokuvan läpinäkymättömyyden on oltava välillä 0–100</string>
|
||||
<string name="revanced_miniplayer_opacity_invalid_toast">Minisoittimen peittokuvan läpinäkymättömyyden tulee olla 0–100 välillä</string>
|
||||
</patch>
|
||||
<patch id="layout.theme.themePatch">
|
||||
<string name="revanced_gradient_loading_screen_title">Ota liukuvärillinen latausruutu käyttöön</string>
|
||||
@@ -1295,6 +1309,7 @@ Tämä voi avata korkealaatuisemmat videot"</string>
|
||||
<string name="microg_settings_summary">GmsCoren asetukset</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
<string name="microg_offline_account_login_error">Jos olet äskettäin muuttanut tilisi kirjautumistietoja, poista ja asenna MicroG uudelleen.</string>
|
||||
</patch>
|
||||
<patch id="misc.links.bypassURLRedirectsPatch">
|
||||
<string name="revanced_bypass_url_redirects_title">Ohita URL-osoitteen uudelleenohjaukset</string>
|
||||
@@ -1352,7 +1367,7 @@ Tämä voi avata korkealaatuisemmat videot"</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Omaa nopeusvalikkoa ei näytetä</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Omat toistonopeudet</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Lisää tai muuta omia toistonopeuksia</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Omien nopeuksien on oltava alle %s</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Omien nopeuksien tulee olla alle %s</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">Virheelliset omat toistonopeudet</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">Automaattinen</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">Oma napauta ja pidä pohjassa -nopeus</string>
|
||||
|
||||
@@ -64,7 +64,7 @@ Second \"item\" text"</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>
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"MicroG GmsCore はバックグラウンドで実行するための権限を持っていません。
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"MicroG GmsCore はバックグラウンドで動くための権限を持っていません。
|
||||
|
||||
下記ウェブサイト「Don't kill my app」の携帯電話メーカー別のガイドに従い、MicroG GmsCore に対するデバイスの設定を変更してください。
|
||||
|
||||
@@ -80,7 +80,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_screen_00_about_title">このアプリについて</string>
|
||||
<string name="revanced_settings_screen_00_about_title">ReVanced について</string>
|
||||
<string name="revanced_settings_screen_01_ads_title">広告</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">代替サムネイル</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">フィード</string>
|
||||
@@ -854,7 +854,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">API 利用不可時にトーストを表示</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">Return YouTube Dislike が利用できない場合、トースト ポップアップが表示されます</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">Return YouTube Dislike が利用できない場合でもトースト ポップアップは表示されません</string>
|
||||
<string name="revanced_ryd_about">このアプリについて</string>
|
||||
<string name="revanced_ryd_about">Return YouTube Dislike について</string>
|
||||
<string name="revanced_ryd_attribution_summary">このデータはReturn YouTube Dislike APIによって提供されています。詳細はここをタップしてください</string>
|
||||
<!-- Statistic strings are shown in the settings only when ReVanced debug mode is enabled. Typical users will never see these. -->
|
||||
<string name="revanced_ryd_statistics_category_title">このデバイスでのReturnYouTubeDislike API 統計情報</string>
|
||||
@@ -1087,7 +1087,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_sb_color_invalid">色の値が無効です</string>
|
||||
<string name="revanced_sb_reset_color">色をリセット</string>
|
||||
<string name="revanced_sb_reset">リセット</string>
|
||||
<string name="revanced_sb_about">このアプリについて</string>
|
||||
<string name="revanced_sb_about">SponsorBlock について</string>
|
||||
<string name="revanced_sb_about_api_sum">SponsorBlock APIによって提供されるデータです。詳細はこちらをタップしてください。</string>
|
||||
</patch>
|
||||
<patch id="layout.formfactor.changeFormFactorPatch">
|
||||
@@ -1311,7 +1311,7 @@ Automotive レイアウト
|
||||
<string name="microg_settings_summary">GmsCore の設定</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
<string name="microg_offline_account_login_error">最近アカウントのログイン情報を変更した場合は、MicroGをアンインストールして再インストールしてください。</string>
|
||||
<string name="microg_offline_account_login_error">最近アカウントのログイン情報を変更した場合は、MicroG をアンインストールして再インストールしてください。</string>
|
||||
</patch>
|
||||
<patch id="misc.links.bypassURLRedirectsPatch">
|
||||
<string name="revanced_bypass_url_redirects_title">URL リダイレクトを回避する</string>
|
||||
|
||||
@@ -712,8 +712,8 @@ Da biste prikazali meni „Audio snimak”, promenite opciju „Lažirani video
|
||||
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_on">Dugmad u plejeru pri pauzi su skrivena</string>
|
||||
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_off">Dugmad u plejeru pri pauzi su prikazana</string>
|
||||
<string name="revanced_hide_shorts_shop_button_title">Sakrij dugme „Prodavnica”</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_on">Dugme „Kupovina” je skriveno</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_off">Dugme „Kupovina” je prikazano</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_on">Dugme „Prodavnica” je skriveno</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_off">Dugme „Prodavnica” je prikazano</string>
|
||||
<string name="revanced_hide_shorts_super_thanks_button_title">Sakrij dugme za kupovinu „Superhvala”</string>
|
||||
<string name="revanced_hide_shorts_super_thanks_button_summary_on">Dugme „Superhvala” je skriveno</string>
|
||||
<string name="revanced_hide_shorts_super_thanks_button_summary_off">Dugme „Superhvala” je prikazano</string>
|
||||
@@ -733,8 +733,8 @@ Da biste prikazali meni „Audio snimak”, promenite opciju „Lažirani video
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">Dugme „Predstojeće” je skriveno</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">Dugme „Predstojeće” je prikazano</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_title">Sakrij dugme „Zeleni ekran”</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_on">Dugme „Green Screen” je skriveno</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_off">Dugme „Green Screen” je prikazano</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_on">Dugme „Zeleni ekran” je skriveno</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_off">Dugme „Zeleni ekran” je prikazano</string>
|
||||
<string name="revanced_hide_shorts_hashtag_button_title">Sakrij dugme heš-oznake</string>
|
||||
<string name="revanced_hide_shorts_hashtag_button_summary_on">Dugme heš-oznake je skriveno</string>
|
||||
<string name="revanced_hide_shorts_hashtag_button_summary_off">Dugme heš-oznake je prikazano</string>
|
||||
|
||||
@@ -712,8 +712,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_on">Дугмад у плејеру при паузи су скривена</string>
|
||||
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_off">Дугмад у плејеру при паузи су приказана</string>
|
||||
<string name="revanced_hide_shorts_shop_button_title">Сакриј дугме „Продавница”</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_on">Дугме „Куповина” је скривено</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_off">Дугме „Куповина” је приказано</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_on">Дугме „Продавница” је скривено</string>
|
||||
<string name="revanced_hide_shorts_shop_button_summary_off">Дугме „Продавница” је приказано</string>
|
||||
<string name="revanced_hide_shorts_super_thanks_button_title">Сакриј дугме за куповину „Суперхвала”</string>
|
||||
<string name="revanced_hide_shorts_super_thanks_button_summary_on">Дугме „Суперхвала” је скривено</string>
|
||||
<string name="revanced_hide_shorts_super_thanks_button_summary_off">Дугме „Суперхвала” је приказано</string>
|
||||
@@ -733,8 +733,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">Дугме „Предстојеће” је скривено</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">Дугме „Предстојеће” је приказано</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_title">Сакриј дугме „Зелени екран”</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_on">Дугме „Green Screen” је скривено</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_off">Дугме „Green Screen” је приказано</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_on">Дугме „Зелени екран” је скривено</string>
|
||||
<string name="revanced_hide_shorts_green_screen_button_summary_off">Дугме „Зелени екран” је приказано</string>
|
||||
<string name="revanced_hide_shorts_hashtag_button_title">Сакриј дугме хеш-ознаке</string>
|
||||
<string name="revanced_hide_shorts_hashtag_button_summary_on">Дугме хеш-ознаке је скривено</string>
|
||||
<string name="revanced_hide_shorts_hashtag_button_summary_off">Дугме хеш-ознаке је приказано</string>
|
||||
|
||||
@@ -1311,7 +1311,7 @@ Second \"item\" text"</string>
|
||||
<string name="microg_settings_summary">Відкрити GmsCore для налаштування та входу в обліковий запис Google</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
<string name="microg_offline_account_login_error">Якщо ви нещодавно змінили дані для входу у свій обліковий запис, видаліть і повторно встановіть MicroG.</string>
|
||||
<string name="microg_offline_account_login_error">Якщо Ви нещодавно змінили дані для входу у свій обліковий запис, видаліть і повторно встановіть MicroG.</string>
|
||||
</patch>
|
||||
<patch id="misc.links.bypassURLRedirectsPatch">
|
||||
<string name="revanced_bypass_url_redirects_title">Обхід URL переадресацій</string>
|
||||
|
||||
@@ -24,7 +24,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_failed_title">Kiểm tra thất bại</string>
|
||||
<string name="revanced_check_environment_dialog_open_official_source_button">Mở trang web chính thức</string>
|
||||
<string name="revanced_check_environment_dialog_ignore_button">Bỏ qua</string>
|
||||
<string name="revanced_check_environment_failed_message"><h5>Ứng dụng này xem ra không phải do bạn tự vá.</h5><br>Ứng dụng này có thể không hoạt động chính xác, <b>tiềm ẩn rủi ro hoặc thậm chí gây nguy hiểm khi sử dụng</b>.<br><br>Những kiểm tra này ngụ ý rằng ứng dụng được vá sẵn hoặc lấy từ nguồn khác;<br><br><small>%1$s</small><br>Chúng tôi khuyến nghị bạn nên <b>gỡ cài đặt ứng này và tự vá lại</b> để đảm bảo bạn đang dùng một ứng dụng an toàn và hợp lệ.<p><br>Cảnh báo này sẽ chỉ hiện hai lần, hãy cân nhắc trước khi bỏ qua.</string>
|
||||
<string name="revanced_check_environment_failed_message"><h5>Ứng dụng này xem ra không phải do bạn tự vá.</h5><br>Ứng dụng này có thể không hoạt động chính xác, <b>tiềm ẩn rủi ro hoặc thậm chí gây nguy hiểm khi sử dụng</b>.<br><br>Những kiểm tra dưới đây cho thấy rằng ứng dụng được vá sẵn hoặc lấy từ nguồn khác;<br><br><small>%1$s</small><br>Chúng tôi khuyến nghị bạn nên <b>gỡ cài đặt ứng này và tự vá lại</b> để đảm bảo bạn đang dùng một ứng dụng an toàn và hợp lệ.<p><br>Cảnh báo này sẽ chỉ hiện hai lần, hãy cân nhắc trước khi bỏ qua.</string>
|
||||
<string name="revanced_check_environment_not_same_patching_device">Đã vá trên một thiết bị khác</string>
|
||||
<string name="revanced_check_environment_manager_not_expected_installer">Không được cài đặt bởi ReVanced Manager</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time">Đã vá hơn 10 phút trước</string>
|
||||
@@ -315,7 +315,7 @@ Nếu cài đặt này được bật và Doodle đang hiển thị tại khu v
|
||||
<string name="revanced_hide_keyword_content_search_title">Ẩn kết quả tìm kiếm bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_search_summary_on">Kết quả tìm kiếm đã được lọc bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_search_summary_off">Kết quả tìm kiếm không được lọc bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_title">Ẩn video đăng ký bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_title">Ẩn video kênh đăng ký bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_summary_on">Video ở thẻ đăng ký đã được lọc bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_summary_off">Video ở thẻ đăng ký không được lọc bằng từ khóa</string>
|
||||
<string name="revanced_hide_keyword_content_phrases_title">Từ khóa để ẩn</string>
|
||||
@@ -399,7 +399,7 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
|
||||
<patch id="interaction.copyvideourl.copyVideoUrlResourcePatch">
|
||||
<string name="revanced_share_copy_url_success">Đã chép URL vào bảng nhớ tạm</string>
|
||||
<string name="revanced_share_copy_url_timestamp_success">Đã chép URL với dấu thời gian</string>
|
||||
<string name="revanced_copy_video_url_title">Hiện nút sao chép url video</string>
|
||||
<string name="revanced_copy_video_url_title">Hiện nút sao chép URL video</string>
|
||||
<string name="revanced_copy_video_url_summary_on">Nút được hiển thị. Chạm để sao chép video URL. Chạm và giữ để sao chép với dấu thời gian</string>
|
||||
<string name="revanced_copy_video_url_summary_off">Nút không được hiển thị</string>
|
||||
<string name="revanced_copy_video_url_timestamp_title">Hiện nút sao chép URL với dấu thời gian</string>
|
||||
@@ -416,7 +416,7 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
|
||||
<string name="revanced_external_downloader_screen_title">Tải xuống bên ngoài</string>
|
||||
<string name="revanced_external_downloader_screen_summary">Các thiết lập trình tải xuống bên ngoài</string>
|
||||
<string name="revanced_external_downloader_title">Hiện nút tải xuống bên ngoài</string>
|
||||
<string name="revanced_external_downloader_summary_on">Nút tải xuống trong trình phát được hiển thị</string>
|
||||
<string name="revanced_external_downloader_summary_on">Nút tải xuống trong trình phát đã được hiển thị</string>
|
||||
<string name="revanced_external_downloader_summary_off">Nút tải xuống trong trình phát không được hiển thị</string>
|
||||
<!-- 'download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title' -->
|
||||
<string name="revanced_external_downloader_action_button_title">Thay thế nút hành động Tải xuống</string>
|
||||
@@ -446,12 +446,12 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
|
||||
<string name="revanced_swipe_volume_summary_on">"Đã bật vuốt âm lượng toàn màn hình
|
||||
|
||||
Điều chỉnh âm lượng bằng cách vuốt dọc ở bên phải màn hình"</string>
|
||||
<string name="revanced_swipe_volume_summary_off">Vuốt âm lượng được tắt</string>
|
||||
<string name="revanced_swipe_press_to_engage_title">Bật cử chỉ nhấn-để-vuốt</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_on">Nhấn-để-vuốt đã bật</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_off">Nhấn-để-vuốt đã tắt</string>
|
||||
<string name="revanced_swipe_volume_summary_off">Vuốt âm lượng toàn màn hình đã tắt</string>
|
||||
<string name="revanced_swipe_press_to_engage_title">Bật cử chỉ nhấn giữ để vuốt</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_on">Nhấn giữ để vuốt đã bật</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_off">Nhấn giữ để vuốt đã tắt</string>
|
||||
<string name="revanced_swipe_haptic_feedback_title">Bật phản hồi xúc giác</string>
|
||||
<string name="revanced_swipe_haptic_feedback_summary_on">Phản hồi xúc giác đã bật</string>
|
||||
<string name="revanced_swipe_haptic_feedback_summary_on">Phản hồi xúc giác đã được bật</string>
|
||||
<string name="revanced_swipe_haptic_feedback_summary_off">Phản hồi xúc giác đã tắt</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_title">Lưu và khôi phục độ sáng</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_summary_on">Lưu và khôi phục độ sáng khi thoát hoặc vào toàn màn hình</string>
|
||||
@@ -496,8 +496,8 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
|
||||
<string name="revanced_hide_buttons_screen_title">Các nút hành động</string>
|
||||
<string name="revanced_hide_buttons_screen_summary">Ẩn hoặc hiện nút dưới video</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_title">Tắt hiệu ứng phát sáng nút Thích và Đăng ký</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_on">Nút Thích và Đăng ký sẽ không phát sáng khi được đề cập đến</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_off">Nút Thích và Đăng ký sẽ phát sáng khi được đề cập đến</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_on">Nút Thích và Đăng ký sẽ không phát sáng khi được tương tác</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_off">Nút Thích và Đăng ký sẽ phát sáng khi được tương tác</string>
|
||||
<string name="revanced_hide_like_dislike_button_title">Ẩn Thích và Không thích</string>
|
||||
<string name="revanced_hide_like_dislike_button_summary_on">Các nút Thích và Không thích đã bị ẩn</string>
|
||||
<string name="revanced_hide_like_dislike_button_summary_off">Các nút Thích và Không thích được hiển thị</string>
|
||||
@@ -525,8 +525,8 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
|
||||
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
|
||||
Button only shows if the user ip is from specific region such as the USA or EU. -->
|
||||
<string name="revanced_hide_ask_button_title">Ẩn Hỏi</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">Nút Hỏi đã bị ẩn</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">Nút Hỏi được hiển thị</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">Nút hỏi đã bị ẩn</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">Nút hỏi được hiển thị</string>
|
||||
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_clip_button_title">Ẩn Tạo đoạn video</string>
|
||||
<string name="revanced_hide_clip_button_summary_on">Nút tạo đoạn video đã bị ẩn</string>
|
||||
@@ -538,26 +538,26 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.navigation.navigationButtonsPatch">
|
||||
<string name="revanced_navigation_buttons_screen_title">Các nút điều hướng</string>
|
||||
<string name="revanced_navigation_buttons_screen_summary">Ẩn hoặc hiện các nút ở thanh điều hướng</string>
|
||||
<string name="revanced_navigation_buttons_screen_summary">Ẩn hoặc thay đổi các nút ở thanh điều hướng</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the tab. -->
|
||||
<string name="revanced_hide_home_button_title">Ẩn Trang chính</string>
|
||||
<string name="revanced_hide_home_button_summary_on">Nút trang chính đã bị ẩn</string>
|
||||
<string name="revanced_hide_home_button_summary_off">Nút trang chính được hiển thị</string>
|
||||
<string name="revanced_hide_home_button_title">Ẩn Trang chủ</string>
|
||||
<string name="revanced_hide_home_button_summary_on">Nút trang chủ đã bị ẩn</string>
|
||||
<string name="revanced_hide_home_button_summary_off">Nút trang chủ được hiển thị</string>
|
||||
<!-- 'Shorts' should be translated using the same localized wording YouTube displays the tab. -->
|
||||
<string name="revanced_hide_shorts_button_title">Ẩn Shorts</string>
|
||||
<string name="revanced_hide_shorts_button_summary_on">Nút Shorts đã bị ẩn</string>
|
||||
<string name="revanced_hide_shorts_button_summary_off">Nút Shorts được hiển thị</string>
|
||||
<!-- The Create button has no display name. Translate normally. -->
|
||||
<string name="revanced_hide_create_button_title">Ẩn Tạo mới</string>
|
||||
<string name="revanced_hide_create_button_title">Ẩn Tạo</string>
|
||||
<string name="revanced_hide_create_button_summary_on">Nút tạo đã bị ẩn</string>
|
||||
<string name="revanced_hide_create_button_summary_off">Nút tạo được hiển thị</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays the tab. -->
|
||||
<string name="revanced_hide_subscriptions_button_title">Ẩn Đăng ký</string>
|
||||
<string name="revanced_hide_subscriptions_button_summary_on">Nút đăng ký đã bị ẩn</string>
|
||||
<string name="revanced_hide_subscriptions_button_summary_off">Nút Đăng ký được hiển thị</string>
|
||||
<string name="revanced_hide_subscriptions_button_title">Ẩn Kênh đăng ký</string>
|
||||
<string name="revanced_hide_subscriptions_button_summary_on">Nút kênh đăng ký đã bị ẩn</string>
|
||||
<string name="revanced_hide_subscriptions_button_summary_off">Nút kênh đăng ký được hiển thị</string>
|
||||
<string name="revanced_hide_notifications_button_title">Ẩn Thông báo</string>
|
||||
<string name="revanced_hide_notifications_button_summary_on">Nút Thông báo đã bị ẩn</string>
|
||||
<string name="revanced_hide_notifications_button_summary_off">Nút Thông báo được hiển thị</string>
|
||||
<string name="revanced_hide_notifications_button_summary_on">Nút thông báo đã bị ẩn</string>
|
||||
<string name="revanced_hide_notifications_button_summary_off">Nút thông báo được hiển thị</string>
|
||||
<!-- 'Notifications' should be translated using the same localized wording YouTube displays the tab. -->
|
||||
<string name="revanced_switch_create_with_notifications_button_title">Chuyển vị nút Tạo với nút Thông báo</string>
|
||||
<string name="revanced_switch_create_with_notifications_button_summary_on">"Nút tạo được chuyển đổi với nút Thông báo
|
||||
@@ -577,7 +577,7 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_title">Vô hiệu hóa thanh điều hướng trong suốt ở chế độ sáng</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">Thanh điều hướng ở chế độ sáng không trong suốt</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_off">Thanh điều hướng ở chế độ sáng là đục hoặc trong mờ</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_title">Vô hiệu hoá thanh điều hướng trong mờ tối</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_title">Vô hiệu hoá thanh điều hướng trong chế độ tối</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">Thanh điều hướng ở chế độ tối không trong suốt</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_off">Thanh điều hướng ở chế độ tối là đục hoặc trong mờ</string>
|
||||
</patch>
|
||||
@@ -601,7 +601,7 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch
|
||||
<string name="revanced_hide_player_flyout_loop_video_summary_on">Trình đơn lặp video đã bị ẩn</string>
|
||||
<string name="revanced_hide_player_flyout_loop_video_summary_off">Trình đơn lặp video được hiển thị</string>
|
||||
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_ambient_mode_title">Ẩn chế độ môi trường</string>
|
||||
<string name="revanced_hide_player_flyout_ambient_mode_title">Ẩn Chế độ môi trường</string>
|
||||
<string name="revanced_hide_player_flyout_ambient_mode_summary_on">Trình đơn chế độ môi trường đã bị ẩn</string>
|
||||
<string name="revanced_hide_player_flyout_ambient_mode_summary_off">Trình đơn chế độ môi trường được hiển thị</string>
|
||||
<string name="revanced_hide_player_flyout_stable_volume_title">Ẩn Âm lượng ổn định</string>
|
||||
@@ -661,8 +661,8 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch
|
||||
<string name="revanced_hide_endscreen_cards_summary_off">Thẻ kết thúc màn hình được hiển thị</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.fullscreenambientmode.disableFullscreenAmbientModePatch">
|
||||
<string name="revanced_disable_fullscreen_ambient_mode_title">Tắt chế độ môi trường khi toàn màn hình</string>
|
||||
<string name="revanced_disable_fullscreen_ambient_mode_summary_on">Chế độ môi trường được tắt</string>
|
||||
<string name="revanced_disable_fullscreen_ambient_mode_title">Tắt Chế độ môi trường khi toàn màn hình</string>
|
||||
<string name="revanced_disable_fullscreen_ambient_mode_summary_on">Chế độ môi trường đã tắt</string>
|
||||
<string name="revanced_disable_fullscreen_ambient_mode_summary_off">Chế độ môi trường được bật</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.infocards.hideInfocardsResourcePatch">
|
||||
@@ -687,12 +687,12 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch
|
||||
<string name="revanced_shorts_player_screen_title">Trình phát Shorts</string>
|
||||
<string name="revanced_shorts_player_screen_summary">Ẩn hoặc hiện các thành phần trong trình phát Shorts</string>
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Ẩn Shorts trong bảng tin trang chính</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Ẩn trong nguồn cấp dữ liệu trang chủ và video liên quan</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Hiện trong nguồn cấp dữ liệu trang chủ và video liên quan</string>
|
||||
<string name="revanced_hide_shorts_home_title">Ẩn Shorts trong thẻ trang chủ</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Ẩn trong thẻ trang chủ và video liên quan</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Hiện trong thẻ trang chủ và video liên quan</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Ẩn Shorts trong bảng tin đăng ký</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Bị ẩn trong nguồn đăng ký</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Ẩn Shorts trong thẻ kênh đăng ký</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Bị ẩn trong thẻ kênh đăng ký</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Được hiện trong nguồn đăng ký</string>
|
||||
<string name="revanced_hide_shorts_search_title">Ẩn Shorts trong kết quả tìm kiếm</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Bị ẩn trong kết quả tìm kiếm</string>
|
||||
@@ -806,10 +806,10 @@ Cài đặt → Phát → Tự động phát video tiếp theo"</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.exitFullscreenPatch">
|
||||
<string name="revanced_exit_fullscreen_title">Thoát chế độ toàn màn hình khi kết thúc video</string>
|
||||
<string name="revanced_exit_fullscreen_entry_1">Đã tắt</string>
|
||||
<string name="revanced_exit_fullscreen_entry_2">Chân dung</string>
|
||||
<string name="revanced_exit_fullscreen_entry_3">Phong cảnh</string>
|
||||
<string name="revanced_exit_fullscreen_entry_4">Chân dung và phong cảnh</string>
|
||||
<string name="revanced_exit_fullscreen_entry_1">Tắt</string>
|
||||
<string name="revanced_exit_fullscreen_entry_2">Chế độ dọc</string>
|
||||
<string name="revanced_exit_fullscreen_entry_3">Chế độ ngang</string>
|
||||
<string name="revanced_exit_fullscreen_entry_4">Chế độ dọc và ngang</string>
|
||||
</patch>
|
||||
<patch id="layout.player.fullscreen.openVideosFullscreen">
|
||||
<string name="revanced_open_videos_fullscreen_portrait_title">Mở video ở chế độ toàn màn hình dọc</string>
|
||||
@@ -916,10 +916,10 @@ Tính năng này hoạt động tốt nhất với chất lượng video 720p tr
|
||||
<string name="revanced_sb_general_time_without_sum_off">Thời lượng đầy đủ của video được hiện</string>
|
||||
<string name="revanced_sb_create_segment_category">Tạo các phân đoạn mới</string>
|
||||
<string name="revanced_sb_enable_create_segment">Hiện nút Tạo phân đoạn mới</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_on">Nút tạo phân đoạn mới được hiển thị</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_on">Nút tạo phân đoạn mới đã được hiển thị</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_off">Nút tạo phân đoạn mới không được hiển thị</string>
|
||||
<string name="revanced_sb_general_adjusting">Điều chỉnh bước tua của phân đoạn mới</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">Số mili-giây của các nút điều chỉnh thay đổi khi tạo phân đoạn mới</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">Số mili-giây mà các nút điều chỉnh thời gian sẽ tua khi tạo phân đoạn mới</string>
|
||||
<string name="revanced_sb_general_adjusting_invalid">Giá trị phải là một số dương</string>
|
||||
<string name="revanced_sb_guidelines_preference_title">Xem hướng dẫn</string>
|
||||
<string name="revanced_sb_guidelines_preference_sum">Hướng dẫn bao gồm các quy tắc và mẹo về cách tạo phân đoạn mới</string>
|
||||
@@ -1174,9 +1174,9 @@ Giới hạn: Sử dụng nút quay lại trên thanh công cụ có thể khôn
|
||||
<string name="revanced_miniplayer_screen_title">Trình phát thu nhỏ</string>
|
||||
<string name="revanced_miniplayer_screen_summary">Thay đổi kiểu trình phát thu nhỏ trong ứng dụng</string>
|
||||
<string name="revanced_miniplayer_type_title">Loại trình phát thu nhỏ</string>
|
||||
<string name="revanced_miniplayer_type_entry_0">Đã tắt</string>
|
||||
<string name="revanced_miniplayer_type_entry_0">Tắt</string>
|
||||
<string name="revanced_miniplayer_type_entry_1">Mặc định</string>
|
||||
<string name="revanced_miniplayer_type_entry_2">Thu gọn</string>
|
||||
<string name="revanced_miniplayer_type_entry_2">Tối giản</string>
|
||||
<string name="revanced_miniplayer_type_entry_3">Máy tính bảng</string>
|
||||
<string name="revanced_miniplayer_type_entry_4">Hiện đại 1</string>
|
||||
<string name="revanced_miniplayer_type_entry_5">Hiện đại 2</string>
|
||||
@@ -1185,22 +1185,22 @@ Giới hạn: Sử dụng nút quay lại trên thanh công cụ có thể khôn
|
||||
<string name="revanced_miniplayer_rounded_corners_title">Bật góc bo tròn</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_on">Góc được bo tròn</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_off">Góc vuông</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_title">Bật nhấp đôi và chụm để thay đổi kích thước</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_on">"Thao tác nhấn đúp và vuốt để thay đổi kích thước được bật
|
||||
<string name="revanced_miniplayer_double_tap_action_title">Bật nhấp đúp và chụm để thay đổi kích thước</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_on">"Thao tác nhấn đúp và chụm để thay đổi kích thước đã được bật
|
||||
|
||||
• Nhấn đúp để tăng kích thước trình phát nhỏ
|
||||
• Nhấn đúp để tăng kích thước trình phát thu nhỏ
|
||||
• Nhấn đúp lại để khôi phục kích thước ban đầu"</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_off">Chạm đôi và chụm để thay đổi kích thước được tắt</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_off">Chạm đôi và chụm để thay đổi kích thước đã tắt</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_title">Bật kéo và thả</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_on">"Kéo và thả được bật
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_on">"Kéo và thả đã được bật
|
||||
|
||||
Trình phát nhỏ có thể được kéo đến bất kỳ góc nào của màn hình"</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_off">Kéo và thả được tắt</string>
|
||||
Trình phát thu nhỏ có thể được kéo đến bất kỳ góc nào của màn hình"</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_off">Kéo và thả đã tắt</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_title">Bật cử chỉ kéo ngang</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_on">"Cử chỉ kéo ngang được bật
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_on">"Cử chỉ kéo ngang đã được bật
|
||||
|
||||
Trình phát nhỏ có thể được kéo ra khỏi màn hình sang trái hoặc phải"</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">Cử chỉ kéo ngang được tắt</string>
|
||||
Trình phát thu nhỏ có thể được kéo ra mép màn hình sang bên trái hoặc phải"</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">Cử chỉ kéo ngang đã tắt</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">Ẩn các nút lớp phủ</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Các nút lớp phủ đã bị ẩn</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Các nút lớp phủ được hiển thị</string>
|
||||
@@ -1212,15 +1212,15 @@ Vuốt để mở rộng hoặc đóng"</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_title">Ẩn văn bản phụ</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_on">Văn bản phụ đã bị ẩn</string>
|
||||
<string name="revanced_miniplayer_hide_subtext_summary_off">Văn bản phụ được hiển thị</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_title">Ẩn các nút bỏ quả đến tiếp và trước đó </string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_on">Các nút bỏ quả đến tiếp và trước đó đã bị ẩn</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_off">Các nút bỏ quả đến tiếp và trước đó được hiển thị</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_title">Ẩn các nút tua nhanh và tua lại</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_on">Các nút tua nhanh và tua lại đã bị ẩn</string>
|
||||
<string name="revanced_miniplayer_hide_rewind_forward_summary_off">Các nút tua nhanh và tua lại được hiển thị</string>
|
||||
<string name="revanced_miniplayer_width_dip_title">Kích thước ban đầu</string>
|
||||
<string name="revanced_miniplayer_width_dip_summary">Kích thước ban đầu trên màn hình, bằng pixel</string>
|
||||
<string name="revanced_miniplayer_width_dip_invalid_toast">Pixel phải nằm giữa %1$s và %2$s</string>
|
||||
<string name="revanced_miniplayer_opacity_title">Độ mờ lớp phủ</string>
|
||||
<string name="revanced_miniplayer_opacity_summary">Giá trị độ mờ của lớp phủ trình phát trong khoảng từ 0 đến 100, trong đó 0 là trong suốt</string>
|
||||
<string name="revanced_miniplayer_opacity_invalid_toast">Độ phủ mờ trình phát thu nhỏ phải nằm giữa 0-100</string>
|
||||
<string name="revanced_miniplayer_opacity_invalid_toast">Độ mờ lớp phủ trình phát thu nhỏ phải nằm trong khoảng từ 0 đến 100</string>
|
||||
</patch>
|
||||
<patch id="layout.theme.themePatch">
|
||||
<string name="revanced_gradient_loading_screen_title">Bật màn hình tải màu dốc</string>
|
||||
@@ -1292,9 +1292,9 @@ Nhấn vào đây để tìm hiểu thêm về DeArrow"</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Không hiện lại</string>
|
||||
</patch>
|
||||
<patch id="misc.autorepeat.autoRepeatPatch">
|
||||
<string name="revanced_auto_repeat_title">Bật tự phát lại</string>
|
||||
<string name="revanced_auto_repeat_summary_on">Tự phát lại được bật</string>
|
||||
<string name="revanced_auto_repeat_summary_off">Tự phát lại được tắt</string>
|
||||
<string name="revanced_auto_repeat_title">Bật tự phát lặp lại</string>
|
||||
<string name="revanced_auto_repeat_summary_on">Tự phát lặp lại đã được bật</string>
|
||||
<string name="revanced_auto_repeat_summary_off">Tự phát lặp lại đã tắt</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
<string name="revanced_spoof_device_dimensions_title">Giả mạo kích thước thiết bị</string>
|
||||
@@ -1325,7 +1325,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"</str
|
||||
</patch>
|
||||
<patch id="misc.privacy.removeTrackingQueryParameterPatch">
|
||||
<string name="revanced_remove_tracking_query_parameter_title">Loại bỏ tham số truy vấn theo dõi</string>
|
||||
<string name="revanced_remove_tracking_query_parameter_summary_on">Tham số truy vấn theo dõi được loại bỏ khỏi liên kết</string>
|
||||
<string name="revanced_remove_tracking_query_parameter_summary_on">Tham số truy vấn theo dõi đã bị loại bỏ khỏi liên kết</string>
|
||||
<string name="revanced_remove_tracking_query_parameter_summary_off">Tham số truy vấn theo dõi không được loại bỏ khỏi liên kết</string>
|
||||
</patch>
|
||||
<patch id="misc.zoomhaptics.zoomHapticsPatch">
|
||||
@@ -1373,7 +1373,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"</str
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">Tốc độ phát lại tùy chỉnh không hợp lệ</string>
|
||||
<string name="revanced_custom_playback_speeds_auto">Tự động</string>
|
||||
<string name="revanced_speed_tap_and_hold_title">Tốc độ chạm và giữ tùy chỉnh</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">Tốc độ phát lại giữa 0-8</string>
|
||||
<string name="revanced_speed_tap_and_hold_summary">Tốc độ phát từ 0 đến 8</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">Nhớ các thay đổi tốc độ phát</string>
|
||||
|
||||
Reference in New Issue
Block a user