mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 23:32:59 +00:00 
			
		
		
		
	Enable per-app language preferences for Android < 13
This commit is contained in:
		| @@ -57,6 +57,15 @@ | |||||||
|             </intent-filter> |             </intent-filter> | ||||||
|         </receiver> |         </receiver> | ||||||
|  |  | ||||||
|  |         <service | ||||||
|  |             android:name="androidx.appcompat.app.AppLocalesMetadataHolderService" | ||||||
|  |             android:enabled="false" | ||||||
|  |             android:exported="false"> | ||||||
|  |             <meta-data | ||||||
|  |                 android:name="autoStoreLocales" | ||||||
|  |                 android:value="true" /> | ||||||
|  |         </service> | ||||||
|  |  | ||||||
|         <service |         <service | ||||||
|             android:name=".player.PlayerService" |             android:name=".player.PlayerService" | ||||||
|             android:exported="true" |             android:exported="true" | ||||||
|   | |||||||
| @@ -102,7 +102,7 @@ public class App extends Application { | |||||||
|         NewPipe.init(getDownloader(), |         NewPipe.init(getDownloader(), | ||||||
|             Localization.getPreferredLocalization(this), |             Localization.getPreferredLocalization(this), | ||||||
|             Localization.getPreferredContentCountry(this)); |             Localization.getPreferredContentCountry(this)); | ||||||
|         Localization.initPrettyTime(Localization.resolvePrettyTime(getApplicationContext())); |         Localization.initPrettyTime(Localization.resolvePrettyTime()); | ||||||
|  |  | ||||||
|         BridgeStateSaverInitializer.init(this); |         BridgeStateSaverInitializer.init(this); | ||||||
|         StateSaver.init(this); |         StateSaver.init(this); | ||||||
|   | |||||||
| @@ -20,8 +20,6 @@ | |||||||
|  |  | ||||||
| package org.schabi.newpipe; | package org.schabi.newpipe; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.content.BroadcastReceiver; | import android.content.BroadcastReceiver; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| @@ -142,6 +140,7 @@ public class MainActivity extends AppCompatActivity { | |||||||
|                     + "savedInstanceState = [" + savedInstanceState + "]"); |                     + "savedInstanceState = [" + savedInstanceState + "]"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         Localization.migrateAppLanguageSettingIfNecessary(getApplicationContext()); | ||||||
|         ThemeHelper.setDayNightMode(this); |         ThemeHelper.setDayNightMode(this); | ||||||
|         ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this)); |         ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this)); | ||||||
|  |  | ||||||
| @@ -158,7 +157,6 @@ public class MainActivity extends AppCompatActivity { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); |         sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); | ||||||
|         sharedPrefEditor = sharedPreferences.edit(); |         sharedPrefEditor = sharedPreferences.edit(); | ||||||
| @@ -197,7 +195,6 @@ public class MainActivity extends AppCompatActivity { | |||||||
|             UpdateSettingsFragment.askForConsentToUpdateChecks(this); |             UpdateSettingsFragment.askForConsentToUpdateChecks(this); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         Localization.migrateAppLanguageSettingIfNecessary(getApplicationContext()); |  | ||||||
|         SettingMigrations.showUserInfoIfPresent(this); |         SettingMigrations.showUserInfoIfPresent(this); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -504,9 +501,8 @@ public class MainActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void onResume() { |     protected void onResume() { | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|         // Change the date format to match the selected language on resume |         // Change the date format to match the selected language on resume | ||||||
|         Localization.initPrettyTime(Localization.resolvePrettyTime(getApplicationContext())); |         Localization.initPrettyTime(Localization.resolvePrettyTime()); | ||||||
|         super.onResume(); |         super.onResume(); | ||||||
|  |  | ||||||
|         // Close drawer on return, and don't show animation, |         // Close drawer on return, and don't show animation, | ||||||
|   | |||||||
| @@ -84,7 +84,6 @@ import org.schabi.newpipe.util.ChannelTabHelper; | |||||||
| import org.schabi.newpipe.util.Constants; | import org.schabi.newpipe.util.Constants; | ||||||
| import org.schabi.newpipe.util.DeviceUtils; | import org.schabi.newpipe.util.DeviceUtils; | ||||||
| import org.schabi.newpipe.util.ExtractorHelper; | import org.schabi.newpipe.util.ExtractorHelper; | ||||||
| import org.schabi.newpipe.util.Localization; |  | ||||||
| import org.schabi.newpipe.util.NavigationHelper; | import org.schabi.newpipe.util.NavigationHelper; | ||||||
| import org.schabi.newpipe.util.PermissionHelper; | import org.schabi.newpipe.util.PermissionHelper; | ||||||
| import org.schabi.newpipe.util.ThemeHelper; | import org.schabi.newpipe.util.ThemeHelper; | ||||||
| @@ -132,7 +131,6 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|         ThemeHelper.setDayNightMode(this); |         ThemeHelper.setDayNightMode(this); | ||||||
|         setTheme(ThemeHelper.isLightThemeSelected(this) |         setTheme(ThemeHelper.isLightThemeSelected(this) | ||||||
|                 ? R.style.RouterActivityThemeLight : R.style.RouterActivityThemeDark); |                 ? R.style.RouterActivityThemeLight : R.style.RouterActivityThemeDark); | ||||||
|         Localization.assureCorrectAppLanguage(this); |  | ||||||
|  |  | ||||||
|         // Pass-through touch events to background activities |         // Pass-through touch events to background activities | ||||||
|         // so that our transparent window won't lock UI in the mean time |         // so that our transparent window won't lock UI in the mean time | ||||||
|   | |||||||
| @@ -16,14 +16,12 @@ import org.schabi.newpipe.BuildConfig | |||||||
| import org.schabi.newpipe.R | import org.schabi.newpipe.R | ||||||
| import org.schabi.newpipe.databinding.ActivityAboutBinding | import org.schabi.newpipe.databinding.ActivityAboutBinding | ||||||
| import org.schabi.newpipe.databinding.FragmentAboutBinding | import org.schabi.newpipe.databinding.FragmentAboutBinding | ||||||
| import org.schabi.newpipe.util.Localization |  | ||||||
| import org.schabi.newpipe.util.ThemeHelper | import org.schabi.newpipe.util.ThemeHelper | ||||||
| import org.schabi.newpipe.util.external_communication.ShareUtils | import org.schabi.newpipe.util.external_communication.ShareUtils | ||||||
|  |  | ||||||
| class AboutActivity : AppCompatActivity() { | class AboutActivity : AppCompatActivity() { | ||||||
|  |  | ||||||
|     override fun onCreate(savedInstanceState: Bundle?) { |     override fun onCreate(savedInstanceState: Bundle?) { | ||||||
|         Localization.assureCorrectAppLanguage(this) |  | ||||||
|         super.onCreate(savedInstanceState) |         super.onCreate(savedInstanceState) | ||||||
|         ThemeHelper.setTheme(this) |         ThemeHelper.setTheme(this) | ||||||
|         title = getString(R.string.title_activity_about) |         title = getString(R.string.title_activity_about) | ||||||
|   | |||||||
| @@ -19,7 +19,6 @@ import org.schabi.newpipe.R | |||||||
| import org.schabi.newpipe.databinding.FragmentLicensesBinding | import org.schabi.newpipe.databinding.FragmentLicensesBinding | ||||||
| import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding | import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding | ||||||
| import org.schabi.newpipe.ktx.parcelableArrayList | import org.schabi.newpipe.ktx.parcelableArrayList | ||||||
| import org.schabi.newpipe.util.Localization |  | ||||||
| import org.schabi.newpipe.util.external_communication.ShareUtils | import org.schabi.newpipe.util.external_communication.ShareUtils | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -100,7 +99,6 @@ class LicenseFragment : Fragment() { | |||||||
|                     val webView = WebView(context) |                     val webView = WebView(context) | ||||||
|                     webView.loadData(webViewData, "text/html; charset=UTF-8", "base64") |                     webView.loadData(webViewData, "text/html; charset=UTF-8", "base64") | ||||||
|  |  | ||||||
|                     Localization.assureCorrectAppLanguage(context) |  | ||||||
|                     val builder = AlertDialog.Builder(requireContext()) |                     val builder = AlertDialog.Builder(requireContext()) | ||||||
|                         .setTitle(softwareComponent.name) |                         .setTitle(softwareComponent.name) | ||||||
|                         .setView(webView) |                         .setView(webView) | ||||||
|   | |||||||
| @@ -20,8 +20,6 @@ import org.schabi.newpipe.views.FocusOverlayView; | |||||||
| import us.shandian.giga.service.DownloadManagerService; | import us.shandian.giga.service.DownloadManagerService; | ||||||
| import us.shandian.giga.ui.fragment.MissionsFragment; | import us.shandian.giga.ui.fragment.MissionsFragment; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| public class DownloadActivity extends AppCompatActivity { | public class DownloadActivity extends AppCompatActivity { | ||||||
|  |  | ||||||
|     private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag"; |     private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag"; | ||||||
| @@ -33,7 +31,6 @@ public class DownloadActivity extends AppCompatActivity { | |||||||
|         i.setClass(this, DownloadManagerService.class); |         i.setClass(this, DownloadManagerService.class); | ||||||
|         startService(i); |         startService(i); | ||||||
|  |  | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|         ThemeHelper.setTheme(this); |         ThemeHelper.setTheme(this); | ||||||
|  |  | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ package org.schabi.newpipe.download; | |||||||
|  |  | ||||||
| import static org.schabi.newpipe.extractor.stream.DeliveryMethod.PROGRESSIVE_HTTP; | import static org.schabi.newpipe.extractor.stream.DeliveryMethod.PROGRESSIVE_HTTP; | ||||||
| import static org.schabi.newpipe.util.ListHelper.getStreamsOfSpecifiedDelivery; | import static org.schabi.newpipe.util.ListHelper.getStreamsOfSpecifiedDelivery; | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.content.ComponentName; | import android.content.ComponentName; | ||||||
| @@ -751,7 +750,6 @@ public class DownloadDialog extends DialogFragment | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void showFailedDialog(@StringRes final int msg) { |     private void showFailedDialog(@StringRes final int msg) { | ||||||
|         assureCorrectAppLanguage(requireContext()); |  | ||||||
|         new AlertDialog.Builder(context) |         new AlertDialog.Builder(context) | ||||||
|                 .setTitle(R.string.general_error) |                 .setTitle(R.string.general_error) | ||||||
|                 .setMessage(msg) |                 .setMessage(msg) | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| package org.schabi.newpipe.error; | package org.schabi.newpipe.error; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.net.Uri; | import android.net.Uri; | ||||||
| @@ -79,7 +77,6 @@ public class ErrorActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(final Bundle savedInstanceState) { |     protected void onCreate(final Bundle savedInstanceState) { | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|  |  | ||||||
|         ThemeHelper.setDayNightMode(this); |         ThemeHelper.setDayNightMode(this); | ||||||
| @@ -306,7 +303,7 @@ public class ErrorActivity extends AppCompatActivity { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private String getAppLanguage() { |     private String getAppLanguage() { | ||||||
|         return Localization.getAppLocale(getApplicationContext()).toString(); |         return Localization.getAppLocale().toString(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private String getOsString() { |     private String getOsString() { | ||||||
|   | |||||||
| @@ -93,7 +93,7 @@ public class DescriptionFragment extends BaseDescriptionFragment { | |||||||
|  |  | ||||||
|         if (streamInfo.getLanguageInfo() != null) { |         if (streamInfo.getLanguageInfo() != null) { | ||||||
|             addMetadataItem(inflater, layout, false, R.string.metadata_language, |             addMetadataItem(inflater, layout, false, R.string.metadata_language, | ||||||
|                     streamInfo.getLanguageInfo().getDisplayLanguage(getAppLocale(getContext()))); |                     streamInfo.getLanguageInfo().getDisplayLanguage(getAppLocale())); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addMetadataItem(inflater, layout, true, R.string.metadata_support, |         addMetadataItem(inflater, layout, true, R.string.metadata_support, | ||||||
|   | |||||||
| @@ -81,9 +81,7 @@ public class ChannelAboutFragment extends BaseDescriptionFragment { | |||||||
|  |  | ||||||
|         if (channelInfo.getSubscriberCount() != UNKNOWN_SUBSCRIBER_COUNT) { |         if (channelInfo.getSubscriberCount() != UNKNOWN_SUBSCRIBER_COUNT) { | ||||||
|             addMetadataItem(inflater, layout, false, R.string.metadata_subscribers, |             addMetadataItem(inflater, layout, false, R.string.metadata_subscribers, | ||||||
|                     Localization.localizeNumber( |                     Localization.localizeNumber(channelInfo.getSubscriberCount())); | ||||||
|                             requireContext(), |  | ||||||
|                             channelInfo.getSubscriberCount())); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addImagesMetadataItem(inflater, layout, R.string.metadata_avatars, |         addImagesMetadataItem(inflater, layout, R.string.metadata_avatars, | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| package org.schabi.newpipe.local.subscription; | package org.schabi.newpipe.local.subscription; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.app.Dialog; | import android.app.Dialog; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| @@ -35,7 +33,6 @@ public class ImportConfirmationDialog extends DialogFragment { | |||||||
|     @NonNull |     @NonNull | ||||||
|     @Override |     @Override | ||||||
|     public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { |     public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { | ||||||
|         assureCorrectAppLanguage(getContext()); |  | ||||||
|         return new AlertDialog.Builder(requireContext()) |         return new AlertDialog.Builder(requireContext()) | ||||||
|                 .setMessage(R.string.import_network_expensive_warning) |                 .setMessage(R.string.import_network_expensive_warning) | ||||||
|                 .setCancelable(true) |                 .setCancelable(true) | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ package org.schabi.newpipe.player; | |||||||
|  |  | ||||||
| import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; | import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; | ||||||
| import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; | import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.content.ComponentName; | import android.content.ComponentName; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| @@ -84,7 +83,6 @@ public final class PlayQueueActivity extends AppCompatActivity | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(final Bundle savedInstanceState) { |     protected void onCreate(final Bundle savedInstanceState) { | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this)); |         ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,7 +44,6 @@ import static org.schabi.newpipe.player.notification.NotificationConstants.ACTIO | |||||||
| import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_SHUFFLE; | import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_SHUFFLE; | ||||||
| import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; | import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; | ||||||
| import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; | import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
| import static java.util.concurrent.TimeUnit.MILLISECONDS; | import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||||||
|  |  | ||||||
| import android.content.BroadcastReceiver; | import android.content.BroadcastReceiver; | ||||||
| @@ -88,8 +87,8 @@ import org.schabi.newpipe.databinding.PlayerBinding; | |||||||
| import org.schabi.newpipe.error.ErrorInfo; | import org.schabi.newpipe.error.ErrorInfo; | ||||||
| import org.schabi.newpipe.error.ErrorUtil; | import org.schabi.newpipe.error.ErrorUtil; | ||||||
| import org.schabi.newpipe.error.UserAction; | import org.schabi.newpipe.error.UserAction; | ||||||
| import org.schabi.newpipe.extractor.stream.AudioStream; |  | ||||||
| import org.schabi.newpipe.extractor.Image; | import org.schabi.newpipe.extractor.Image; | ||||||
|  | import org.schabi.newpipe.extractor.stream.AudioStream; | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfo; | import org.schabi.newpipe.extractor.stream.StreamInfo; | ||||||
| import org.schabi.newpipe.extractor.stream.StreamType; | import org.schabi.newpipe.extractor.stream.StreamType; | ||||||
| import org.schabi.newpipe.extractor.stream.VideoStream; | import org.schabi.newpipe.extractor.stream.VideoStream; | ||||||
| @@ -120,9 +119,9 @@ import org.schabi.newpipe.player.ui.VideoPlayerUi; | |||||||
| import org.schabi.newpipe.util.DependentPreferenceHelper; | import org.schabi.newpipe.util.DependentPreferenceHelper; | ||||||
| import org.schabi.newpipe.util.ListHelper; | import org.schabi.newpipe.util.ListHelper; | ||||||
| import org.schabi.newpipe.util.NavigationHelper; | import org.schabi.newpipe.util.NavigationHelper; | ||||||
| import org.schabi.newpipe.util.image.PicassoHelper; |  | ||||||
| import org.schabi.newpipe.util.SerializedCache; | import org.schabi.newpipe.util.SerializedCache; | ||||||
| import org.schabi.newpipe.util.StreamTypeUtil; | import org.schabi.newpipe.util.StreamTypeUtil; | ||||||
|  | import org.schabi.newpipe.util.image.PicassoHelper; | ||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| @@ -753,7 +752,6 @@ public final class Player implements PlaybackListener, Listener { | |||||||
|                 toggleShuffleModeEnabled(); |                 toggleShuffleModeEnabled(); | ||||||
|                 break; |                 break; | ||||||
|             case Intent.ACTION_CONFIGURATION_CHANGED: |             case Intent.ACTION_CONFIGURATION_CHANGED: | ||||||
|                 assureCorrectAppLanguage(service); |  | ||||||
|                 if (DEBUG) { |                 if (DEBUG) { | ||||||
|                     Log.d(TAG, "ACTION_CONFIGURATION_CHANGED received"); |                     Log.d(TAG, "ACTION_CONFIGURATION_CHANGED received"); | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -19,8 +19,6 @@ | |||||||
|  |  | ||||||
| package org.schabi.newpipe.player; | package org.schabi.newpipe.player; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.os.Binder; | import android.os.Binder; | ||||||
| @@ -91,7 +89,6 @@ public final class PlayerService extends MediaBrowserServiceCompat { | |||||||
|         if (DEBUG) { |         if (DEBUG) { | ||||||
|             Log.d(TAG, "onCreate() called"); |             Log.d(TAG, "onCreate() called"); | ||||||
|         } |         } | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|         ThemeHelper.setTheme(this); |         ThemeHelper.setTheme(this); | ||||||
|  |  | ||||||
|         mediaBrowserImpl = new MediaBrowserImpl(this, this::notifyChildrenChanged); |         mediaBrowserImpl = new MediaBrowserImpl(this, this::notifyChildrenChanged); | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ package org.schabi.newpipe.player.helper; | |||||||
|  |  | ||||||
| import static org.schabi.newpipe.ktx.ViewUtils.animateRotation; | import static org.schabi.newpipe.ktx.ViewUtils.animateRotation; | ||||||
| import static org.schabi.newpipe.player.Player.DEBUG; | import static org.schabi.newpipe.player.Player.DEBUG; | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
| import static org.schabi.newpipe.util.ThemeHelper.resolveDrawable; | import static org.schabi.newpipe.util.ThemeHelper.resolveDrawable; | ||||||
|  |  | ||||||
| import android.app.Dialog; | import android.app.Dialog; | ||||||
| @@ -145,7 +144,6 @@ public class PlaybackParameterDialog extends DialogFragment { | |||||||
|     @NonNull |     @NonNull | ||||||
|     @Override |     @Override | ||||||
|     public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { |     public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { | ||||||
|         assureCorrectAppLanguage(getContext()); |  | ||||||
|         Bridge.restoreInstanceState(this, savedInstanceState); |         Bridge.restoreInstanceState(this, savedInstanceState); | ||||||
|  |  | ||||||
|         binding = DialogPlaybackParameterBinding.inflate(getLayoutInflater()); |         binding = DialogPlaybackParameterBinding.inflate(getLayoutInflater()); | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import android.os.Bundle | |||||||
| import android.os.ResultReceiver | import android.os.ResultReceiver | ||||||
| import android.support.v4.media.session.PlaybackStateCompat | import android.support.v4.media.session.PlaybackStateCompat | ||||||
| import android.util.Log | import android.util.Log | ||||||
|  | import androidx.core.content.ContextCompat | ||||||
| import androidx.core.net.toUri | import androidx.core.net.toUri | ||||||
| import com.google.android.exoplayer2.Player | import com.google.android.exoplayer2.Player | ||||||
| import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.PlaybackPreparer | import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.PlaybackPreparer | ||||||
| @@ -109,14 +110,14 @@ class MediaBrowserPlaybackPreparer( | |||||||
|     //region Errors |     //region Errors | ||||||
|     private fun onUnsupportedError() { |     private fun onUnsupportedError() { | ||||||
|         setMediaSessionError.accept( |         setMediaSessionError.accept( | ||||||
|             context.getString(R.string.content_not_supported), |             ContextCompat.getString(context, R.string.content_not_supported), | ||||||
|             PlaybackStateCompat.ERROR_CODE_NOT_SUPPORTED |             PlaybackStateCompat.ERROR_CODE_NOT_SUPPORTED | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun onPrepareError() { |     private fun onPrepareError() { | ||||||
|         setMediaSessionError.accept( |         setMediaSessionError.accept( | ||||||
|             context.getString(R.string.error_snackbar_message), |             ContextCompat.getString(context, R.string.error_snackbar_message), | ||||||
|             PlaybackStateCompat.ERROR_CODE_APP_ERROR |             PlaybackStateCompat.ERROR_CODE_APP_ERROR | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
| package org.schabi.newpipe.settings; | package org.schabi.newpipe.settings; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.extractor.utils.Utils.isBlank; | import static org.schabi.newpipe.extractor.utils.Utils.isBlank; | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.app.AlertDialog; | import android.app.AlertDialog; | ||||||
| @@ -126,7 +125,6 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void requestExportPathResult(final ActivityResult result) { |     private void requestExportPathResult(final ActivityResult result) { | ||||||
|         assureCorrectAppLanguage(requireContext()); |  | ||||||
|         if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { |         if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { | ||||||
|             // will be saved only on success |             // will be saved only on success | ||||||
|             final Uri lastExportDataUri = result.getData().getData(); |             final Uri lastExportDataUri = result.getData().getData(); | ||||||
| @@ -139,7 +137,6 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void requestImportPathResult(final ActivityResult result) { |     private void requestImportPathResult(final ActivityResult result) { | ||||||
|         assureCorrectAppLanguage(requireContext()); |  | ||||||
|         if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { |         if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { | ||||||
|             // will be saved only on success |             // will be saved only on success | ||||||
|             final Uri lastImportDataUri = result.getData().getData(); |             final Uri lastImportDataUri = result.getData().getData(); | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ import android.util.Log; | |||||||
| import android.widget.Toast; | import android.widget.Toast; | ||||||
|  |  | ||||||
| import androidx.appcompat.app.AppCompatDelegate; | import androidx.appcompat.app.AppCompatDelegate; | ||||||
|  | import androidx.core.os.LocaleListCompat; | ||||||
| import androidx.preference.Preference; | import androidx.preference.Preference; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.DownloaderImpl; | import org.schabi.newpipe.DownloaderImpl; | ||||||
| @@ -27,26 +28,20 @@ import java.util.Locale; | |||||||
| public class ContentSettingsFragment extends BasePreferenceFragment { | public class ContentSettingsFragment extends BasePreferenceFragment { | ||||||
|     private String youtubeRestrictedModeEnabledKey; |     private String youtubeRestrictedModeEnabledKey; | ||||||
|  |  | ||||||
|     private String initialLanguage; |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { |     public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) { | ||||||
|         youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled); |         youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled); | ||||||
|  |  | ||||||
|         addPreferencesFromResourceRegistry(); |         addPreferencesFromResourceRegistry(); | ||||||
|  |  | ||||||
|         initialLanguage = defaultPreferences.getString(getString(R.string.app_language_key), "en"); |         final var appLanguagePref = requirePreference(R.string.app_language_key); | ||||||
|  |  | ||||||
|         if (Build.VERSION.SDK_INT >= 33) { |         if (Build.VERSION.SDK_INT >= 33) { | ||||||
|             requirePreference(R.string.app_language_key).setVisible(false); |             appLanguagePref.setVisible(false); | ||||||
|             final Preference newAppLanguagePref = |             final var newAppLanguagePref = | ||||||
|                     requirePreference(R.string.app_language_android_13_and_up_key); |                     requirePreference(R.string.app_language_android_13_and_up_key); | ||||||
|             newAppLanguagePref.setSummaryProvider(preference -> { |             newAppLanguagePref.setSummaryProvider(preference -> { | ||||||
|                 final Locale customLocale = AppCompatDelegate.getApplicationLocales().get(0); |                 final Locale loc = AppCompatDelegate.getApplicationLocales().get(0); | ||||||
|                 if (customLocale != null) { |                 return loc != null ? loc.getDisplayName() : getString(R.string.systems_language); | ||||||
|                     return customLocale.getDisplayName(); |  | ||||||
|                 } |  | ||||||
|                 return getString(R.string.systems_language); |  | ||||||
|             }); |             }); | ||||||
|             newAppLanguagePref.setOnPreferenceClickListener(preference -> { |             newAppLanguagePref.setOnPreferenceClickListener(preference -> { | ||||||
|                 final Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS) |                 final Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS) | ||||||
| @@ -55,10 +50,16 @@ public class ContentSettingsFragment extends BasePreferenceFragment { | |||||||
|                 return true; |                 return true; | ||||||
|             }); |             }); | ||||||
|             newAppLanguagePref.setVisible(true); |             newAppLanguagePref.setVisible(true); | ||||||
|  |         } else { | ||||||
|  |             appLanguagePref.setOnPreferenceChangeListener((preference, newValue) -> { | ||||||
|  |                 final String language = (String) newValue; | ||||||
|  |                 final Locale locale = Locale.forLanguageTag(language); | ||||||
|  |                 AppCompatDelegate.setApplicationLocales(LocaleListCompat.create(locale)); | ||||||
|  |                 return true; | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final Preference imageQualityPreference = requirePreference(R.string.image_quality_key); |         requirePreference(R.string.image_quality_key).setOnPreferenceChangeListener( | ||||||
|         imageQualityPreference.setOnPreferenceChangeListener( |  | ||||||
|                 (preference, newValue) -> { |                 (preference, newValue) -> { | ||||||
|                     ImageStrategy.setPreferredImageQuality(PreferredImageQuality |                     ImageStrategy.setPreferredImageQuality(PreferredImageQuality | ||||||
|                             .fromPreferenceKey(requireContext(), (String) newValue)); |                             .fromPreferenceKey(requireContext(), (String) newValue)); | ||||||
| @@ -92,22 +93,10 @@ public class ContentSettingsFragment extends BasePreferenceFragment { | |||||||
|     public void onDestroy() { |     public void onDestroy() { | ||||||
|         super.onDestroy(); |         super.onDestroy(); | ||||||
|  |  | ||||||
|         final String selectedLanguage = |  | ||||||
|                 defaultPreferences.getString(getString(R.string.app_language_key), "en"); |  | ||||||
|  |  | ||||||
|         if (!selectedLanguage.equals(initialLanguage)) { |  | ||||||
|             if (Build.VERSION.SDK_INT < 33) { |  | ||||||
|                 Toast.makeText( |  | ||||||
|                         requireContext(), |  | ||||||
|                         R.string.localization_changes_requires_app_restart, |  | ||||||
|                         Toast.LENGTH_LONG |  | ||||||
|                 ).show(); |  | ||||||
|             } |  | ||||||
|         final Localization selectedLocalization = org.schabi.newpipe.util.Localization |         final Localization selectedLocalization = org.schabi.newpipe.util.Localization | ||||||
|                 .getPreferredLocalization(requireContext()); |                 .getPreferredLocalization(requireContext()); | ||||||
|         final ContentCountry selectedContentCountry = org.schabi.newpipe.util.Localization |         final ContentCountry selectedContentCountry = org.schabi.newpipe.util.Localization | ||||||
|                 .getPreferredContentCountry(requireContext()); |                 .getPreferredContentCountry(requireContext()); | ||||||
|         NewPipe.setupLocalization(selectedLocalization, selectedContentCountry); |         NewPipe.setupLocalization(selectedLocalization, selectedContentCountry); | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| package org.schabi.newpipe.settings; | package org.schabi.newpipe.settings; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.content.ContentResolver; | import android.content.ContentResolver; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| @@ -209,8 +207,6 @@ public class DownloadSettingsFragment extends BasePreferenceFragment { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void requestDownloadPathResult(final ActivityResult result, final String key) { |     private void requestDownloadPathResult(final ActivityResult result, final String key) { | ||||||
|         assureCorrectAppLanguage(getContext()); |  | ||||||
|  |  | ||||||
|         if (result.getResultCode() != Activity.RESULT_OK) { |         if (result.getResultCode() != Activity.RESULT_OK) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| package org.schabi.newpipe.settings; | package org.schabi.newpipe.settings; | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; |  | ||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.text.TextUtils; | import android.text.TextUtils; | ||||||
| @@ -89,7 +87,6 @@ public class SettingsActivity extends AppCompatActivity implements | |||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(final Bundle savedInstanceBundle) { |     protected void onCreate(final Bundle savedInstanceBundle) { | ||||||
|         setTheme(ThemeHelper.getSettingsThemeStyle(this)); |         setTheme(ThemeHelper.getSettingsThemeStyle(this)); | ||||||
|         assureCorrectAppLanguage(this); |  | ||||||
|  |  | ||||||
|         super.onCreate(savedInstanceBundle); |         super.onCreate(savedInstanceBundle); | ||||||
|         Bridge.restoreInstanceState(this, savedInstanceBundle); |         Bridge.restoreInstanceState(this, savedInstanceBundle); | ||||||
| @@ -228,7 +225,6 @@ public class SettingsActivity extends AppCompatActivity implements | |||||||
|  |  | ||||||
|         // Build search items |         // Build search items | ||||||
|         final Context searchContext = getApplicationContext(); |         final Context searchContext = getApplicationContext(); | ||||||
|         assureCorrectAppLanguage(searchContext); |  | ||||||
|         final PreferenceParser parser = new PreferenceParser(searchContext, config); |         final PreferenceParser parser = new PreferenceParser(searchContext, config); | ||||||
|         final PreferenceSearcher searcher = new PreferenceSearcher(config); |         final PreferenceSearcher searcher = new PreferenceSearcher(config); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -322,7 +322,7 @@ public final class ListHelper { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Sort collected streams by name |         // Sort collected streams by name | ||||||
|         return collectedStreams.values().stream().sorted(getAudioTrackNameComparator(context)) |         return collectedStreams.values().stream().sorted(getAudioTrackNameComparator()) | ||||||
|                 .collect(Collectors.toList()); |                 .collect(Collectors.toList()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -359,7 +359,7 @@ public final class ListHelper { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Sort tracks alphabetically, sort track streams by quality |         // 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); |         final Comparator<AudioStream> formatCmp = getAudioFormatComparator(context); | ||||||
|  |  | ||||||
|         return collectedStreams.values().stream() |         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 |      * Get a {@link Comparator} to compare {@link AudioStream}s by their languages and track types | ||||||
|      * for alphabetical sorting. |      * for alphabetical sorting. | ||||||
|      * |      * | ||||||
|      * @param context app context for localization |  | ||||||
|      * @return Comparator |      * @return Comparator | ||||||
|      */ |      */ | ||||||
|     private static Comparator<AudioStream> getAudioTrackNameComparator( |     private static Comparator<AudioStream> getAudioTrackNameComparator() { | ||||||
|             @NonNull final Context context) { |         final Locale appLoc = Localization.getAppLocale(); | ||||||
|         final Locale appLoc = Localization.getAppLocale(context); |  | ||||||
|  |  | ||||||
|         return Comparator.comparing(AudioStream::getAudioLocale, Comparator.nullsLast( |         return Comparator.comparing(AudioStream::getAudioLocale, Comparator.nullsLast( | ||||||
|                         Comparator.comparing(locale -> locale.getDisplayName(appLoc)))) |                         Comparator.comparing(locale -> locale.getDisplayName(appLoc)))) | ||||||
|   | |||||||
| @@ -5,14 +5,12 @@ import static org.schabi.newpipe.MainActivity.DEBUG; | |||||||
| import android.annotation.SuppressLint; | import android.annotation.SuppressLint; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
| import android.content.res.Configuration; |  | ||||||
| import android.content.res.Resources; | import android.content.res.Resources; | ||||||
| import android.icu.text.CompactDecimalFormat; | import android.icu.text.CompactDecimalFormat; | ||||||
| import android.os.Build; | import android.os.Build; | ||||||
|  | import android.text.BidiFormatter; | ||||||
| import android.text.TextUtils; | import android.text.TextUtils; | ||||||
| import android.text.format.DateUtils; | import android.text.format.DateUtils; | ||||||
| import android.text.BidiFormatter; |  | ||||||
| import android.util.DisplayMetrics; |  | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  |  | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| @@ -43,7 +41,6 @@ import java.time.format.FormatStyle; | |||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.Objects; |  | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -120,39 +117,35 @@ public final class Localization { | |||||||
|         return getLocaleFromPrefs(context, R.string.content_language_key); |         return getLocaleFromPrefs(context, R.string.content_language_key); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static Locale getAppLocale(@NonNull final Context context) { |     public static Locale getAppLocale() { | ||||||
|         if (Build.VERSION.SDK_INT >= 33) { |  | ||||||
|         final Locale customLocale = AppCompatDelegate.getApplicationLocales().get(0); |         final Locale customLocale = AppCompatDelegate.getApplicationLocales().get(0); | ||||||
|             return Objects.requireNonNullElseGet(customLocale, Locale::getDefault); |         return customLocale != null ? customLocale : Locale.getDefault(); | ||||||
|         } |  | ||||||
|         return getLocaleFromPrefs(context, R.string.app_language_key); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String localizeNumber(@NonNull final Context context, final long number) { |     public static String localizeNumber(final long number) { | ||||||
|         return localizeNumber(context, (double) number); |         return localizeNumber((double) number); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String localizeNumber(@NonNull final Context context, final double number) { |     public static String localizeNumber(final double number) { | ||||||
|         final NumberFormat nf = NumberFormat.getInstance(getAppLocale(context)); |         final NumberFormat nf = NumberFormat.getInstance(getAppLocale()); | ||||||
|         return nf.format(number); |         return nf.format(number); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String formatDate(@NonNull final Context context, |     public static String formatDate(@NonNull final OffsetDateTime offsetDateTime) { | ||||||
|                                     @NonNull final OffsetDateTime offsetDateTime) { |  | ||||||
|         return DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) |         return DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) | ||||||
|                 .withLocale(getAppLocale(context)).format(offsetDateTime |                 .withLocale(getAppLocale()).format(offsetDateTime | ||||||
|                         .atZoneSameInstant(ZoneId.systemDefault())); |                         .atZoneSameInstant(ZoneId.systemDefault())); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @SuppressLint("StringFormatInvalid") |     @SuppressLint("StringFormatInvalid") | ||||||
|     public static String localizeUploadDate(@NonNull final Context context, |     public static String localizeUploadDate(@NonNull final Context context, | ||||||
|                                             @NonNull final OffsetDateTime offsetDateTime) { |                                             @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) { |     public static String localizeViewCount(@NonNull final Context context, final long viewCount) { | ||||||
|         return getQuantity(context, R.plurals.views, R.string.no_views, 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, |     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); |                 return context.getResources().getString(R.string.more_than_100_videos); | ||||||
|             default: |             default: | ||||||
|                 return getQuantity(context, R.plurals.videos, R.string.no_videos, streamCount, |                 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, |     public static String localizeWatchingCount(@NonNull final Context context, | ||||||
|                                                final long watchingCount) { |                                                final long watchingCount) { | ||||||
|         return getQuantity(context, R.plurals.watching, R.string.no_one_watching, 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) { |     public static String shortCount(@NonNull final Context context, final long count) { | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||||
|             return CompactDecimalFormat.getInstance(getAppLocale(context), |             return CompactDecimalFormat.getInstance(getAppLocale(), | ||||||
|                     CompactDecimalFormat.CompactStyle.SHORT).format(count); |                     CompactDecimalFormat.CompactStyle.SHORT).format(count); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final double value = (double) count; |         final double value = (double) count; | ||||||
|         if (count >= 1000000000) { |         if (count >= 1000000000) { | ||||||
|             return localizeNumber(context, round(value / 1000000000)) |             return localizeNumber(round(value / 1000000000)) | ||||||
|                     + context.getString(R.string.short_billion); |                     + context.getString(R.string.short_billion); | ||||||
|         } else if (count >= 1000000) { |         } else if (count >= 1000000) { | ||||||
|             return localizeNumber(context, round(value / 1000000)) |             return localizeNumber(round(value / 1000000)) | ||||||
|                     + context.getString(R.string.short_million); |                     + context.getString(R.string.short_million); | ||||||
|         } else if (count >= 1000) { |         } else if (count >= 1000) { | ||||||
|             return localizeNumber(context, round(value / 1000)) |             return localizeNumber(round(value / 1000)) | ||||||
|                     + context.getString(R.string.short_thousand); |                     + context.getString(R.string.short_thousand); | ||||||
|         } else { |         } else { | ||||||
|             return localizeNumber(context, value); |             return localizeNumber(value); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -377,8 +370,8 @@ public final class Localization { | |||||||
|         prettyTime.removeUnit(Decade.class); |         prettyTime.removeUnit(Decade.class); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static PrettyTime resolvePrettyTime(@NonNull final Context context) { |     public static PrettyTime resolvePrettyTime() { | ||||||
|         return new PrettyTime(getAppLocale(context)); |         return new PrettyTime(getAppLocale()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String relativeTime(@NonNull final OffsetDateTime offsetDateTime) { |     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, |     private static Locale getLocaleFromPrefs(@NonNull final Context context, | ||||||
|                                              @StringRes final int prefKey) { |                                              @StringRes final int prefKey) { | ||||||
|         final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); |         final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); | ||||||
| @@ -453,23 +438,25 @@ public final class Localization { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static void migrateAppLanguageSettingIfNecessary(@NonNull final Context context) { |     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. |         // 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 |         // The following code will migrate any existing custom app language in SharedPreferences to | ||||||
|         // app language in SharedPreferences to use the public per-app language APIs instead. |         // use the public per-app language APIs instead. | ||||||
|         if (Build.VERSION.SDK_INT >= 33) { |  | ||||||
|         final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); |         final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); | ||||||
|         final String appLanguageKey = context.getString(R.string.app_language_key); |         final String appLanguageKey = context.getString(R.string.app_language_key); | ||||||
|         final String appLanguageValue = sp.getString(appLanguageKey, null); |         final String appLanguageValue = sp.getString(appLanguageKey, null); | ||||||
|         if (appLanguageValue != 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(); |                 sp.edit().remove(appLanguageKey).apply(); | ||||||
|  |             } | ||||||
|             final String appLanguageDefaultValue = |             final String appLanguageDefaultValue = | ||||||
|                     context.getString(R.string.default_localization_key); |                     context.getString(R.string.default_localization_key); | ||||||
|             if (!appLanguageValue.equals(appLanguageDefaultValue)) { |             if (!appLanguageValue.equals(appLanguageDefaultValue)) { | ||||||
|                 try { |                 try { | ||||||
|                         AppCompatDelegate.setApplicationLocales( |                     final var locales = LocaleListCompat.forLanguageTags(appLanguageValue); | ||||||
|                                 LocaleListCompat.forLanguageTags(appLanguageValue) |                     AppCompatDelegate.setApplicationLocales(locales); | ||||||
|                         ); |  | ||||||
|                 } catch (final RuntimeException e) { |                 } catch (final RuntimeException e) { | ||||||
|                     Log.e(TAG, "Failed to migrate previous custom app language " |                     Log.e(TAG, "Failed to migrate previous custom app language " | ||||||
|                             + "setting to public per-app language APIs" |                             + "setting to public per-app language APIs" | ||||||
| @@ -478,5 +465,4 @@ public final class Localization { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Isira Seneviratne
					Isira Seneviratne