Enable per-app language preferences for Android < 13
This commit is contained in:
parent
0db859e225
commit
893a227ab1
23 changed files with 85 additions and 145 deletions
|
|
@ -322,7 +322,7 @@ public final class ListHelper {
|
|||
}
|
||||
|
||||
// Sort collected streams by name
|
||||
return collectedStreams.values().stream().sorted(getAudioTrackNameComparator(context))
|
||||
return collectedStreams.values().stream().sorted(getAudioTrackNameComparator())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +359,7 @@ public final class ListHelper {
|
|||
}
|
||||
|
||||
// Sort tracks alphabetically, sort track streams by quality
|
||||
final Comparator<AudioStream> nameCmp = getAudioTrackNameComparator(context);
|
||||
final Comparator<AudioStream> nameCmp = getAudioTrackNameComparator();
|
||||
final Comparator<AudioStream> formatCmp = getAudioFormatComparator(context);
|
||||
|
||||
return collectedStreams.values().stream()
|
||||
|
|
@ -867,12 +867,10 @@ public final class ListHelper {
|
|||
* Get a {@link Comparator} to compare {@link AudioStream}s by their languages and track types
|
||||
* for alphabetical sorting.
|
||||
*
|
||||
* @param context app context for localization
|
||||
* @return Comparator
|
||||
*/
|
||||
private static Comparator<AudioStream> getAudioTrackNameComparator(
|
||||
@NonNull final Context context) {
|
||||
final Locale appLoc = Localization.getAppLocale(context);
|
||||
private static Comparator<AudioStream> getAudioTrackNameComparator() {
|
||||
final Locale appLoc = Localization.getAppLocale();
|
||||
|
||||
return Comparator.comparing(AudioStream::getAudioLocale, Comparator.nullsLast(
|
||||
Comparator.comparing(locale -> locale.getDisplayName(appLoc))))
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@ import static org.schabi.newpipe.MainActivity.DEBUG;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.icu.text.CompactDecimalFormat;
|
||||
import android.os.Build;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.text.BidiFormatter;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
|
@ -43,7 +41,6 @@ import java.time.format.FormatStyle;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
|
|
@ -120,39 +117,35 @@ public final class Localization {
|
|||
return getLocaleFromPrefs(context, R.string.content_language_key);
|
||||
}
|
||||
|
||||
public static Locale getAppLocale(@NonNull final Context context) {
|
||||
if (Build.VERSION.SDK_INT >= 33) {
|
||||
final Locale customLocale = AppCompatDelegate.getApplicationLocales().get(0);
|
||||
return Objects.requireNonNullElseGet(customLocale, Locale::getDefault);
|
||||
}
|
||||
return getLocaleFromPrefs(context, R.string.app_language_key);
|
||||
public static Locale getAppLocale() {
|
||||
final Locale customLocale = AppCompatDelegate.getApplicationLocales().get(0);
|
||||
return customLocale != null ? customLocale : Locale.getDefault();
|
||||
}
|
||||
|
||||
public static String localizeNumber(@NonNull final Context context, final long number) {
|
||||
return localizeNumber(context, (double) number);
|
||||
public static String localizeNumber(final long number) {
|
||||
return localizeNumber((double) number);
|
||||
}
|
||||
|
||||
public static String localizeNumber(@NonNull final Context context, final double number) {
|
||||
final NumberFormat nf = NumberFormat.getInstance(getAppLocale(context));
|
||||
public static String localizeNumber(final double number) {
|
||||
final NumberFormat nf = NumberFormat.getInstance(getAppLocale());
|
||||
return nf.format(number);
|
||||
}
|
||||
|
||||
public static String formatDate(@NonNull final Context context,
|
||||
@NonNull final OffsetDateTime offsetDateTime) {
|
||||
public static String formatDate(@NonNull final OffsetDateTime offsetDateTime) {
|
||||
return DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
|
||||
.withLocale(getAppLocale(context)).format(offsetDateTime
|
||||
.withLocale(getAppLocale()).format(offsetDateTime
|
||||
.atZoneSameInstant(ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatInvalid")
|
||||
public static String localizeUploadDate(@NonNull final Context context,
|
||||
@NonNull final OffsetDateTime offsetDateTime) {
|
||||
return context.getString(R.string.upload_date_text, formatDate(context, offsetDateTime));
|
||||
return context.getString(R.string.upload_date_text, formatDate(offsetDateTime));
|
||||
}
|
||||
|
||||
public static String localizeViewCount(@NonNull final Context context, final long viewCount) {
|
||||
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount,
|
||||
localizeNumber(context, viewCount));
|
||||
localizeNumber(viewCount));
|
||||
}
|
||||
|
||||
public static String localizeStreamCount(@NonNull final Context context,
|
||||
|
|
@ -166,7 +159,7 @@ public final class Localization {
|
|||
return context.getResources().getString(R.string.more_than_100_videos);
|
||||
default:
|
||||
return getQuantity(context, R.plurals.videos, R.string.no_videos, streamCount,
|
||||
localizeNumber(context, streamCount));
|
||||
localizeNumber(streamCount));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,27 +180,27 @@ public final class Localization {
|
|||
public static String localizeWatchingCount(@NonNull final Context context,
|
||||
final long watchingCount) {
|
||||
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount,
|
||||
localizeNumber(context, watchingCount));
|
||||
localizeNumber(watchingCount));
|
||||
}
|
||||
|
||||
public static String shortCount(@NonNull final Context context, final long count) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return CompactDecimalFormat.getInstance(getAppLocale(context),
|
||||
return CompactDecimalFormat.getInstance(getAppLocale(),
|
||||
CompactDecimalFormat.CompactStyle.SHORT).format(count);
|
||||
}
|
||||
|
||||
final double value = (double) count;
|
||||
if (count >= 1000000000) {
|
||||
return localizeNumber(context, round(value / 1000000000))
|
||||
return localizeNumber(round(value / 1000000000))
|
||||
+ context.getString(R.string.short_billion);
|
||||
} else if (count >= 1000000) {
|
||||
return localizeNumber(context, round(value / 1000000))
|
||||
return localizeNumber(round(value / 1000000))
|
||||
+ context.getString(R.string.short_million);
|
||||
} else if (count >= 1000) {
|
||||
return localizeNumber(context, round(value / 1000))
|
||||
return localizeNumber(round(value / 1000))
|
||||
+ context.getString(R.string.short_thousand);
|
||||
} else {
|
||||
return localizeNumber(context, value);
|
||||
return localizeNumber(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -377,8 +370,8 @@ public final class Localization {
|
|||
prettyTime.removeUnit(Decade.class);
|
||||
}
|
||||
|
||||
public static PrettyTime resolvePrettyTime(@NonNull final Context context) {
|
||||
return new PrettyTime(getAppLocale(context));
|
||||
public static PrettyTime resolvePrettyTime() {
|
||||
return new PrettyTime(getAppLocale());
|
||||
}
|
||||
|
||||
public static String relativeTime(@NonNull final OffsetDateTime offsetDateTime) {
|
||||
|
|
@ -410,14 +403,6 @@ public final class Localization {
|
|||
}
|
||||
}
|
||||
|
||||
public static void assureCorrectAppLanguage(final Context c) {
|
||||
final Resources res = c.getResources();
|
||||
final DisplayMetrics dm = res.getDisplayMetrics();
|
||||
final Configuration conf = res.getConfiguration();
|
||||
conf.setLocale(getAppLocale(c));
|
||||
res.updateConfiguration(conf, dm);
|
||||
}
|
||||
|
||||
private static Locale getLocaleFromPrefs(@NonNull final Context context,
|
||||
@StringRes final int prefKey) {
|
||||
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
|
@ -453,28 +438,29 @@ public final class Localization {
|
|||
}
|
||||
|
||||
public static void migrateAppLanguageSettingIfNecessary(@NonNull final Context context) {
|
||||
// Starting with pull request #12093, NewPipe on Android 13+ exclusively uses Android's
|
||||
// Starting with pull request #12093, NewPipe exclusively uses Android's
|
||||
// public per-app language APIs to read and set the UI language for NewPipe.
|
||||
// If running on Android 13+, the following code will migrate any existing custom
|
||||
// app language in SharedPreferences to use the public per-app language APIs instead.
|
||||
if (Build.VERSION.SDK_INT >= 33) {
|
||||
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String appLanguageKey = context.getString(R.string.app_language_key);
|
||||
final String appLanguageValue = sp.getString(appLanguageKey, null);
|
||||
if (appLanguageValue != null) {
|
||||
// The following code will migrate any existing custom app language in SharedPreferences to
|
||||
// use the public per-app language APIs instead.
|
||||
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String appLanguageKey = context.getString(R.string.app_language_key);
|
||||
final String appLanguageValue = sp.getString(appLanguageKey, null);
|
||||
if (appLanguageValue != null) {
|
||||
// The app language key is used on Android versions < Tiramisu; for more info, see
|
||||
// ContentSettingsFragment.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
sp.edit().remove(appLanguageKey).apply();
|
||||
final String appLanguageDefaultValue =
|
||||
context.getString(R.string.default_localization_key);
|
||||
if (!appLanguageValue.equals(appLanguageDefaultValue)) {
|
||||
try {
|
||||
AppCompatDelegate.setApplicationLocales(
|
||||
LocaleListCompat.forLanguageTags(appLanguageValue)
|
||||
);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.e(TAG, "Failed to migrate previous custom app language "
|
||||
+ "setting to public per-app language APIs"
|
||||
);
|
||||
}
|
||||
}
|
||||
final String appLanguageDefaultValue =
|
||||
context.getString(R.string.default_localization_key);
|
||||
if (!appLanguageValue.equals(appLanguageDefaultValue)) {
|
||||
try {
|
||||
final var locales = LocaleListCompat.forLanguageTags(appLanguageValue);
|
||||
AppCompatDelegate.setApplicationLocales(locales);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.e(TAG, "Failed to migrate previous custom app language "
|
||||
+ "setting to public per-app language APIs"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue