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:rxandroid:2.1.0'
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-rxjava2:${roomDbLibVersion}"

View File

@ -99,7 +99,7 @@ public class App extends Application {
NewPipe.init(getDownloader(),
Localization.getPreferredLocalization(this),
Localization.getPreferredContentCountry(this));
Localization.init();
Localization.init(getApplicationContext());
StateSaver.init(this);
initNotificationChannel();

View File

@ -31,7 +31,6 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
@ -56,7 +55,6 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.navigation.NavigationView;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
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.util.Constants;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PeertubeHelper;
import org.schabi.newpipe.util.PermissionHelper;
@ -78,6 +77,8 @@ import org.schabi.newpipe.util.ThemeHelper;
import java.util.ArrayList;
import java.util.List;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
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) {
TLSSocketFactoryCompat.setAsDefault();
}
ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this));
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@ -419,6 +420,8 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onResume() {
assureCorrectAppLanguage(this);
Localization.init(getApplicationContext()); //change the date format to match the selected language on resume
super.onResume();
// 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.R;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class AboutActivity extends AppCompatActivity {
/**
@ -62,8 +63,10 @@ public class AboutActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this);
this.setTitle(getString(R.string.title_activity_about));
setContentView(R.layout.activity_about);

View File

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

View File

@ -12,12 +12,13 @@ import android.view.MenuItem;
import android.view.ViewTreeObserver;
import org.schabi.newpipe.R;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.ThemeHelper;
import us.shandian.giga.service.DownloadManagerService;
import us.shandian.giga.ui.fragment.MissionsFragment;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class DownloadActivity extends AppCompatActivity {
private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag";
@ -29,6 +30,7 @@ public class DownloadActivity extends AppCompatActivity {
i.setClass(this, DownloadManagerService.class);
startService(i);
assureCorrectAppLanguage(this);
ThemeHelper.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_downloader);

View File

@ -11,15 +11,6 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
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.SparseArray;
import android.view.LayoutInflater;
@ -34,6 +25,16 @@ import android.widget.Spinner;
import android.widget.TextView;
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 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.MissionState;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheckedChangeListener, AdapterView.OnItemSelectedListener {
private static final String TAG = "DialogFragment";
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) {
assureCorrectAppLanguage(getContext());
new AlertDialog.Builder(context)
.setTitle(R.string.general_error)
.setMessage(msg)
.setNegativeButton(android.R.string.ok, null)
.setNegativeButton(getString(R.string.finish), null)
.create()
.show();
}

View File

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

View File

@ -58,7 +58,7 @@ import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/**
* Base players joining the common properties
@ -115,7 +115,7 @@ public final class BackgroundPlayer extends Service {
notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
lockManager = new LockManager(this);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
assureCorrectAppLanguage(this);
ThemeHelper.setTheme(this);
basePlayerImpl = new BasePlayerImpl(this);
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.animateRotation;
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;
/**
@ -125,6 +126,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(this);
@ -192,6 +194,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
protected void onResume() {
if (DEBUG) Log.d(TAG, "onResume() called");
assureCorrectAppLanguage(this);
super.onResume();
if (globalScreenOrientationLocked()) {
@ -222,6 +225,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
assureCorrectAppLanguage(this);
if (playerImpl.isSomePopupMenuVisible()) {
playerImpl.getQualityPopupMenu().dismiss();
@ -366,8 +370,8 @@ public final class MainVideoPlayer extends AppCompatActivity
}
private boolean globalScreenOrientationLocked() {
// 1: Screen orientation changes using acelerometer
// 0: Screen orientatino is locked
// 1: Screen orientation changes using accelerometer
// 0: Screen orientation is locked
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_HIDE_TIME;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/**
* Service Popup Player implementing VideoPlayer
@ -142,6 +143,7 @@ public final class PopupVideoPlayer extends Service {
@Override
public void onCreate() {
assureCorrectAppLanguage(this);
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
notificationManager = ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
@ -169,6 +171,7 @@ public final class PopupVideoPlayer extends Service {
@Override
public void onConfigurationChanged(Configuration newConfig) {
assureCorrectAppLanguage(this);
if (DEBUG) Log.d(TAG, "onConfigurationChanged() called with: newConfig = [" + newConfig + "]");
updateScreenSize();
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.formatSpeed;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public abstract class ServicePlayerActivity extends AppCompatActivity
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
@ -116,6 +117,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this);
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 static org.schabi.newpipe.player.BasePlayer.DEBUG;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class PlaybackParameterDialog extends DialogFragment {
@NonNull private static final String TAG = "PlaybackParameterDialog";
@ -108,6 +109,7 @@ public class PlaybackParameterDialog extends DialogFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(getContext());
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
initialTempo = savedInstanceState.getDouble(INITIAL_TEMPO_KEY, DEFAULT_TEMPO);
@ -137,6 +139,7 @@ public class PlaybackParameterDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
assureCorrectAppLanguage(getContext());
final View view = View.inflate(getContext(), R.layout.dialog_playback_parameter, null);
setupControlViews(view);

View File

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

View File

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

View File

@ -8,11 +8,12 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.preference.Preference;
import android.util.Log;
import android.widget.Toast;
import com.nononsenseapps.filepicker.Utils;
@ -28,6 +29,8 @@ import java.nio.charset.StandardCharsets;
import us.shandian.giga.io.StoredDirectoryHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
public class DownloadSettingsFragment extends BasePreferenceFragment {
private static final int REQUEST_DOWNLOAD_VIDEO_PATH = 0x1235;
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);
msg.setTitle(title);
msg.setMessage(message);
msg.setPositiveButton(android.R.string.ok, null);
msg.setPositiveButton(getString(R.string.finish), null);
msg.show();
}
@ -202,6 +205,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
assureCorrectAppLanguage(getContext());
super.onActivityResult(requestCode, resultCode, data);
if (DEBUG) {
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.util.ThemeHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
/*
* Created by Christian Schabesberger on 31.08.15.
@ -44,7 +45,7 @@ public class SettingsActivity extends AppCompatActivity implements BasePreferenc
@Override
protected void onCreate(Bundle savedInstanceBundle) {
setTheme(ThemeHelper.getSettingsThemeStyle(this));
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceBundle);
setContentView(R.layout.settings_layout);

View File

@ -1,9 +1,17 @@
package org.schabi.newpipe.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.preference.PreferenceManager;
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.units.Decade;
@ -18,10 +26,6 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
/*
* Created by chschtsch on 12/29/15.
*
@ -50,8 +54,8 @@ public class Localization {
private Localization() {
}
public static void init() {
initPrettyTime();
public static void init(Context context) {
initPrettyTime(context);
}
@NonNull
@ -115,12 +119,13 @@ public class Localization {
return nf.format(number);
}
public static String formatDate(Date date) {
return DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).format(date);
public static String formatDate(Date date, Context context) {
return DateFormat.getDateInstance(DateFormat.MEDIUM, getAppLocale(context)).format(date);
}
@SuppressLint("StringFormatInvalid")
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) {
@ -199,21 +204,47 @@ public class Localization {
// Pretty Time
//////////////////////////////////////////////////////////////////////////*/
private static void initPrettyTime() {
prettyTime = new PrettyTime(Locale.getDefault());
private static void initPrettyTime(Context context) {
prettyTime = new PrettyTime(getAppLocale(context));
// Do not use decades as YouTube doesn't either.
prettyTime.removeUnit(Decade.class);
}
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;
}
public static String relativeTime(Calendar 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())
.create()
.show();

View File

@ -31,20 +31,20 @@
<string name="seek_duration_key" translatable="false">seek_duration</string>
<string name="seek_duration_default_value" translatable="false">10000</string>
<string-array name="seek_duration_description" translatable="false">
<item>5 seconds</item>
<item>10 seconds</item>
<item>15 seconds</item>
<item>20 seconds</item>
<item>25 seconds</item>
<item>30 seconds</item>
<item>5 seconds</item>
<item>10 seconds</item>
<item>15 seconds</item>
<item>20 seconds</item>
<item>25 seconds</item>
<item>30 seconds</item>
</string-array>
<string-array name="seek_duration_value" translatable="false">
<item>5000</item>
<item>10000</item>
<item>15000</item>
<item>20000</item>
<item>25000</item>
<item>30000</item>
<item>5000</item>
<item>10000</item>
<item>15000</item>
<item>20000</item>
<item>25000</item>
<item>30000</item>
</string-array>
<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="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="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="import_data" translatable="false">import_data</string>
@ -924,6 +926,138 @@
<item>ZW</item>
</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 -->
<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>

View File

@ -590,4 +590,6 @@
<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="choose_instance_prompt">Choose an instance</string>
<string name="app_language_title">App language</string>
<string name="systems_language">System default</string>
</resources>

View File

@ -3,6 +3,16 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
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
app:iconSpaceReserved="false"
android:defaultValue="@string/default_language_value"