-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Support per-app language preferences #12093
base: dev
Are you sure you want to change the base?
Support per-app language preferences #12093
Conversation
I'll paste my comment from #10994 here:
Is it possible to check whether the per-app language is set? If it is, we might want to disable the in-app setting and display a hint that the per-app language preference is used instead. |
thanks @TobiGr! I looked briefly for an existing in-app language picker but didn't check in the "content" settings. Yeah, I'll need to make some more changes so they don't conflict. I should be able to keep the in-app language picker and migrate it to use the new APIs. |
If it's just a matter of hiding the settings screen language toggle and showing a message instead, in case the language has been changed from outside, then it's ok on the |
<Preference | ||
android:key="@string/app_language_android_13_and_up_key" | ||
android:title="@string/app_language_title" | ||
app:isPreferenceVisible="false" | ||
app:singleLineTitle="false" | ||
app:iconSpaceReserved="false" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a separate Preference
for the Android 13+ behavior only because for some reason when I set an OnPreferenceClickListener
on the existing preference that returns true
(indicating "the click was handled"), it still opens the existing dialog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. There is still a toast displayed that the language change is going to take effect with the next start of the app when changing the language on SDK 33+ which is obviously false.
|
||
if (Build.VERSION.SDK_INT >= 33) { | ||
ensureAppLanguagePreferenceIsMigrated(prefs); | ||
} | ||
} | ||
|
||
private void ensureAppLanguagePreferenceIsMigrated(final SharedPreferences prefs) { | ||
final String appLanguageDefaultValue = getString(R.string.default_localization_key); | ||
final String appLanguageKey = getString(R.string.app_language_key); | ||
final String appLanguageCurrentValue = prefs.getString(appLanguageKey, null); | ||
if (appLanguageCurrentValue != null) { | ||
// Migrate to Android per-app language settings | ||
prefs.edit().remove(appLanguageKey).apply(); | ||
if (!appLanguageCurrentValue.equals(appLanguageDefaultValue)) { | ||
try { | ||
AppCompatDelegate.setApplicationLocales( | ||
LocaleListCompat.forLanguageTags(appLanguageCurrentValue) | ||
); | ||
} catch (final RuntimeException e) { | ||
Log.e(TAG, "Error migrating to Android 13+ per-app language settings"); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks like it should be moved and converted to a Migration
in org.schabi.newpipe.settings.SettingMigrations
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only concern is that if we convert this to a Migration
, my understanding is that it will only run once. So in theory, the following scenario is possible:
- Someone running NewPipe on Android <13 sets a custom app language
- They update to the new version of NewPipe, where this migration is run but doesn't do anything because they're on Android <13
- They update to Android 13+
- Their custom app language pref isn't used (because it's running the Android 13+ code path) and it's not migrated from their old preference (because there's nothing triggering the migration to run again)
I recognize this will probably be a pretty rare scenario, just wanted to flag it. But whether or not we make it a Migration
, I do recognize that this code belongs somewhere outside of the Application
subclass for sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved it to a Migration
. If we want to prevent the hypothetical app language setting loss I described above, maybe we could add a new migrations file for "migrations that should always be run on app startup because they depend on the current Android version".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmmh you are right, this shouldn't be a migration as it needs to run every time the app notices it has been updated to Android 13+ from a lower Android version. What do you think @TobiGr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right. My bad. I'd move it to initSettings
in NewPipeSettings
then. Does that make sense @Stypox ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
My bad, totally forgot to fix the toast! So prior to this PR, we've been showing this toast whenever the app language, content language, or content country is changed. But are we sure that changes to content language/country have ever required a restart? When building from the latest commit on content.language.changing.without.restart.mp4If changes to the content language and country are reflected without having to restart, then the only situation where we need to show the toast is when app language is changed on a device running Android <13. Let me know if that sounds correct! |
The most recent commit I pushed assumes this is the case, but we can revert it if not. Video showing new behavior (no toast when changing only content language): dont.show.toast.when.changing.content.language.or.country.mp4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good to me, thank you! I have a comment here that could possibly be solved in a separate PR if you prefer. Also, see my comment about the migration.
Also, could you take a video of the updated code on pre-Android-13, so we can see if it still works as expected there?
androidResources { | ||
generateLocaleConfig = true | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't pay attention to new languages being added from Weblate, this might lead to half-translated being proposed to the user. Currently the list of languages is manually kept in settings_keys.xml
, so when new languages are added through Weblate they don't automatically appear in the app menu. However, I'm fine with switching to the new behavior, as it would avoid work to keep the language list up to date. Is it possible to access the locale config from within the app, so we can delete the list of languages in settings_keys.xml
and use the autogenerated locale config even for the pre-Android-13 language picker?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found LocaleManager#getOverrideLocaleConfig but it sounds like that method is only to get a LocaleConfig
that's already been set with setOverrideLocaleConfig()
. As far as I can tell, we would have to manually generate a LocaleConfig
instead of using the auto-generated one if we wanted to use it for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could find the data under app/build/generated/res/localeConfig/debug/xml/_generated_res_locale_config.xml
after running the build, with this data inside:
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="en-US"/>
<locale android:name="ace"/>
...
So in theory the data is there, but in practice I think we better not access it by manually opening the xml since it's not officially supported. So yeah let's keep the previous behavior.
@Stypox I tried it on an emulator running Android 12 and it seems fine: changing.language.on.android.12.mp4 |
Thank you! I tested to import an export from a previous version of NewPipe into this PR's build on Android 13 and unfortunately it did not work: the app language remained the one that was there previously before importing settings. This is the database I imported (it should set the language to italian): NewPipeData-20250324_172806.zip |
thanks for catching that and for sharing the settings export @Stypox! It turns out
I've moved the migration method to fixed.migration.mp4 |
|
What is it?
Description of the changes in your PR
Enables automatic per-app language support.
On Android 13+, the preference in Settings -> Content shows any locale that has been set by the user through Android's per-app language settings. When tapped, it opens NewPipe's per-app language settings screen.
Also added a method to migrate any existing app language preference from
SharedPreferences
to the Android per-app language settings when we run the app on Android 13+.Before/After Screenshots/Screen Record
per-app.language.settings.integrated.with.existing.ui.without.toast.mp4
APK testing
The APK can be found by going to the "Checks" tab below the title. On the left pane, click on "CI", scroll down to "artifacts" and click "app" to download the zip file which contains the debug APK of this PR. You can find more info and a video demonstration on this wiki page.
Due diligence