NewPipe/app/src/main/java/org/schabi/newpipe/util/Localization.java

270 lines
11 KiB
Java
Raw Normal View History

2017-05-08 15:28:33 +02:00
package org.schabi.newpipe.util;
2015-12-29 15:35:51 +01:00
import android.annotation.SuppressLint;
2015-12-29 15:35:51 +01:00
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
2015-12-29 15:35:51 +01:00
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
2015-12-29 15:35:51 +01:00
import org.ocpsoft.prettytime.PrettyTime;
import org.ocpsoft.prettytime.units.Decade;
2017-05-08 15:28:33 +02:00
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.localization.ContentCountry;
2017-05-08 15:28:33 +02:00
import java.math.BigDecimal;
import java.math.RoundingMode;
2015-12-29 15:35:51 +01:00
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Calendar;
2015-12-29 15:35:51 +01:00
import java.util.Date;
import java.util.List;
2015-12-29 15:35:51 +01:00
import java.util.Locale;
/*
2015-12-29 15:35:51 +01:00
* Created by chschtsch on 12/29/15.
*
* Copyright (C) Gregory Arkhipov 2015
* Localization.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
2015-12-29 15:35:51 +01:00
*/
public class Localization {
private static final String DOT_SEPARATOR = "";
private static PrettyTime prettyTime;
private Localization() {
}
public static void init(Context context) {
initPrettyTime(context);
}
@NonNull
public static String concatenateStrings(final String... strings) {
return concatenateStrings(Arrays.asList(strings));
}
@NonNull
public static String concatenateStrings(final List<String> strings) {
if (strings.isEmpty()) return "";
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(strings.get(0));
for (int i = 1; i < strings.size(); i++) {
final String string = strings.get(i);
if (!TextUtils.isEmpty(string)) {
stringBuilder.append(DOT_SEPARATOR).append(strings.get(i));
}
}
return stringBuilder.toString();
}
public static org.schabi.newpipe.extractor.localization.Localization getPreferredLocalization(final Context context) {
final String contentLanguage = PreferenceManager
.getDefaultSharedPreferences(context)
2020-02-15 16:29:46 +01:00
.getString(context.getString(R.string.content_language_key), context.getString(R.string.default_localization_key));
if (contentLanguage.equals(context.getString(R.string.default_localization_key))) {
return org.schabi.newpipe.extractor.localization.Localization.fromLocale(Locale.getDefault());
}
return org.schabi.newpipe.extractor.localization.Localization.fromLocalizationCode(contentLanguage);
}
public static ContentCountry getPreferredContentCountry(final Context context) {
final String contentCountry = PreferenceManager
.getDefaultSharedPreferences(context)
2020-02-15 16:29:46 +01:00
.getString(context.getString(R.string.content_country_key), context.getString(R.string.default_localization_key));
if (contentCountry.equals(context.getString(R.string.default_localization_key))) {
return new ContentCountry(Locale.getDefault().getCountry());
}
return new ContentCountry(contentCountry);
}
2015-12-29 15:35:51 +01:00
public static Locale getPreferredLocale(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
String languageCode = sp.getString(context.getString(R.string.content_language_key),
2020-02-15 16:29:46 +01:00
context.getString(R.string.default_localization_key));
2015-12-29 15:35:51 +01:00
try {
if (languageCode.length() == 2) {
return new Locale(languageCode);
} else if (languageCode.contains("_")) {
String country = languageCode.substring(languageCode.indexOf("_"));
return new Locale(languageCode.substring(0, 2), country);
}
} catch (Exception ignored) {
2015-12-29 15:35:51 +01:00
}
return Locale.getDefault();
2015-12-29 15:35:51 +01:00
}
public static String localizeNumber(Context context, long number) {
return localizeNumber(context, (double) number);
}
public static String localizeNumber(Context context, double number) {
NumberFormat nf = NumberFormat.getInstance(getAppLocale(context));
2015-12-29 15:35:51 +01:00
return nf.format(number);
}
public static String formatDate(Date date, Context context) {
return DateFormat.getDateInstance(DateFormat.MEDIUM, getAppLocale(context)).format(date);
2015-12-29 15:35:51 +01:00
}
@SuppressLint("StringFormatInvalid")
public static String localizeUploadDate(Context context, Date date) {
return context.getString(R.string.upload_date_text, formatDate(date, context));
2015-12-29 15:35:51 +01:00
}
public static String localizeViewCount(Context context, long viewCount) {
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount, localizeNumber(context, viewCount));
}
public static String localizeStreamCount(Context context, long streamCount) {
return getQuantity(context, R.plurals.videos, R.string.no_videos, streamCount, localizeNumber(context, streamCount));
}
public static String localizeWatchingCount(Context context, long watchingCount) {
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount, localizeNumber(context, watchingCount));
}
public static String shortCount(Context context, long count) {
double value = (double) count;
if (count >= 1000000000) {
return localizeNumber(context, round(value / 1000000000, 1)) + context.getString(R.string.short_billion);
} else if (count >= 1000000) {
return localizeNumber(context, round(value / 1000000, 1)) + context.getString(R.string.short_million);
} else if (count >= 1000) {
return localizeNumber(context, round(value / 1000, 1)) + context.getString(R.string.short_thousand);
} else {
return localizeNumber(context, value);
}
}
public static String listeningCount(Context context, long listeningCount) {
return getQuantity(context, R.plurals.listening, R.string.no_one_listening, listeningCount, shortCount(context, listeningCount));
}
public static String shortWatchingCount(Context context, long watchingCount) {
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount, shortCount(context, watchingCount));
}
public static String shortViewCount(Context context, long viewCount) {
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount, shortCount(context, viewCount));
}
public static String shortSubscriberCount(Context context, long subscriberCount) {
return getQuantity(context, R.plurals.subscribers, R.string.no_subscribers, subscriberCount, shortCount(context, subscriberCount));
}
private static String getQuantity(Context context, @PluralsRes int pluralId, @StringRes int zeroCaseStringId, long count, String formattedCount) {
if (count == 0) return context.getString(zeroCaseStringId);
// As we use the already formatted count, is not the responsibility of this method handle long numbers
// (it probably will fall in the "other" category, or some language have some specific rule... then we have to change it)
int safeCount = count > Integer.MAX_VALUE ? Integer.MAX_VALUE : count < Integer.MIN_VALUE ? Integer.MIN_VALUE : (int) count;
return context.getResources().getQuantityString(pluralId, safeCount, formattedCount);
}
public static String getDurationString(long duration) {
if (duration < 0) {
duration = 0;
}
String output;
long days = duration / (24 * 60 * 60L); /* greater than a day */
duration %= (24 * 60 * 60L);
long hours = duration / (60 * 60L); /* greater than an hour */
duration %= (60 * 60L);
long minutes = duration / 60L;
long seconds = duration % 60L;
//handle days
if (days > 0) {
output = String.format(Locale.US, "%d:%02d:%02d:%02d", days, hours, minutes, seconds);
} else if (hours > 0) {
output = String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds);
} else {
output = String.format(Locale.US, "%d:%02d", minutes, seconds);
}
return output;
}
/*//////////////////////////////////////////////////////////////////////////
// Pretty Time
//////////////////////////////////////////////////////////////////////////*/
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() {
return prettyTime;
}
public static String relativeTime(Calendar calendarTime) {
String time = getPrettyTime().formatUnrounded(calendarTime);
return time.startsWith("-") ? time.substring(1) : time;
//workaround fix for russian showing -1 day ago, -19hrs ago…
}
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 = PreferenceManager.getDefaultSharedPreferences(context);
String lang = prefs.getString(context.getString(R.string.app_language_key), "en");
Locale loc;
2020-02-15 16:29:46 +01:00
if (lang.equals(context.getString(R.string.default_localization_key))) {
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());
}
private static double round(double value, int places) {
return new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue();
}
2015-12-29 15:35:51 +01:00
}