Merge pull request #2921 from B0pol/dev

Add language selector to change the app language
This commit is contained in:
Tobias Groza 2020-02-01 15:47:13 +01:00 committed by GitHub
commit 14e852237f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 290 additions and 68 deletions

View File

@ -94,7 +94,7 @@ dependencies {
implementation 'io.reactivex.rxjava2:rxjava:2.2.2' implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1' implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.1.Final' implementation 'org.ocpsoft.prettytime:prettytime:4.0.3.Final'
implementation "androidx.room:room-runtime:${roomDbLibVersion}" implementation "androidx.room:room-runtime:${roomDbLibVersion}"
implementation "androidx.room:room-rxjava2:${roomDbLibVersion}" implementation "androidx.room:room-rxjava2:${roomDbLibVersion}"

View File

@ -99,7 +99,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.init(); Localization.init(getApplicationContext());
StateSaver.init(this); StateSaver.init(this);
initNotificationChannel(); initNotificationChannel();

View File

@ -31,7 +31,6 @@ import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
@ -56,7 +55,6 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance; import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
@ -67,6 +65,7 @@ import org.schabi.newpipe.fragments.list.search.SearchFragment;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PeertubeHelper; import org.schabi.newpipe.util.PeertubeHelper;
import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.PermissionHelper;
@ -78,6 +77,8 @@ import org.schabi.newpipe.util.ThemeHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity"; private static final String TAG = "MainActivity";
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release"); public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
@ -113,9 +114,9 @@ public class MainActivity extends AppCompatActivity {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
TLSSocketFactoryCompat.setAsDefault(); TLSSocketFactoryCompat.setAsDefault();
} }
ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this)); ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this));
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
@ -419,6 +420,8 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
protected void onResume() { protected void onResume() {
assureCorrectAppLanguage(this);
Localization.init(getApplicationContext()); //change the date format to match the selected language on resume
super.onResume(); super.onResume();
// close drawer on return, and don't show animation, so its looks like the drawer isn't open // close drawer on return, and don't show animation, so its looks like the drawer isn't open

View File

@ -22,9 +22,10 @@ import android.widget.TextView;
import org.schabi.newpipe.BuildConfig; import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class AboutActivity extends AppCompatActivity { public class AboutActivity extends AppCompatActivity {
/** /**
@ -62,8 +63,10 @@ public class AboutActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this); ThemeHelper.setTheme(this);
this.setTitle(getString(R.string.title_activity_about));
setContentView(R.layout.activity_about); setContentView(R.layout.activity_about);

View File

@ -3,6 +3,7 @@ package org.schabi.newpipe.about;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.AsyncTask; import android.os.AsyncTask;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -14,6 +15,8 @@ import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> { public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
final WeakReference<Activity> weakReference; final WeakReference<Activity> weakReference;
@ -55,15 +58,15 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
wv.loadData(webViewData, "text/html; charset=UTF-8", null); wv.loadData(webViewData, "text/html; charset=UTF-8", null);
alert.setView(wv); alert.setView(wv);
alert.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() { assureCorrectAppLanguage(activity.getApplicationContext());
@Override alert.setNegativeButton(getFinishString(activity), (dialog, which) -> dialog.dismiss());
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.show(); alert.show();
} }
private static String getFinishString(Activity activity) {
return activity.getApplicationContext().getResources().getString(R.string.finish);
}
/** /**
* @param context the context to use * @param context the context to use
* @param license the license * @param license the license

View File

@ -12,12 +12,13 @@ import android.view.MenuItem;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
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";
@ -29,6 +30,7 @@ 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);
setContentView(R.layout.activity_downloader); setContentView(R.layout.activity_downloader);

View File

@ -11,15 +11,6 @@ import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.DialogFragment;
import androidx.documentfile.provider.DocumentFile;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.menu.ActionMenuItemView;
import androidx.appcompat.widget.Toolbar;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -34,6 +25,16 @@ import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.menu.ActionMenuItemView;
import androidx.appcompat.widget.Toolbar;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.DialogFragment;
import com.nononsenseapps.filepicker.Utils; import com.nononsenseapps.filepicker.Utils;
import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.MainActivity;
@ -78,6 +79,8 @@ import us.shandian.giga.service.DownloadManagerService;
import us.shandian.giga.service.DownloadManagerService.DownloadManagerBinder; import us.shandian.giga.service.DownloadManagerService.DownloadManagerBinder;
import us.shandian.giga.service.MissionState; import us.shandian.giga.service.MissionState;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheckedChangeListener, AdapterView.OnItemSelectedListener { public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheckedChangeListener, AdapterView.OnItemSelectedListener {
private static final String TAG = "DialogFragment"; private static final String TAG = "DialogFragment";
private static final boolean DEBUG = MainActivity.DEBUG; private static final boolean DEBUG = MainActivity.DEBUG;
@ -527,10 +530,11 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
} }
private void showFailedDialog(@StringRes int msg) { private void showFailedDialog(@StringRes int msg) {
assureCorrectAppLanguage(getContext());
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setTitle(R.string.general_error) .setTitle(R.string.general_error)
.setMessage(msg) .setMessage(msg)
.setNegativeButton(android.R.string.ok, null) .setNegativeButton(getString(R.string.finish), null)
.create() .create()
.show(); .show();
} }

View File

@ -15,6 +15,8 @@ import org.schabi.newpipe.util.ThemeHelper;
import icepick.Icepick; import icepick.Icepick;
import icepick.State; import icepick.State;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class ImportConfirmationDialog extends DialogFragment { public class ImportConfirmationDialog extends DialogFragment {
@State @State
protected Intent resultServiceIntent; protected Intent resultServiceIntent;
@ -34,11 +36,12 @@ public class ImportConfirmationDialog extends DialogFragment {
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(getContext());
return new AlertDialog.Builder(getContext(), ThemeHelper.getDialogTheme(getContext())) return new AlertDialog.Builder(getContext(), ThemeHelper.getDialogTheme(getContext()))
.setMessage(R.string.import_network_expensive_warning) .setMessage(R.string.import_network_expensive_warning)
.setCancelable(true) .setCancelable(true)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { .setPositiveButton(R.string.finish, (dialogInterface, i) -> {
if (resultServiceIntent != null && getContext() != null) { if (resultServiceIntent != null && getContext() != null) {
getContext().startService(resultServiceIntent); getContext().startService(resultServiceIntent);
} }

View File

@ -58,7 +58,7 @@ import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString; import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/** /**
* Base players joining the common properties * Base players joining the common properties
@ -115,7 +115,7 @@ public final class BackgroundPlayer extends Service {
notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)); notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
lockManager = new LockManager(this); lockManager = new LockManager(this);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
assureCorrectAppLanguage(this);
ThemeHelper.setTheme(this); ThemeHelper.setTheme(this);
basePlayerImpl = new BasePlayerImpl(this); basePlayerImpl = new BasePlayerImpl(this);
basePlayerImpl.setup(); basePlayerImpl.setup();

View File

@ -95,6 +95,7 @@ import static org.schabi.newpipe.util.AnimationUtils.Type.SCALE_AND_ALPHA;
import static org.schabi.newpipe.util.AnimationUtils.Type.SLIDE_AND_ALPHA; import static org.schabi.newpipe.util.AnimationUtils.Type.SLIDE_AND_ALPHA;
import static org.schabi.newpipe.util.AnimationUtils.animateRotation; import static org.schabi.newpipe.util.AnimationUtils.animateRotation;
import static org.schabi.newpipe.util.AnimationUtils.animateView; import static org.schabi.newpipe.util.AnimationUtils.animateView;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
import static org.schabi.newpipe.util.StateSaver.KEY_SAVED_STATE; import static org.schabi.newpipe.util.StateSaver.KEY_SAVED_STATE;
/** /**
@ -125,6 +126,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]"); if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(this); defaultPreferences = PreferenceManager.getDefaultSharedPreferences(this);
@ -192,6 +194,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override @Override
protected void onResume() { protected void onResume() {
if (DEBUG) Log.d(TAG, "onResume() called"); if (DEBUG) Log.d(TAG, "onResume() called");
assureCorrectAppLanguage(this);
super.onResume(); super.onResume();
if (globalScreenOrientationLocked()) { if (globalScreenOrientationLocked()) {
@ -222,6 +225,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override @Override
public void onConfigurationChanged(Configuration newConfig) { public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
assureCorrectAppLanguage(this);
if (playerImpl.isSomePopupMenuVisible()) { if (playerImpl.isSomePopupMenuVisible()) {
playerImpl.getQualityPopupMenu().dismiss(); playerImpl.getQualityPopupMenu().dismiss();
@ -366,8 +370,8 @@ public final class MainVideoPlayer extends AppCompatActivity
} }
private boolean globalScreenOrientationLocked() { private boolean globalScreenOrientationLocked() {
// 1: Screen orientation changes using acelerometer // 1: Screen orientation changes using accelerometer
// 0: Screen orientatino is locked // 0: Screen orientation is locked
return !(android.provider.Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 1); return !(android.provider.Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
} }

View File

@ -80,6 +80,7 @@ import static org.schabi.newpipe.player.BasePlayer.STATE_PLAYING;
import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_DURATION; import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_DURATION;
import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME; import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME;
import static org.schabi.newpipe.util.AnimationUtils.animateView; import static org.schabi.newpipe.util.AnimationUtils.animateView;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/** /**
* Service Popup Player implementing VideoPlayer * Service Popup Player implementing VideoPlayer
@ -142,6 +143,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
assureCorrectAppLanguage(this);
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)); notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
@ -169,6 +171,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public void onConfigurationChanged(Configuration newConfig) { public void onConfigurationChanged(Configuration newConfig) {
assureCorrectAppLanguage(this);
if (DEBUG) Log.d(TAG, "onConfigurationChanged() called with: newConfig = [" + newConfig + "]"); if (DEBUG) Log.d(TAG, "onConfigurationChanged() called with: newConfig = [" + newConfig + "]");
updateScreenSize(); updateScreenSize();
updatePopupSize(popupLayoutParams.width, -1); updatePopupSize(popupLayoutParams.width, -1);

View File

@ -46,6 +46,7 @@ import java.util.List;
import static org.schabi.newpipe.player.helper.PlayerHelper.formatPitch; import static org.schabi.newpipe.player.helper.PlayerHelper.formatPitch;
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;
public abstract class ServicePlayerActivity extends AppCompatActivity public abstract class ServicePlayerActivity extends AppCompatActivity
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener, implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
@ -116,6 +117,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this); ThemeHelper.setTheme(this);
setContentView(R.layout.activity_player_queue_control); setContentView(R.layout.activity_player_queue_control);

View File

@ -17,6 +17,7 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.util.SliderStrategy; import org.schabi.newpipe.util.SliderStrategy;
import static org.schabi.newpipe.player.BasePlayer.DEBUG; import static org.schabi.newpipe.player.BasePlayer.DEBUG;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class PlaybackParameterDialog extends DialogFragment { public class PlaybackParameterDialog extends DialogFragment {
@NonNull private static final String TAG = "PlaybackParameterDialog"; @NonNull private static final String TAG = "PlaybackParameterDialog";
@ -108,6 +109,7 @@ public class PlaybackParameterDialog extends DialogFragment {
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(getContext());
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (savedInstanceState != null) { if (savedInstanceState != null) {
initialTempo = savedInstanceState.getDouble(INITIAL_TEMPO_KEY, DEFAULT_TEMPO); initialTempo = savedInstanceState.getDouble(INITIAL_TEMPO_KEY, DEFAULT_TEMPO);
@ -137,6 +139,7 @@ public class PlaybackParameterDialog extends DialogFragment {
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(getContext());
final View view = View.inflate(getContext(), R.layout.dialog_playback_parameter, null); final View view = View.inflate(getContext(), R.layout.dialog_playback_parameter, null);
setupControlViews(view); setupControlViews(view);

View File

@ -46,6 +46,8 @@ import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.Vector; import java.util.Vector;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/* /*
* Created by Christian Schabesberger on 24.10.15. * Created by Christian Schabesberger on 24.10.15.
* *
@ -171,6 +173,7 @@ public class ErrorActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this); ThemeHelper.setTheme(this);
setContentView(R.layout.activity_error); setContentView(R.layout.activity_error);

View File

@ -7,11 +7,12 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.Preference; import androidx.preference.Preference;
import android.util.Log;
import android.widget.Toast;
import com.nononsenseapps.filepicker.Utils; import com.nononsenseapps.filepicker.Utils;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
@ -40,6 +41,8 @@ import java.util.Map;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class ContentSettingsFragment extends BasePreferenceFragment { public class ContentSettingsFragment extends BasePreferenceFragment {
private static final int REQUEST_IMPORT_PATH = 8945; private static final int REQUEST_IMPORT_PATH = 8945;
@ -56,6 +59,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
private Localization initialSelectedLocalization; private Localization initialSelectedLocalization;
private ContentCountry initialSelectedContentCountry; private ContentCountry initialSelectedContentCountry;
private String initialLanguage;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
@ -64,6 +68,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
initialSelectedLocalization = org.schabi.newpipe.util.Localization.getPreferredLocalization(requireContext()); initialSelectedLocalization = org.schabi.newpipe.util.Localization.getPreferredLocalization(requireContext());
initialSelectedContentCountry = org.schabi.newpipe.util.Localization.getPreferredContentCountry(requireContext()); initialSelectedContentCountry = org.schabi.newpipe.util.Localization.getPreferredContentCountry(requireContext());
initialLanguage = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("app_language_key", "en");
} }
@Override @Override
@ -125,9 +130,10 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
.getPreferredLocalization(requireContext()); .getPreferredLocalization(requireContext());
final ContentCountry selectedContentCountry = org.schabi.newpipe.util.Localization final ContentCountry selectedContentCountry = org.schabi.newpipe.util.Localization
.getPreferredContentCountry(requireContext()); .getPreferredContentCountry(requireContext());
final String selectedLanguage = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("app_language_key", "en");
if (!selectedLocalization.equals(initialSelectedLocalization) if (!selectedLocalization.equals(initialSelectedLocalization)
|| !selectedContentCountry.equals(initialSelectedContentCountry)) { || !selectedContentCountry.equals(initialSelectedContentCountry) || !selectedLanguage.equals(initialLanguage)) {
Toast.makeText(requireContext(), R.string.localization_changes_requires_app_restart, Toast.LENGTH_LONG).show(); Toast.makeText(requireContext(), R.string.localization_changes_requires_app_restart, Toast.LENGTH_LONG).show();
NewPipe.setupLocalization(selectedLocalization, selectedContentCountry); NewPipe.setupLocalization(selectedLocalization, selectedContentCountry);
@ -136,6 +142,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, @NonNull Intent data) { public void onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
assureCorrectAppLanguage(getContext());
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]"); Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
@ -150,7 +157,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
} else { } else {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.override_current_data) builder.setMessage(R.string.override_current_data)
.setPositiveButton(android.R.string.ok, .setPositiveButton(getString(R.string.finish),
(DialogInterface d, int id) -> importDatabase(path)) (DialogInterface d, int id) -> importDatabase(path))
.setNegativeButton(android.R.string.cancel, .setNegativeButton(android.R.string.cancel,
(DialogInterface d, int id) -> d.cancel()); (DialogInterface d, int id) -> d.cancel());
@ -189,7 +196,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
}finally { } finally {
try { try {
if (output != null) { if (output != null) {
output.flush(); output.flush();
@ -236,7 +243,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
} }
//If settings file exist, ask if it should be imported. //If settings file exist, ask if it should be imported.
if(ZipHelper.extractFileFromZip(filePath, newpipe_settings.getPath(), "newpipe.settings")) { if (ZipHelper.extractFileFromZip(filePath, newpipe_settings.getPath(), "newpipe.settings")) {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext()); AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle(R.string.import_settings); alert.setTitle(R.string.import_settings);
@ -245,7 +252,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
// restart app to properly load db // restart app to properly load db
System.exit(0); System.exit(0);
}); });
alert.setPositiveButton(android.R.string.yes, (dialog, which) -> { alert.setPositiveButton(getString(R.string.finish), (dialog, which) -> {
dialog.dismiss(); dialog.dismiss();
loadSharedPreferences(newpipe_settings); loadSharedPreferences(newpipe_settings);
// restart app to properly load db // restart app to properly load db
@ -291,7 +298,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
e.printStackTrace(); e.printStackTrace();
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
}finally { } finally {
try { try {
if (input != null) { if (input != null) {
input.close(); input.close();

View File

@ -8,11 +8,12 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.preference.Preference; import androidx.preference.Preference;
import android.util.Log;
import android.widget.Toast;
import com.nononsenseapps.filepicker.Utils; import com.nononsenseapps.filepicker.Utils;
@ -28,6 +29,8 @@ import java.nio.charset.StandardCharsets;
import us.shandian.giga.io.StoredDirectoryHelper; import us.shandian.giga.io.StoredDirectoryHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class DownloadSettingsFragment extends BasePreferenceFragment { public class DownloadSettingsFragment extends BasePreferenceFragment {
private static final int REQUEST_DOWNLOAD_VIDEO_PATH = 0x1235; private static final int REQUEST_DOWNLOAD_VIDEO_PATH = 0x1235;
private static final int REQUEST_DOWNLOAD_AUDIO_PATH = 0x1236; private static final int REQUEST_DOWNLOAD_AUDIO_PATH = 0x1236;
@ -159,7 +162,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
AlertDialog.Builder msg = new AlertDialog.Builder(ctx); AlertDialog.Builder msg = new AlertDialog.Builder(ctx);
msg.setTitle(title); msg.setTitle(title);
msg.setMessage(message); msg.setMessage(message);
msg.setPositiveButton(android.R.string.ok, null); msg.setPositiveButton(getString(R.string.finish), null);
msg.show(); msg.show();
} }
@ -202,6 +205,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
assureCorrectAppLanguage(getContext());
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], " + Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], " +

View File

@ -14,6 +14,7 @@ import android.view.MenuItem;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/* /*
* Created by Christian Schabesberger on 31.08.15. * Created by Christian Schabesberger on 31.08.15.
@ -44,7 +45,7 @@ public class SettingsActivity extends AppCompatActivity implements BasePreferenc
@Override @Override
protected void onCreate(Bundle savedInstanceBundle) { protected void onCreate(Bundle savedInstanceBundle) {
setTheme(ThemeHelper.getSettingsThemeStyle(this)); setTheme(ThemeHelper.getSettingsThemeStyle(this));
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceBundle); super.onCreate(savedInstanceBundle);
setContentView(R.layout.settings_layout); setContentView(R.layout.settings_layout);

View File

@ -1,9 +1,17 @@
package org.schabi.newpipe.util; package org.schabi.newpipe.util;
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.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.DisplayMetrics;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
import org.ocpsoft.prettytime.PrettyTime; import org.ocpsoft.prettytime.PrettyTime;
import org.ocpsoft.prettytime.units.Decade; import org.ocpsoft.prettytime.units.Decade;
@ -18,10 +26,6 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
/* /*
* Created by chschtsch on 12/29/15. * Created by chschtsch on 12/29/15.
* *
@ -50,8 +54,8 @@ public class Localization {
private Localization() { private Localization() {
} }
public static void init() { public static void init(Context context) {
initPrettyTime(); initPrettyTime(context);
} }
@NonNull @NonNull
@ -115,12 +119,13 @@ public class Localization {
return nf.format(number); return nf.format(number);
} }
public static String formatDate(Date date) { public static String formatDate(Date date, Context context) {
return DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).format(date); return DateFormat.getDateInstance(DateFormat.MEDIUM, getAppLocale(context)).format(date);
} }
@SuppressLint("StringFormatInvalid")
public static String localizeUploadDate(Context context, Date date) { public static String localizeUploadDate(Context context, Date date) {
return context.getString(R.string.upload_date_text, formatDate(date)); return context.getString(R.string.upload_date_text, formatDate(date, context));
} }
public static String localizeViewCount(Context context, long viewCount) { public static String localizeViewCount(Context context, long viewCount) {
@ -199,21 +204,47 @@ public class Localization {
// Pretty Time // Pretty Time
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private static void initPrettyTime() { private static void initPrettyTime(Context context) {
prettyTime = new PrettyTime(Locale.getDefault()); prettyTime = new PrettyTime(getAppLocale(context));
// Do not use decades as YouTube doesn't either. // Do not use decades as YouTube doesn't either.
prettyTime.removeUnit(Decade.class); prettyTime.removeUnit(Decade.class);
} }
private static PrettyTime getPrettyTime() { private static PrettyTime getPrettyTime() {
// If pretty time's Locale is different, init again with the new one.
if (!prettyTime.getLocale().equals(Locale.getDefault())) {
initPrettyTime();
}
return prettyTime; return prettyTime;
} }
public static String relativeTime(Calendar calendarTime) { public static String relativeTime(Calendar calendarTime) {
return getPrettyTime().formatUnrounded(calendarTime); return getPrettyTime().formatUnrounded(calendarTime);
} }
private static void changeAppLanguage(Locale loc, Resources res) {
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.setLocale(loc);
res.updateConfiguration(conf, dm);
}
public static Locale getAppLocale(Context context) {
SharedPreferences prefs = androidx.preference.PreferenceManager.getDefaultSharedPreferences(context);
String lang = prefs.getString("app_language_key", "en");
Locale loc;
if (lang.equals("system")) {
loc = Locale.getDefault();
} else if (lang.matches(".*-.*")) {
//to differentiate different versions of the language
//for example, pt (portuguese in Portugal) and pt-br (portuguese in Brazil)
String[] localisation = lang.split("-");
lang = localisation[0];
String country = localisation[1];
loc = new Locale(lang, country);
} else {
loc = new Locale(lang);
}
return loc;
}
public static void assureCorrectAppLanguage(Context c) {
changeAppLanguage(getAppLocale(c), c.getResources());
}
} }

View File

@ -534,7 +534,7 @@ public class MissionAdapter extends Adapter<ViewHolder> implements Handler.Callb
); );
} }
builder.setNegativeButton(android.R.string.ok, (dialog, which) -> dialog.cancel()) builder.setNegativeButton(R.string.finish, (dialog, which) -> dialog.cancel())
.setTitle(mission.storage.getName()) .setTitle(mission.storage.getName())
.create() .create()
.show(); .show();

View File

@ -31,20 +31,20 @@
<string name="seek_duration_key" translatable="false">seek_duration</string> <string name="seek_duration_key" translatable="false">seek_duration</string>
<string name="seek_duration_default_value" translatable="false">10000</string> <string name="seek_duration_default_value" translatable="false">10000</string>
<string-array name="seek_duration_description" translatable="false"> <string-array name="seek_duration_description" translatable="false">
<item>5 seconds</item> <item>5 seconds</item>
<item>10 seconds</item> <item>10 seconds</item>
<item>15 seconds</item> <item>15 seconds</item>
<item>20 seconds</item> <item>20 seconds</item>
<item>25 seconds</item> <item>25 seconds</item>
<item>30 seconds</item> <item>30 seconds</item>
</string-array> </string-array>
<string-array name="seek_duration_value" translatable="false"> <string-array name="seek_duration_value" translatable="false">
<item>5000</item> <item>5000</item>
<item>10000</item> <item>10000</item>
<item>15000</item> <item>15000</item>
<item>20000</item> <item>20000</item>
<item>25000</item> <item>25000</item>
<item>30000</item> <item>30000</item>
</string-array> </string-array>
<string name="minimize_on_exit_key" translatable="false">minimize_on_exit_key</string> <string name="minimize_on_exit_key" translatable="false">minimize_on_exit_key</string>
@ -175,6 +175,8 @@
<string name="main_page_content_key" translatable="false">main_page_content</string> <string name="main_page_content_key" translatable="false">main_page_content</string>
<string name="enable_playback_resume_key" translatable="false">enable_playback_resume</string> <string name="enable_playback_resume_key" translatable="false">enable_playback_resume</string>
<string name="enable_playback_state_lists_key" translatable="false">enable_playback_state_lists</string> <string name="enable_playback_state_lists_key" translatable="false">enable_playback_state_lists</string>
<string name="app_language_key" translatable="false">app_language_key</string>
<string name="enable_lock_screen_video_thumbnail_key" translatable="false">enable_lock_screen_video_thumbnail</string> <string name="enable_lock_screen_video_thumbnail_key" translatable="false">enable_lock_screen_video_thumbnail</string>
<string name="import_data" translatable="false">import_data</string> <string name="import_data" translatable="false">import_data</string>
@ -924,6 +926,138 @@
<item>ZW</item> <item>ZW</item>
</string-array> </string-array>
<!--The next two arrays are set to change the app language-->
<string-array name="app_language_code" translatable="false">
<item>system</item>
<item>ar</item>
<item>az</item>
<item>ast</item>
<item>be</item>
<item>bg-bd</item>
<item>bn</item>
<item>ca</item>
<item>cs</item>
<item>da</item>
<item>de</item>
<item>el</item>
<item>en</item>
<item>eo</item>
<item>es</item>
<item>et</item>
<item>eu</item>
<item>fa</item>
<item>fi</item>
<item>fil</item>
<item>fr</item>
<item>gl</item>
<item>he</item>
<item>hi</item>
<item>hr</item>
<item>hu</item>
<item>hy</item>
<item>ia</item>
<item>in</item>
<item>it</item>
<item>ja</item>
<item>ko</item>
<item>ku</item>
<item>lt</item>
<item>mk</item>
<item>ms</item>
<item>nb-no</item>
<item>ne</item>
<item>nl</item>
<item>nl-be</item>
<item>oc</item>
<item>pa</item>
<item>pl</item>
<item>pr</item>
<item>pt</item>
<item>pt-br</item>
<item>ro</item>
<item>ru</item>
<item>sk</item>
<item>sl</item>
<item>sq</item>
<item>sr</item>
<item>sv</item>
<item>ta</item>
<item>te</item>
<item>th</item>
<item>tr</item>
<item>uk</item>
<item>ur</item>
<item>vi</item>
<item>zh</item>
<item>zh-hans</item>
<item>zh-tw</item>
</string-array>
<string-array name="app_language_name" translatable="false">
<item>@string/systems_language</item>
<item>العربية</item>
<item>Azərbaycan dili</item>
<item>Asturianu</item>
<item>Беларуская</item>
<item>български език</item>
<item>বাংলা</item>
<item>Català</item>
<item>Čeština</item>
<item>Dansk</item>
<item>Deutsch</item>
<item>Ελληνικά</item>
<item>English</item>
<item>Esperanto</item>
<item>Español</item>
<item>Eesti keel</item>
<item>Euskara</item>
<item>فارسی</item>
<item>Suomen kieli</item>
<item>Wikang Filipino</item>
<item>Français</item>
<item>Galego</item>
<item>עברית</item>
<item>हिन्दी</item>
<item>Hrvatski</item>
<item>magyar</item>
<item>Հայերեն</item>
<item>Interlingua</item>
<item>Bahasa Indonesia</item>
<item>Italiano</item>
<item>日本語</item>
<item>한국어</item>
<item>کوردی</item>
<item>Lietuvių kalba</item>
<item>македонски јазик</item>
<item>Bahasa Melayu</item>
<item>Norsk bokmål</item>
<item>Nनेपाली</item>
<item>Nederlands (NL)</item>
<item>Nederlands (BE)</item>
<item>Occitan</item>
<item>ਪੰਜਾਬੀ</item>
<item>Polski</item>
<item>Pirate Language</item>
<item>Português (PT)</item>
<item>Português (BR)</item>
<item>Română</item>
<item>русский язык</item>
<item>Slovenčina</item>
<item>Slovenščina</item>
<item>Shqip</item>
<item>Српски</item>
<item>Svenska</item>
<item>தமிழ்</item>
<item>తెలుగు</item>
<item>ไทย</item>
<item>Türkçe</item>
<item>українська мова</item>
<item>اردو</item>
<item>Tiếng Việt</item>
<item>官话</item>
<item>简化字</item>
<item>臺灣華語</item>
</string-array>
<!-- Limit mobile data usage --> <!-- Limit mobile data usage -->
<string name="limit_mobile_data_usage_key" translatable="false">limit_mobile_data_usage</string> <string name="limit_mobile_data_usage_key" translatable="false">limit_mobile_data_usage</string>
<string name="limit_data_usage_none_key" translatable="false">limit_data_usage_none</string> <string name="limit_data_usage_none_key" translatable="false">limit_data_usage_none</string>

View File

@ -590,4 +590,6 @@
<string name="downloads_storage_use_saf_title">Use SAF</string> <string name="downloads_storage_use_saf_title">Use SAF</string>
<string name="downloads_storage_use_saf_summary">The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible</string> <string name="downloads_storage_use_saf_summary">The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible</string>
<string name="choose_instance_prompt">Choose an instance</string> <string name="choose_instance_prompt">Choose an instance</string>
<string name="app_language_title">App language</string>
<string name="systems_language">System default</string>
</resources> </resources>

View File

@ -3,6 +3,16 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/content"> android:title="@string/content">
<ListPreference
app:iconSpaceReserved="false"
android:defaultValue="system"
android:entries="@array/app_language_name"
android:entryValues="@array/app_language_code"
android:key="@string/app_language_key"
android:summary="%s"
android:title="@string/app_language_title"/>
<ListPreference <ListPreference
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
android:defaultValue="@string/default_language_value" android:defaultValue="@string/default_language_value"