Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(YouTube): Add in app option to select a preferred language for ReVanced specific text #4231

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.BooleanSetting;
import app.revanced.extension.shared.settings.preference.ReVancedAboutPreference;

Expand Down Expand Up @@ -360,7 +362,17 @@ public static Context getContext() {
}

public static void setContext(Context appContext) {
// Must initially set context as the language settings needs it.
context = appContext;

AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
if (language != AppLanguage.DEFAULT) {
// Create a new context with the desired language.
Configuration config = appContext.getResources().getConfiguration();
config.setLocale(language.getLocale());
context = appContext.createConfigurationContext(config);
}

// In some apps like TikTok, the Setting classes can load in weird orders due to cyclic class dependencies.
// Calling the regular printDebug method here can cause a Settings context null pointer exception,
// even though the context is already set before the call.
Expand Down Expand Up @@ -765,17 +777,17 @@ public static void setPreferenceTitlesToMultiLineIfNeeded(PreferenceGroup group)
return;
}

String deviceLanguage = Utils.getContext().getResources().getConfiguration().locale.getLanguage();
if (deviceLanguage.equals("en")) {
String revancedLocale = Utils.getContext().getResources().getConfiguration().locale.getLanguage();
if (revancedLocale.equals(Locale.ENGLISH.getLanguage())) {
return;
}

for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
Preference pref = group.getPreference(i);
pref.setSingleLineTitle(false);

if (pref instanceof PreferenceGroup) {
setPreferenceTitlesToMultiLineIfNeeded((PreferenceGroup) pref);
if (pref instanceof PreferenceGroup subGroup) {
setPreferenceTitlesToMultiLineIfNeeded(subGroup);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package app.revanced.extension.shared.spoof;
package app.revanced.extension.shared.settings;

import java.util.Locale;

public enum AudioStreamLanguage {
public enum AppLanguage {
/**
* The current app language.
*/
Expand Down Expand Up @@ -34,7 +34,7 @@ public enum AudioStreamLanguage {
GL,
GU,
HI,
HE, // App uses obsolete 'IW' and 'HE' is modern ISO code.
HE, // App uses obsolete 'IW' and not the modern 'HE' ISO code.
HR,
HU,
HY,
Expand Down Expand Up @@ -87,7 +87,7 @@ public enum AudioStreamLanguage {

private final String language;

AudioStreamLanguage() {
AppLanguage() {
language = name().toLowerCase(Locale.US);
}

Expand All @@ -103,4 +103,12 @@ public String getLanguage() {

return language;
}

public Locale getLocale() {
if (this == DEFAULT) {
return Locale.getDefault();
}

return Locale.forLanguageTag(language);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability;

import app.revanced.extension.shared.spoof.AudioStreamLanguage;
import app.revanced.extension.shared.spoof.ClientType;

/**
Expand All @@ -22,8 +21,10 @@ public class BaseSettings {

public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false);

public static final EnumSetting<AppLanguage> REVANCED_LANGUAGE = new EnumSetting<>("revanced_language", AppLanguage.DEFAULT, true, "revanced_language_user_dialog_message");

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<AudioStreamLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.requests.Route;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.spoof.AudioStreamLanguage;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.spoof.ClientType;

final class PlayerRoutes {
Expand Down Expand Up @@ -42,9 +42,9 @@ static String createInnertubeBody(ClientType clientType) {
// 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();
AudioStreamLanguage language = userSelectedClient == ClientType.ANDROID_VR_NO_AUTH
AppLanguage language = userSelectedClient == ClientType.ANDROID_VR_NO_AUTH
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get()
: AudioStreamLanguage.DEFAULT;
: AppLanguage.DEFAULT;

JSONObject client = new JSONObject();
client.put("hl", language.getLanguage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ public static void endOfVideoReached() {
Logger.printDebug(() -> "Fullscreen button is null, cannot click");
} else {
Logger.printDebug(() -> "Clicking fullscreen button");
final boolean soundEffectsEnabled = button.isSoundEffectsEnabled();
button.setSoundEffectsEnabled(false);
button.performClick();
button.setSoundEffectsEnabled(soundEffectsEnabled);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.preference.PreferenceFragment;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
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.youtube.ThemeHelper;
import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFragment;
import app.revanced.extension.youtube.settings.preference.ReturnYouTubeDislikePreferenceFragment;
Expand All @@ -25,6 +29,19 @@
@SuppressWarnings("unused")
public class LicenseActivityHook {

/**
* Injection point.
* Overrides the ReVanced settings language.
*/
public static Context getAttachBaseContext(Context original) {
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
if (language == AppLanguage.DEFAULT) {
return original;
}

return Utils.getContext();
}

/**
* Injection point.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

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.EnumSetting;
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
import app.revanced.extension.youtube.ThemeHelper;
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
Expand Down Expand Up @@ -109,15 +111,20 @@ protected void initialize() {
CustomPlaybackSpeedPatch.initializeListPreference(playbackPreference);
}

preference = findPreference(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE.key);
if (preference instanceof ListPreference languagePreference) {
sortListPreferenceByValues(languagePreference, 1);
}
sortPreferenceListMenu(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE);
sortPreferenceListMenu(BaseSettings.REVANCED_LANGUAGE);
} catch (Exception ex) {
Logger.printException(() -> "initialize failure", ex);
}
}

private void sortPreferenceListMenu(EnumSetting<?> setting) {
Preference preference = findPreference(setting.key);
if (preference instanceof ListPreference languagePreference) {
sortListPreferenceByValues(languagePreference, 1);
}
}

private void setPreferenceScreenToolbar(PreferenceScreen parentScreen) {
for (int i = 0, preferenceCount = parentScreen.getPreferenceCount(); i < preferenceCount; i++) {
Preference childPreference = parentScreen.getPreference(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
Expand All @@ -20,8 +21,12 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.fix.cairo.disableCairoSettingsPatch
import app.revanced.patches.youtube.misc.fix.playbackspeed.fixPlaybackSpeedWhilePlayingPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
import com.android.tools.smali.dexlib2.util.MethodUtil

// Used by a fingerprint() from SettingsPatch.
Expand Down Expand Up @@ -150,6 +155,10 @@ val settingsPatch = bytecodePatch(
inputType = InputType.TEXT_MULTI_LINE,
tag = "app.revanced.extension.shared.settings.preference.ImportExportPreference",
),
ListPreference(
key = "revanced_language",
summaryKey = null
)
)

setThemeFingerprint.method.let { setThemeMethod ->
Expand Down Expand Up @@ -189,6 +198,32 @@ val settingsPatch = bytecodePatch(
licenseActivityOnCreateFingerprint.classDef.apply {
methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
}

// Add context override to force a specific settings language.
licenseActivityOnCreateFingerprint.classDef.apply {
val attachBaseContext = ImmutableMethod(
type,
"attachBaseContext",
listOf(ImmutableMethodParameter("Landroid/content/Context;", null, null)),
"V",
AccessFlags.PROTECTED.value,
null,
null,
MutableMethodImplementation(3),
).toMutable().apply {
addInstructions(
"""
invoke-static { p1 }, $activityHookClassDescriptor->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
move-result-object p1
invoke-super { p0, p1 }, $superclass->attachBaseContext(Landroid/content/Context;)V
return-void
"""
)
}

methods.add(attachBaseContext)
}
LisoUseInAIKyrios marked this conversation as resolved.
Show resolved Hide resolved

}

finalize {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
),
ListPreference(
"revanced_spoof_video_streams_language",
summaryKey = null
key = "revanced_spoof_video_streams_language",
summaryKey = null,
// Language strings are declared in Setting patch.
entriesKey = "revanced_language_entries",
entryValuesKey = "revanced_language_entry_values"
),
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
Expand Down
Loading
Loading