NekoX/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java

2972 lines
125 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
package org.telegram.messenger;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Xml;
import android.view.Gravity;
import org.telegram.messenger.support.ArrayUtils;
import org.telegram.messenger.time.FastDateFormat;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.xmlpull.v1.XmlPullParser;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.TimeZone;
import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.utils.FileUtil;
public class LocaleController {
static final int QUANTITY_OTHER = 0x0000;
static final int QUANTITY_ZERO = 0x0001;
static final int QUANTITY_ONE = 0x0002;
static final int QUANTITY_TWO = 0x0004;
static final int QUANTITY_FEW = 0x0008;
static final int QUANTITY_MANY = 0x0010;
public static boolean isRTL = false;
public static int generateFlagStart() {
return isRTL ? Gravity.RIGHT : Gravity.LEFT;
}
public static boolean is24HourFormat = false;
public FastDateFormat formatterDay;
public FastDateFormat formatterWeek;
public FastDateFormat formatterDayMonth;
public FastDateFormat formatterYear;
public FastDateFormat formatterYearMax;
public FastDateFormat formatterStats;
public FastDateFormat formatterBannedUntil;
public FastDateFormat formatterBannedUntilThisYear;
public FastDateFormat chatDate;
public FastDateFormat chatFullDate;
public FastDateFormat formatterScheduleDay;
public FastDateFormat formatterScheduleYear;
public FastDateFormat[] formatterScheduleSend = new FastDateFormat[6];
private HashMap<String, PluralRules> allRules = new HashMap<>();
public Locale currentLocale;
private Locale systemDefaultLocale;
private PluralRules currentPluralRules;
private LocaleInfo currentLocaleInfo;
private HashMap<String, String> localeValues = new HashMap<>();
private String languageOverride;
private boolean changingConfiguration = false;
private boolean reloadLastFile;
private String currentSystemLocale;
private HashMap<String, String> currencyValues;
private HashMap<String, String> translitChars;
private HashMap<String, String> ruTranslitChars;
private class TimeZoneChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ApplicationLoader.applicationHandler.post(() -> {
if (!formatterDayMonth.getTimeZone().equals(TimeZone.getDefault())) {
LocaleController.getInstance().recreateFormatters();
}
});
}
}
public static class LocaleInfo {
public String name;
public String nameEnglish;
public String shortName;
public String pathToFile;
public String baseLangCode;
public String pluralLangCode;
public boolean isRtl;
public int version;
public int baseVersion;
public boolean builtIn;
public int serverIndex;
public TLRPC.TL_langPackLanguage pack;
public boolean toInstall;
public String getSaveString() {
String langCode = baseLangCode == null ? "" : baseLangCode;
String pluralCode = TextUtils.isEmpty(pluralLangCode) ? shortName : pluralLangCode;
return name + "|" + nameEnglish + "|" + shortName + "|" + pathToFile + "|" + version + "|" + langCode + "|" + pluralLangCode + "|" + (isRtl ? 1 : 0) + "|" + baseVersion + "|" + serverIndex;
}
public static LocaleInfo createWithString(String string) {
if (string == null || string.length() == 0) {
return null;
}
String[] args = string.split("\\|");
LocaleInfo localeInfo = null;
if (args.length >= 4) {
localeInfo = new LocaleInfo();
localeInfo.name = args[0];
localeInfo.nameEnglish = args[1];
localeInfo.shortName = args[2].toLowerCase();
localeInfo.pathToFile = args[3];
if (args.length >= 5) {
localeInfo.version = Utilities.parseInt(args[4]);
}
localeInfo.baseLangCode = args.length >= 6 ? args[5] : "";
localeInfo.pluralLangCode = args.length >= 7 ? args[6] : localeInfo.shortName;
if (args.length >= 8) {
localeInfo.isRtl = Utilities.parseInt(args[7]) == 1;
}
if (args.length >= 9) {
localeInfo.baseVersion = Utilities.parseInt(args[8]);
}
if (args.length >= 10) {
localeInfo.serverIndex = Utilities.parseInt(args[9]);
} else {
localeInfo.serverIndex = Integer.MAX_VALUE;
}
if (!TextUtils.isEmpty(localeInfo.baseLangCode)) {
localeInfo.baseLangCode = localeInfo.baseLangCode.replace("-", "_");
}
}
return localeInfo;
}
public File getPathToFile() {
File baseDir = new File(ApplicationLoader.getDataDirFixed(), "languages");
FileUtil.initDir(baseDir);
if (isRemote()) {
return new File(baseDir, "remote_" + shortName + ".xml");
} else if (isUnofficial()) {
return new File(baseDir, "unofficial_" + shortName + ".xml");
}
return !TextUtils.isEmpty(pathToFile) ? new File(pathToFile) : null;
}
public File getPathToBaseFile() {
if (isUnofficial()) {
File baseDir = new File(ApplicationLoader.getDataDirFixed(), "languages");
FileUtil.initDir(baseDir);
return new File(baseDir, "unofficial_base_" + shortName + ".xml");
}
return null;
}
public String getKey() {
if (pathToFile != null && !isRemote() && !isUnofficial()) {
return "local_" + shortName;
} else if (isUnofficial()) {
return "unofficial_" + shortName;
}
return shortName;
}
public boolean hasBaseLang() {
return isUnofficial() && !TextUtils.isEmpty(baseLangCode) && !baseLangCode.equals(shortName);
}
public boolean isRemote() {
return "remote".equals(pathToFile);
}
public boolean isUnofficial() {
return "unofficial".equals(pathToFile);
}
public boolean isLocal() {
return !TextUtils.isEmpty(pathToFile) && !isRemote() && !isUnofficial();
}
public boolean isBuiltIn() {
return builtIn;
}
public String getLangCode() {
return shortName.replace("_", "-");
}
public String getBaseLangCode() {
return baseLangCode == null ? "" : baseLangCode.replace("_", "-");
}
}
private boolean loadingRemoteLanguages;
public ArrayList<LocaleInfo> languages = new ArrayList<>();
public ArrayList<LocaleInfo> unofficialLanguages = new ArrayList<>();
public ArrayList<LocaleInfo> remoteLanguages = new ArrayList<>();
public HashMap<String, LocaleInfo> remoteLanguagesDict = new HashMap<>();
public HashMap<String, LocaleInfo> languagesDict = new HashMap<>();
private ArrayList<LocaleInfo> otherLanguages = new ArrayList<>();
private static volatile LocaleController Instance = null;
public static LocaleController getInstance() {
LocaleController localInstance = Instance;
if (localInstance == null) {
synchronized (LocaleController.class) {
localInstance = Instance;
if (localInstance == null) {
Instance = localInstance = new LocaleController();
}
}
}
if (localInstance.formatterDay == null || localInstance.chatFullDate == null)
localInstance.recreateFormatters();
return localInstance;
}
public LocaleController() {
addRules(new String[]{"bem", "brx", "da", "de", "el", "en", "eo", "es", "et", "fi", "fo", "gl", "he", "iw", "it", "nb",
"nl", "nn", "no", "sv", "af", "bg", "bn", "ca", "eu", "fur", "fy", "gu", "ha", "is", "ku",
"lb", "ml", "mr", "nah", "ne", "om", "or", "pa", "pap", "ps", "so", "sq", "sw", "ta", "te",
"tk", "ur", "zu", "mn", "gsw", "chr", "rm", "pt", "an", "ast"}, new PluralRules_One());
addRules(new String[]{"cs", "sk"}, new PluralRules_Czech());
addRules(new String[]{"ff", "fr", "kab"}, new PluralRules_French());
addRules(new String[]{"hr", "ru", "sr", "uk", "be", "bs", "sh"}, new PluralRules_Balkan());
addRules(new String[]{"lv"}, new PluralRules_Latvian());
addRules(new String[]{"lt"}, new PluralRules_Lithuanian());
addRules(new String[]{"pl"}, new PluralRules_Polish());
addRules(new String[]{"ro", "mo"}, new PluralRules_Romanian());
addRules(new String[]{"sl"}, new PluralRules_Slovenian());
addRules(new String[]{"ar"}, new PluralRules_Arabic());
addRules(new String[]{"mk"}, new PluralRules_Macedonian());
addRules(new String[]{"cy"}, new PluralRules_Welsh());
addRules(new String[]{"br"}, new PluralRules_Breton());
addRules(new String[]{"lag"}, new PluralRules_Langi());
addRules(new String[]{"shi"}, new PluralRules_Tachelhit());
addRules(new String[]{"mt"}, new PluralRules_Maltese());
addRules(new String[]{"ga", "se", "sma", "smi", "smj", "smn", "sms"}, new PluralRules_Two());
addRules(new String[]{"ak", "am", "bh", "fil", "tl", "guw", "hi", "ln", "mg", "nso", "ti", "wa"}, new PluralRules_Zero());
addRules(new String[]{"az", "bm", "fa", "ig", "hu", "ja", "kde", "kea", "ko", "my", "ses", "sg", "to",
"tr", "vi", "wo", "yo", "zh", "bo", "dz", "id", "jv", "jw", "ka", "km", "kn", "ms", "th", "in"}, new PluralRules_None());
LocaleInfo localeInfo = new LocaleInfo();
localeInfo.name = "English";
localeInfo.nameEnglish = "English";
localeInfo.shortName = localeInfo.pluralLangCode = "en";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "Italiano";
localeInfo.nameEnglish = "Italian";
localeInfo.shortName = localeInfo.pluralLangCode = "it";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "Español";
localeInfo.nameEnglish = "Spanish";
localeInfo.shortName = localeInfo.pluralLangCode = "es";
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "Deutsch";
localeInfo.nameEnglish = "German";
localeInfo.shortName = localeInfo.pluralLangCode = "de";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "Nederlands";
localeInfo.nameEnglish = "Dutch";
localeInfo.shortName = localeInfo.pluralLangCode = "nl";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "العربية";
localeInfo.nameEnglish = "Arabic";
localeInfo.shortName = localeInfo.pluralLangCode = "ar";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
localeInfo.isRtl = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "Português (Brasil)";
localeInfo.nameEnglish = "Portuguese (Brazil)";
localeInfo.shortName = localeInfo.pluralLangCode = "pt_br";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "한국어";
localeInfo.nameEnglish = "Korean";
localeInfo.shortName = localeInfo.pluralLangCode = "ko";
localeInfo.pathToFile = null;
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.shortName, localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "简体中文 ( NekoX )";
localeInfo.nameEnglish = "Simplified Chinese ( NekoX )";
localeInfo.shortName = "nekox_zh_cn";
localeInfo.baseLangCode = "zh_hans_raw";
localeInfo.isRtl = false;
localeInfo.pathToFile = "unofficial";
localeInfo.pluralLangCode = "zh_cn";
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
languagesDict.put("zh_cn", localeInfo);
languagesDict.put("zh_sg", localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "瓜体中文 \uD83D\uDE36";
localeInfo.nameEnglish = "Duangified Chinese (Simplified)";
localeInfo.shortName = "duang_zh_hans";
localeInfo.baseLangCode = "zh_hans_raw";
localeInfo.isRtl = false;
localeInfo.pathToFile = "unofficial";
localeInfo.pluralLangCode = "zh_duang";
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "正體中文";
localeInfo.nameEnglish = "Chinese (zh-Hant-TW)";
localeInfo.shortName = "taiwan";
localeInfo.baseLangCode = "zh_hant_raw";
localeInfo.isRtl = false;
localeInfo.pathToFile = "unofficial";
localeInfo.pluralLangCode = "zh_tw";
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
languagesDict.put("zh_tw", localeInfo);
languagesDict.put("zh_hk", localeInfo);
languagesDict.put("zh_mo", localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "日本語";
localeInfo.nameEnglish = "Japanese";
localeInfo.shortName = "ja_raw";
localeInfo.baseLangCode = null;
localeInfo.isRtl = false;
localeInfo.pathToFile = "unofficial";
localeInfo.pluralLangCode = "ja";
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
languagesDict.put("ja", localeInfo);
loadOtherLanguages();
if (remoteLanguages.isEmpty()) {
AndroidUtilities.runOnUIThread(() -> loadRemoteLanguages(UserConfig.selectedAccount));
}
for (int a = 0; a < otherLanguages.size(); a++) {
LocaleInfo locale = otherLanguages.get(a);
languages.add(locale);
languagesDict.put(locale.getKey(), locale);
}
for (int a = 0; a < remoteLanguages.size(); a++) {
LocaleInfo locale = remoteLanguages.get(a);
LocaleInfo existingLocale = getLanguageFromDict(locale.getKey());
if (existingLocale != null) {
existingLocale.pathToFile = locale.pathToFile;
existingLocale.version = locale.version;
existingLocale.baseVersion = locale.baseVersion;
existingLocale.serverIndex = locale.serverIndex;
remoteLanguages.set(a, existingLocale);
} else {
languages.add(locale);
languagesDict.put(locale.getKey(), locale);
}
}
for (int a = 0; a < unofficialLanguages.size(); a++) {
LocaleInfo locale = unofficialLanguages.get(a);
LocaleInfo existingLocale = getLanguageFromDict(locale.getKey());
if (existingLocale != null) {
existingLocale.pathToFile = locale.pathToFile;
existingLocale.version = locale.version;
existingLocale.baseVersion = locale.baseVersion;
existingLocale.serverIndex = locale.serverIndex;
unofficialLanguages.set(a, existingLocale);
} else {
languagesDict.put(locale.getKey(), locale);
}
}
systemDefaultLocale = Locale.getDefault();
is24HourFormat = DateFormat.is24HourFormat(ApplicationLoader.applicationContext);
LocaleInfo currentInfo = null;
boolean override = false;
try {
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
String lang = preferences.getString("language", null);
if (lang != null) {
currentInfo = getLanguageFromDict(lang);
if (currentInfo != null) {
override = true;
}
}
if (currentInfo == null && systemDefaultLocale.getLanguage() != null) {
currentInfo = getLanguageFromDict(systemDefaultLocale.getLanguage());
}
if (currentInfo == null) {
currentInfo = getLanguageFromDict(getLocaleString(systemDefaultLocale));
if (currentInfo == null) {
currentInfo = getLanguageFromDict("en");
}
}
applyLanguage(currentInfo, override, true, UserConfig.selectedAccount);
} catch (Exception e) {
FileLog.e(e);
}
try {
IntentFilter timezoneFilter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);
ApplicationLoader.applicationContext.registerReceiver(new TimeZoneChangedReceiver(), timezoneFilter);
} catch (Exception e) {
FileLog.e(e);
}
AndroidUtilities.runOnUIThread(() -> currentSystemLocale = getSystemLocaleStringIso639());
}
public LocaleInfo getLanguageFromDict(String key) {
if (key == null) {
return null;
}
return languagesDict.get(key.toLowerCase().replace("-", "_"));
}
private void addRules(String[] languages, PluralRules rules) {
for (String language : languages) {
allRules.put(language, rules);
}
}
private String stringForQuantity(int quantity) {
switch (quantity) {
case QUANTITY_ZERO:
return "zero";
case QUANTITY_ONE:
return "one";
case QUANTITY_TWO:
return "two";
case QUANTITY_FEW:
return "few";
case QUANTITY_MANY:
return "many";
default:
return "other";
}
}
public Locale getSystemDefaultLocale() {
return systemDefaultLocale;
}
public boolean isCurrentLocalLocale() {
return currentLocaleInfo.isLocal();
}
public void reloadCurrentRemoteLocale(int currentAccount, String langCode, boolean force) {
if (langCode != null) {
langCode = langCode.replace("-", "_");
}
if (langCode == null || currentLocaleInfo != null && (langCode.equals(currentLocaleInfo.shortName) || langCode.equals(currentLocaleInfo.baseLangCode))) {
applyRemoteLanguage(currentLocaleInfo, langCode, force, currentAccount);
}
}
public void checkUpdateForCurrentRemoteLocale(int currentAccount, int version, int baseVersion) {
if (currentLocaleInfo == null || currentLocaleInfo != null && !currentLocaleInfo.isRemote() && !currentLocaleInfo.isUnofficial()) {
return;
}
if (currentLocaleInfo.hasBaseLang()) {
if (currentLocaleInfo.baseVersion < baseVersion) {
applyRemoteLanguage(currentLocaleInfo, currentLocaleInfo.baseLangCode, false, currentAccount);
}
}
if (currentLocaleInfo.version < version) {
applyRemoteLanguage(currentLocaleInfo, currentLocaleInfo.shortName, false, currentAccount);
}
}
private String getLocaleString(Locale locale) {
if (locale == null) {
return "en";
}
String languageCode = locale.getLanguage();
String countryCode = locale.getCountry();
String variantCode = locale.getVariant();
if (languageCode.length() == 0 && countryCode.length() == 0) {
return "en";
}
StringBuilder result = new StringBuilder(11);
result.append(languageCode);
if (countryCode.length() > 0 || variantCode.length() > 0) {
result.append('_');
}
result.append(countryCode);
if (variantCode.length() > 0) {
result.append('_');
}
result.append(variantCode);
return result.toString();
}
public static String getSystemLocaleStringIso639() {
Locale locale = getInstance().getSystemDefaultLocale();
if (locale == null) {
return "en";
}
String languageCode = locale.getLanguage();
String countryCode = locale.getCountry();
String variantCode = locale.getVariant();
if (languageCode.length() == 0 && countryCode.length() == 0) {
return "en";
}
StringBuilder result = new StringBuilder(11);
result.append(languageCode);
if (countryCode.length() > 0 || variantCode.length() > 0) {
result.append('-');
}
result.append(countryCode);
if (variantCode.length() > 0) {
result.append('_');
}
result.append(variantCode);
return result.toString();
}
public static String getLocaleStringIso639() {
LocaleInfo info = getInstance().currentLocaleInfo;
if (info != null) {
return info.getLangCode();
}
Locale locale = getInstance().currentLocale;
if (locale == null) {
return "en";
}
String languageCode = locale.getLanguage();
String countryCode = locale.getCountry();
String variantCode = locale.getVariant();
if (languageCode.length() == 0 && countryCode.length() == 0) {
return "en";
}
StringBuilder result = new StringBuilder(11);
result.append(languageCode);
if (countryCode.length() > 0 || variantCode.length() > 0) {
result.append('-');
}
result.append(countryCode);
if (variantCode.length() > 0) {
result.append('_');
}
result.append(variantCode);
return result.toString();
}
public static String getLocaleAlias(String code) {
if (code == null) {
return null;
}
switch (code) {
case "in":
return "id";
case "iw":
return "he";
case "jw":
return "jv";
case "no":
return "nb";
case "tl":
return "fil";
case "ji":
return "yi";
case "id":
return "in";
case "he":
return "iw";
case "jv":
return "jw";
case "nb":
return "no";
case "fil":
return "tl";
case "yi":
return "ji";
}
return null;
}
public boolean applyLanguageFile(File file, int currentAccount) {
try {
HashMap<String, String> stringMap = getLocaleFileStrings(file);
String languageName = stringMap.get("LanguageName");
String languageNameInEnglish = stringMap.get("LanguageNameInEnglish");
String languageCode = stringMap.get("LanguageCode");
if (languageName != null && languageName.length() > 0 &&
languageNameInEnglish != null && languageNameInEnglish.length() > 0 &&
languageCode != null && languageCode.length() > 0) {
if (languageName.contains("&") || languageName.contains("|")) {
return false;
}
if (languageNameInEnglish.contains("&") || languageNameInEnglish.contains("|")) {
return false;
}
if (languageCode.contains("&") || languageCode.contains("|") || languageCode.contains("/") || languageCode.contains("\\")) {
return false;
}
File finalFile = new File(ApplicationLoader.getFilesDirFixed(), languageCode + ".xml");
if (!AndroidUtilities.copyFile(file, finalFile)) {
return false;
}
String key = "local_" + languageCode.toLowerCase();
LocaleInfo localeInfo = getLanguageFromDict(key);
if (localeInfo == null) {
localeInfo = new LocaleInfo();
localeInfo.name = languageName;
localeInfo.nameEnglish = languageNameInEnglish;
localeInfo.shortName = languageCode.toLowerCase();
localeInfo.pluralLangCode = localeInfo.shortName;
localeInfo.pathToFile = finalFile.getAbsolutePath();
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
otherLanguages.add(localeInfo);
saveOtherLanguages();
}
localeValues = stringMap;
applyLanguage(localeInfo, true, false, true, false, currentAccount);
return true;
}
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
private void saveOtherLanguages() {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("langconfig", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
StringBuilder stringBuilder = new StringBuilder();
for (int a = 0; a < otherLanguages.size(); a++) {
LocaleInfo localeInfo = otherLanguages.get(a);
String loc = localeInfo.getSaveString();
if (loc != null) {
if (stringBuilder.length() != 0) {
stringBuilder.append("&");
}
stringBuilder.append(loc);
}
}
editor.putString("locales", stringBuilder.toString());
stringBuilder.setLength(0);
for (int a = 0; a < remoteLanguages.size(); a++) {
LocaleInfo localeInfo = remoteLanguages.get(a);
String loc = localeInfo.getSaveString();
if (loc != null) {
if (stringBuilder.length() != 0) {
stringBuilder.append("&");
}
stringBuilder.append(loc);
}
}
editor.putString("remote", stringBuilder.toString());
stringBuilder.setLength(0);
for (int a = 0; a < unofficialLanguages.size(); a++) {
LocaleInfo localeInfo = unofficialLanguages.get(a);
String loc = localeInfo.getSaveString();
if (loc != null) {
if (stringBuilder.length() != 0) {
stringBuilder.append("&");
}
stringBuilder.append(loc);
}
}
editor.putString("unofficial", stringBuilder.toString());
editor.apply();
}
public boolean deleteLanguage(LocaleInfo localeInfo, int currentAccount) {
if (localeInfo.pathToFile == null || localeInfo.isRemote() && localeInfo.serverIndex != Integer.MAX_VALUE) {
return false;
}
if (currentLocaleInfo == localeInfo) {
LocaleInfo info = null;
if (systemDefaultLocale.getLanguage() != null) {
info = getLanguageFromDict(systemDefaultLocale.getLanguage());
}
if (info == null) {
info = getLanguageFromDict(getLocaleString(systemDefaultLocale));
}
if (info == null) {
info = getLanguageFromDict("en");
}
applyLanguage(info, true, false, currentAccount);
}
unofficialLanguages.remove(localeInfo);
remoteLanguages.remove(localeInfo);
remoteLanguagesDict.remove(localeInfo.getKey());
otherLanguages.remove(localeInfo);
languages.remove(localeInfo);
languagesDict.remove(localeInfo.getKey());
File file = new File(localeInfo.pathToFile);
file.delete();
saveOtherLanguages();
return true;
}
private void loadOtherLanguages() {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("langconfig", Activity.MODE_PRIVATE);
String locales = preferences.getString("locales", null);
if (!TextUtils.isEmpty(locales)) {
String[] localesArr = locales.split("&");
for (String locale : localesArr) {
LocaleInfo localeInfo = LocaleInfo.createWithString(locale);
if (localeInfo != null) {
otherLanguages.add(localeInfo);
}
}
}
locales = preferences.getString("remote", null);
if (!TextUtils.isEmpty(locales)) {
String[] localesArr = locales.split("&");
for (String locale : localesArr) {
LocaleInfo localeInfo = LocaleInfo.createWithString(locale);
localeInfo.shortName = localeInfo.shortName.replace("-", "_");
if (remoteLanguagesDict.containsKey(localeInfo.getKey())) {
continue;
}
if (localeInfo != null) {
remoteLanguages.add(localeInfo);
remoteLanguagesDict.put(localeInfo.getKey(), localeInfo);
}
}
}
locales = preferences.getString("unofficial", null);
if (!TextUtils.isEmpty(locales)) {
String[] localesArr = locales.split("&");
for (String locale : localesArr) {
LocaleInfo localeInfo = LocaleInfo.createWithString(locale);
localeInfo.shortName = localeInfo.shortName.replace("-", "_");
if (localeInfo != null) {
unofficialLanguages.add(localeInfo);
}
}
}
}
private HashMap<String, String> getLocaleFileStrings(File file) {
return getLocaleFileStrings(file, false);
}
private HashMap<String, String> getLocaleFileStrings(File file, boolean preserveEscapes) {
FileInputStream stream = null;
reloadLastFile = false;
try {
if (!file.exists()) {
return new HashMap<>();
}
HashMap<String, String> stringMap = new HashMap<>();
XmlPullParser parser = Xml.newPullParser();
//AndroidUtilities.copyFile(file, new File(ApplicationLoader.applicationContext.getExternalFilesDir(null), "locale10.xml"));
stream = new FileInputStream(file);
parser.setInput(stream, "UTF-8");
int eventType = parser.getEventType();
String name = null;
String value = null;
String attrName = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
name = parser.getName();
int c = parser.getAttributeCount();
if (c > 0) {
attrName = parser.getAttributeValue(0);
}
} else if (eventType == XmlPullParser.TEXT) {
if (attrName != null) {
value = parser.getText();
if (value != null) {
value = value.trim();
if (preserveEscapes) {
value = value.replace("<", "&lt;").replace(">", "&gt;").replace("'", "\\'").replace("& ", "&amp; ");
} else {
value = value.replace("\\n", "\n");
value = value.replace("\\", "");
String old = value;
value = value.replace("&lt;", "<");
if (!reloadLastFile && !value.equals(old)) {
reloadLastFile = true;
}
}
}
}
} else if (eventType == XmlPullParser.END_TAG) {
value = null;
attrName = null;
name = null;
}
if (name != null && name.equals("string") && value != null && attrName != null && value.length() != 0 && attrName.length() != 0) {
stringMap.put(attrName, value);
name = null;
value = null;
attrName = null;
}
eventType = parser.next();
}
return stringMap;
} catch (Exception e) {
FileLog.e(e);
reloadLastFile = true;
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (Exception e) {
FileLog.e(e);
}
}
return new HashMap<>();
}
public void applyLanguage(LocaleInfo localeInfo, boolean override, boolean init, final int currentAccount) {
applyLanguage(localeInfo, override, init, false, false, currentAccount);
}
public void applyLanguage(final LocaleInfo localeInfo, boolean override, boolean init, boolean fromFile, boolean force, final int currentAccount) {
if (localeInfo == null) {
return;
}
boolean hasBase = localeInfo.hasBaseLang();
File pathToFile = localeInfo.getPathToFile();
File pathToBaseFile = localeInfo.getPathToBaseFile();
String shortName = localeInfo.shortName;
if (!init) {
ConnectionsManager.setLangCode(localeInfo.getLangCode());
}
LocaleInfo existingInfo = getLanguageFromDict(localeInfo.getKey());
if (existingInfo == null) {
if (localeInfo.isRemote()) {
remoteLanguages.add(localeInfo);
remoteLanguagesDict.put(localeInfo.getKey(), localeInfo);
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
saveOtherLanguages();
} else if (localeInfo.isUnofficial()) {
unofficialLanguages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
saveOtherLanguages();
}
}
loadPrebuiltLocaleFile(localeInfo);
if ((localeInfo.isRemote() || localeInfo.isUnofficial()) && (force || !pathToFile.exists() || hasBase && !pathToBaseFile.exists())) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("reload locale because one of file doesn't exist" + pathToFile + " " + pathToBaseFile);
}
if (init) {
AndroidUtilities.runOnUIThread(() -> applyRemoteLanguage(localeInfo, null, true, currentAccount));
} else {
applyRemoteLanguage(localeInfo, null, true, currentAccount);
}
}
try {
Locale newLocale;
String[] args;
if (!TextUtils.isEmpty(localeInfo.pluralLangCode)) {
args = localeInfo.pluralLangCode.split("_");
} else if (!TextUtils.isEmpty(localeInfo.baseLangCode)) {
args = localeInfo.baseLangCode.split("_");
} else {
args = localeInfo.shortName.split("_");
}
if (args.length == 1) {
newLocale = new Locale(args[0]);
} else {
newLocale = new Locale(args[0], args[1]);
}
if (override) {
languageOverride = localeInfo.shortName;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
editor.putString("language", localeInfo.getKey());
editor.apply();
}
if (pathToFile == null) {
localeValues.clear();
} else if (!fromFile) {
localeValues = getLocaleFileStrings(hasBase ? localeInfo.getPathToBaseFile() : localeInfo.getPathToFile());
if (hasBase) {
localeValues.putAll(getLocaleFileStrings(localeInfo.getPathToFile()));
}
}
currentLocale = newLocale;
currentLocaleInfo = localeInfo;
if (currentLocaleInfo != null && !TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) {
currentPluralRules = allRules.get(currentLocaleInfo.pluralLangCode);
}
if (currentPluralRules == null) {
currentPluralRules = allRules.get(args[0]);
if (currentPluralRules == null) {
currentPluralRules = allRules.get(currentLocale.getLanguage());
if (currentPluralRules == null) {
currentPluralRules = new PluralRules_None();
}
}
}
changingConfiguration = true;
Locale.setDefault(currentLocale);
android.content.res.Configuration config = new android.content.res.Configuration();
config.locale = currentLocale;
ApplicationLoader.applicationContext.getResources().updateConfiguration(config, ApplicationLoader.applicationContext.getResources().getDisplayMetrics());
changingConfiguration = false;
if (reloadLastFile) {
if (init) {
AndroidUtilities.runOnUIThread(() -> reloadCurrentRemoteLocale(currentAccount, null, force));
} else {
reloadCurrentRemoteLocale(currentAccount, null, force);
}
reloadLastFile = false;
}
} catch (Exception e) {
FileLog.e(e);
changingConfiguration = false;
}
recreateFormatters();
}
public LocaleInfo getCurrentLocaleInfo() {
return currentLocaleInfo;
}
public static String getCurrentLanguageName() {
LocaleInfo localeInfo = getInstance().currentLocaleInfo;
return localeInfo == null || TextUtils.isEmpty(localeInfo.name) ? getString("LanguageName", R.string.LanguageName) : localeInfo.name;
}
private String getStringInternal(String key, int res) {
String value = BuildVars.USE_CLOUD_STRINGS ? localeValues.get(key) : null;
if (value == null) {
try {
value = ApplicationLoader.applicationContext.getString(res);
} catch (Exception e) {
FileLog.e(e);
}
}
if (value == null) {
value = "LOC_ERR:" + key;
}
return value;
}
public static String getServerString(String key) {
String value = getInstance().localeValues.get(key);
if (value == null) {
int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(key, "string", ApplicationLoader.applicationContext.getPackageName());
if (resourceId != 0) {
value = ApplicationLoader.applicationContext.getString(resourceId);
}
}
return value;
}
public static String getString(String key, int res) {
return getInstance().getStringInternal(key, res);
}
public static String getString(String key) {
if (TextUtils.isEmpty(key)) {
return "LOC_ERR:" + key;
}
int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(key, "string", ApplicationLoader.applicationContext.getPackageName());
if (resourceId != 0) {
return getString(key, resourceId);
}
return getServerString(key);
}
public static String getPluralString(String key, int plural) {
if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) {
return "LOC_ERR:" + key;
}
String param = getInstance().stringForQuantity(getInstance().currentPluralRules.quantityForNumber(plural));
param = key + "_" + param;
int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName());
return getString(param, resourceId);
}
public static String formatPluralString(String key, int plural) {
if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) {
return "LOC_ERR:" + key;
}
String param = getInstance().stringForQuantity(getInstance().currentPluralRules.quantityForNumber(plural));
param = key + "_" + param;
int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName());
return formatString(param, resourceId, plural);
}
public static String formatPluralStringComma(String key, int plural) {
try {
if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) {
return "LOC_ERR:" + key;
}
String param = getInstance().stringForQuantity(getInstance().currentPluralRules.quantityForNumber(plural));
param = key + "_" + param;
StringBuilder stringBuilder = new StringBuilder(String.format(Locale.US, "%d", plural));
for (int a = stringBuilder.length() - 3; a > 0; a -= 3) {
stringBuilder.insert(a, ',');
}
String value = BuildVars.USE_CLOUD_STRINGS ? getInstance().localeValues.get(param) : null;
if (value == null) {
int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName());
value = ApplicationLoader.applicationContext.getString(resourceId);
}
value = value.replace("%1$d", "%1$s");
if (getInstance().currentLocale != null) {
return String.format(getInstance().currentLocale, value, stringBuilder);
} else {
return String.format(value, stringBuilder);
}
} catch (Exception e) {
FileLog.e(e);
return "LOC_ERR: " + key;
}
}
public static String formatString(String key, int res, Object... args) {
try {
String value = BuildVars.USE_CLOUD_STRINGS ? getInstance().localeValues.get(key) : null;
if (value == null) {
value = ApplicationLoader.applicationContext.getString(res);
}
if (getInstance().currentLocale != null) {
return String.format(getInstance().currentLocale, value, args);
} else {
return String.format(value, args);
}
} catch (Exception e) {
FileLog.e(e);
return "LOC_ERR: " + key;
}
}
public static String formatTTLString(int ttl) {
if (ttl < 60) {
return LocaleController.formatPluralString("Seconds", ttl);
} else if (ttl < 60 * 60) {
return LocaleController.formatPluralString("Minutes", ttl / 60);
} else if (ttl < 60 * 60 * 24) {
return LocaleController.formatPluralString("Hours", ttl / 60 / 60);
} else if (ttl < 60 * 60 * 24 * 7) {
return LocaleController.formatPluralString("Days", ttl / 60 / 60 / 24);
} else {
int days = ttl / 60 / 60 / 24;
if (ttl % 7 == 0) {
return LocaleController.formatPluralString("Weeks", days / 7);
} else {
return String.format("%s %s", LocaleController.formatPluralString("Weeks", days / 7), LocaleController.formatPluralString("Days", days % 7));
}
}
}
public String formatCurrencyString(long amount, String type) {
type = type.toUpperCase();
String customFormat;
double doubleAmount;
boolean discount = amount < 0;
amount = Math.abs(amount);
Currency currency = Currency.getInstance(type);
switch (type) {
case "CLF":
customFormat = " %.4f";
doubleAmount = amount / 10000.0;
break;
case "IRR":
doubleAmount = amount / 100.0f;
if (amount % 100 == 0) {
customFormat = " %.0f";
} else {
customFormat = " %.2f";
}
break;
case "BHD":
case "IQD":
case "JOD":
case "KWD":
case "LYD":
case "OMR":
case "TND":
customFormat = " %.3f";
doubleAmount = amount / 1000.0;
break;
case "BIF":
case "BYR":
case "CLP":
case "CVE":
case "DJF":
case "GNF":
case "ISK":
case "JPY":
case "KMF":
case "KRW":
case "MGA":
case "PYG":
case "RWF":
case "UGX":
case "UYI":
case "VND":
case "VUV":
case "XAF":
case "XOF":
case "XPF":
customFormat = " %.0f";
doubleAmount = amount;
break;
case "MRO":
customFormat = " %.1f";
doubleAmount = amount / 10.0;
break;
default:
customFormat = " %.2f";
doubleAmount = amount / 100.0;
break;
}
String result;
if (currency != null) {
NumberFormat format = NumberFormat.getCurrencyInstance(currentLocale != null ? currentLocale : systemDefaultLocale);
format.setCurrency(currency);
if (type.equals("IRR")) {
format.setMaximumFractionDigits(0);
}
return (discount ? "-" : "") + format.format(doubleAmount);
}
return (discount ? "-" : "") + String.format(Locale.US, type + customFormat, doubleAmount);
}
public String formatCurrencyDecimalString(long amount, String type, boolean inludeType) {
type = type.toUpperCase();
String customFormat;
double doubleAmount;
amount = Math.abs(amount);
switch (type) {
case "CLF":
customFormat = " %.4f";
doubleAmount = amount / 10000.0;
break;
case "IRR":
doubleAmount = amount / 100.0f;
if (amount % 100 == 0) {
customFormat = " %.0f";
} else {
customFormat = " %.2f";
}
break;
case "BHD":
case "IQD":
case "JOD":
case "KWD":
case "LYD":
case "OMR":
case "TND":
customFormat = " %.3f";
doubleAmount = amount / 1000.0;
break;
case "BIF":
case "BYR":
case "CLP":
case "CVE":
case "DJF":
case "GNF":
case "ISK":
case "JPY":
case "KMF":
case "KRW":
case "MGA":
case "PYG":
case "RWF":
case "UGX":
case "UYI":
case "VND":
case "VUV":
case "XAF":
case "XOF":
case "XPF":
customFormat = " %.0f";
doubleAmount = amount;
break;
case "MRO":
customFormat = " %.1f";
doubleAmount = amount / 10.0;
break;
default:
customFormat = " %.2f";
doubleAmount = amount / 100.0;
break;
}
return String.format(Locale.US, inludeType ? type : "" + customFormat, doubleAmount).trim();
}
public static String formatStringSimple(String string, Object... args) {
try {
if (getInstance().currentLocale != null) {
return String.format(getInstance().currentLocale, string, args);
} else {
return String.format(string, args);
}
} catch (Exception e) {
FileLog.e(e);
return "LOC_ERR: " + string;
}
}
public static String formatCallDuration(int duration) {
if (duration > 3600) {
String result = LocaleController.formatPluralString("Hours", duration / 3600);
int minutes = duration % 3600 / 60;
if (minutes > 0) {
result += ", " + LocaleController.formatPluralString("Minutes", minutes);
}
return result;
} else if (duration > 60) {
return LocaleController.formatPluralString("Minutes", duration / 60);
} else {
return LocaleController.formatPluralString("Seconds", duration);
}
}
public void onDeviceConfigurationChange(Configuration newConfig) {
if (changingConfiguration) {
return;
}
is24HourFormat = DateFormat.is24HourFormat(ApplicationLoader.applicationContext);
systemDefaultLocale = newConfig.locale;
if (languageOverride != null) {
LocaleInfo toSet = currentLocaleInfo;
currentLocaleInfo = null;
applyLanguage(toSet, false, true, UserConfig.selectedAccount);
} else {
Locale newLocale = newConfig.locale;
if (newLocale != null) {
String d1 = newLocale.getDisplayName();
String d2 = currentLocale.getDisplayName();
if (d1 != null && d2 != null && !d1.equals(d2)) {
recreateFormatters();
}
currentLocale = newLocale;
if (currentLocaleInfo != null && !TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) {
currentPluralRules = allRules.get(currentLocaleInfo.pluralLangCode);
}
if (currentPluralRules == null) {
currentPluralRules = allRules.get(currentLocale.getLanguage());
if (currentPluralRules == null) {
currentPluralRules = allRules.get("en");
}
}
}
}
String newSystemLocale = getSystemLocaleStringIso639();
if (currentSystemLocale != null && !newSystemLocale.equals(currentSystemLocale)) {
currentSystemLocale = newSystemLocale;
ConnectionsManager.setSystemLangCode(currentSystemLocale);
}
}
public static String formatDateChat(long date) {
return formatDateChat(date, false);
}
public static String formatDateChat(long date, boolean checkYear) {
try {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
int currentYear = calendar.get(Calendar.YEAR);
date *= 1000;
calendar.setTimeInMillis(date);
if (checkYear && currentYear == calendar.get(Calendar.YEAR) || !checkYear && Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
return getInstance().chatDate.format(date);
}
return getInstance().chatFullDate.format(date);
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR: formatDateChat";
}
public static String formatDate(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return getInstance().formatterDay.format(new Date(date));
} else if (dateDay + 1 == day && year == dateYear) {
return getString("Yesterday", R.string.Yesterday);
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
return getInstance().formatterDayMonth.format(new Date(date));
} else {
return getInstance().formatterYear.format(new Date(date));
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR: formatDate";
}
public static String formatDateAudio(long date, boolean shortFormat) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
if (shortFormat) {
return LocaleController.formatString("TodayAtFormatted", R.string.TodayAtFormatted, getInstance().formatterDay.format(new Date(date)));
} else {
return LocaleController.formatString("TodayAtFormattedWithToday", R.string.TodayAtFormattedWithToday, getInstance().formatterDay.format(new Date(date)));
}
} else if (dateDay + 1 == day && year == dateYear) {
return LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date)));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
return LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterDayMonth.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
} else {
return LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterYear.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatDateCallLog(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return getInstance().formatterDay.format(new Date(date));
} else if (dateDay + 1 == day && year == dateYear) {
return LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date)));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
return LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().chatDate.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
} else {
return LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().chatFullDate.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatLocationUpdateDate(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
int diff = (int) (ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime() - date / 1000) / 60;
if (diff < 1) {
return LocaleController.getString("LocationUpdatedJustNow", R.string.LocationUpdatedJustNow);
} else if (diff < 60) {
return LocaleController.formatPluralString("UpdatedMinutes", diff);
}
return LocaleController.formatString("LocationUpdatedFormatted", R.string.LocationUpdatedFormatted, LocaleController.formatString("TodayAtFormatted", R.string.TodayAtFormatted, getInstance().formatterDay.format(new Date(date))));
} else if (dateDay + 1 == day && year == dateYear) {
return LocaleController.formatString("LocationUpdatedFormatted", R.string.LocationUpdatedFormatted, LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date))));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterDayMonth.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
return LocaleController.formatString("LocationUpdatedFormatted", R.string.LocationUpdatedFormatted, format);
} else {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterYear.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
return LocaleController.formatString("LocationUpdatedFormatted", R.string.LocationUpdatedFormatted, format);
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatLocationLeftTime(int time) {
String text;
int hours = time / 60 / 60;
time -= hours * 60 * 60;
int minutes = time / 60;
time -= minutes * 60;
if (hours != 0) {
text = String.format("%dh", hours + (minutes > 30 ? 1 : 0));
} else if (minutes != 0) {
text = String.format("%d", minutes + (time > 30 ? 1 : 0));
} else {
text = String.format("%d", time);
}
return text;
}
public static String formatDateOnline(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return LocaleController.formatString("LastSeenFormatted", R.string.LastSeenFormatted, LocaleController.formatString("TodayAtFormatted", R.string.TodayAtFormatted, getInstance().formatterDay.format(new Date(date))));
/*int diff = (int) (ConnectionsManager.getInstance().getCurrentTime() - date) / 60;
if (diff < 1) {
return LocaleController.getString("LastSeenNow", R.string.LastSeenNow);
} else if (diff < 60) {
return LocaleController.formatPluralString("LastSeenMinutes", diff);
} else {
return LocaleController.formatPluralString("LastSeenHours", (int) Math.ceil(diff / 60.0f));
}*/
} else if (dateDay + 1 == day && year == dateYear) {
return LocaleController.formatString("LastSeenFormatted", R.string.LastSeenFormatted, LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date))));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterDayMonth.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
return LocaleController.formatString("LastSeenDateFormatted", R.string.LastSeenDateFormatted, format);
} else {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterYear.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
return LocaleController.formatString("LastSeenDateFormatted", R.string.LastSeenDateFormatted, format);
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatDateJoined(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return LocaleController.formatString("JoinedFormatted", R.string.JoinedFormatted, LocaleController.formatString("TodayAtFormatted", R.string.TodayAtFormatted, getInstance().formatterDay.format(new Date(date))));
} else if (dateDay + 1 == day && year == dateYear) {
return LocaleController.formatString("JoinedFormatted", R.string.JoinedFormatted, LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date))));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterDayMonth.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
return LocaleController.formatString("JoinedDateFormatted", R.string.JoinedDateFormatted, format);
} else {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterYear.format(new Date(date)), getInstance().formatterDay.format(new Date(date)));
return LocaleController.formatString("JoinedDateFormatted", R.string.JoinedDateFormatted, format);
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
private FastDateFormat createFormatter(Locale locale, String format, String defaultFormat) {
if (format == null || format.length() == 0) {
format = defaultFormat;
}
FastDateFormat formatter;
try {
formatter = FastDateFormat.getInstance(format, locale);
} catch (Exception e) {
format = defaultFormat;
formatter = FastDateFormat.getInstance(format, locale);
}
return formatter;
}
public void recreateFormatters() {
Locale locale = currentLocale;
if (locale == null) {
locale = Locale.getDefault();
}
String lang = locale.getLanguage();
if (lang == null) {
lang = "en";
}
lang = lang.toLowerCase();
isRTL = lang.length() == 2 && (lang.equals("ar") || lang.equals("fa") || lang.equals("he") || lang.equals("iw")) ||
lang.startsWith("ar_") || lang.startsWith("fa_") || lang.startsWith("he_") || lang.startsWith("iw_")
|| currentLocaleInfo != null && currentLocaleInfo.isRtl;
formatterDayMonth = createFormatter(locale, getStringInternal("formatterMonth", R.string.formatterMonth), "dd MMM");
formatterYear = createFormatter(locale, getStringInternal("formatterYear", R.string.formatterYear), "dd.MM.yy");
formatterYearMax = createFormatter(locale, getStringInternal("formatterYearMax", R.string.formatterYearMax), "dd.MM.yyyy");
chatDate = createFormatter(locale, getStringInternal("chatDate", R.string.chatDate), "d MMMM");
chatFullDate = createFormatter(locale, getStringInternal("chatFullDate", R.string.chatFullDate), "d MMMM yyyy");
formatterWeek = createFormatter(locale, getStringInternal("formatterWeek", R.string.formatterWeek), "EEE");
formatterScheduleDay = createFormatter(locale, getStringInternal("formatDateSchedule", R.string.formatDateSchedule), "MMM d");
formatterScheduleYear = createFormatter(locale, getStringInternal("formatDateScheduleYear", R.string.formatDateScheduleYear), "MMM d yyyy");
formatterDay = createFormatter(lang.toLowerCase().equals("ar") || lang.toLowerCase().equals("ko") ? locale : Locale.US, is24HourFormat ? getStringInternal("formatterDay24H", R.string.formatterDay24H) : getStringInternal("formatterDay12H", R.string.formatterDay12H), is24HourFormat ? "HH:mm" : "h:mm a");
formatterStats = createFormatter(locale, is24HourFormat ? getStringInternal("formatterStats24H", R.string.formatterStats24H) : getStringInternal("formatterStats12H", R.string.formatterStats12H), is24HourFormat ? "MMM dd yyyy, HH:mm" : "MMM dd yyyy, h:mm a");
formatterBannedUntil = createFormatter(locale, is24HourFormat ? getStringInternal("formatterBannedUntil24H", R.string.formatterBannedUntil24H) : getStringInternal("formatterBannedUntil12H", R.string.formatterBannedUntil12H), is24HourFormat ? "MMM dd yyyy, HH:mm" : "MMM dd yyyy, h:mm a");
formatterBannedUntilThisYear = createFormatter(locale, is24HourFormat ? getStringInternal("formatterBannedUntilThisYear24H", R.string.formatterBannedUntilThisYear24H) : getStringInternal("formatterBannedUntilThisYear12H", R.string.formatterBannedUntilThisYear12H), is24HourFormat ? "MMM dd, HH:mm" : "MMM dd, h:mm a");
formatterScheduleSend[0] = createFormatter(locale, getStringInternal("SendTodayAt", R.string.SendTodayAt), "'Send today at' HH:mm");
formatterScheduleSend[1] = createFormatter(locale, getStringInternal("SendDayAt", R.string.SendDayAt), "'Send on' MMM d 'at' HH:mm");
formatterScheduleSend[2] = createFormatter(locale, getStringInternal("SendDayYearAt", R.string.SendDayYearAt), "'Send on' MMM d yyyy 'at' HH:mm");
formatterScheduleSend[3] = createFormatter(locale, getStringInternal("RemindTodayAt", R.string.RemindTodayAt), "'Remind today at' HH:mm");
formatterScheduleSend[4] = createFormatter(locale, getStringInternal("RemindDayAt", R.string.RemindDayAt), "'Remind on' MMM d 'at' HH:mm");
formatterScheduleSend[5] = createFormatter(locale, getStringInternal("RemindDayYearAt", R.string.RemindDayYearAt), "'Remind on' MMM d yyyy 'at' HH:mm");
}
public static boolean isRTLCharacter(char ch) {
return Character.getDirectionality(ch) == Character.DIRECTIONALITY_RIGHT_TO_LEFT || Character.getDirectionality(ch) == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC || Character.getDirectionality(ch) == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING || Character.getDirectionality(ch) == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE;
}
public static String formatSectionDate(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateYear = rightNow.get(Calendar.YEAR);
int month = rightNow.get(Calendar.MONTH);
final String[] months = new String[]{
LocaleController.getString("January", R.string.January),
LocaleController.getString("February", R.string.February),
LocaleController.getString("March", R.string.March),
LocaleController.getString("April", R.string.April),
LocaleController.getString("May", R.string.May),
LocaleController.getString("June", R.string.June),
LocaleController.getString("July", R.string.July),
LocaleController.getString("August", R.string.August),
LocaleController.getString("September", R.string.September),
LocaleController.getString("October", R.string.October),
LocaleController.getString("November", R.string.November),
LocaleController.getString("December", R.string.December)
};
if (year == dateYear) {
return months[month];
} else {
return months[month] + " " + dateYear;
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatDateForBan(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateYear = rightNow.get(Calendar.YEAR);
if (year == dateYear) {
return getInstance().formatterBannedUntilThisYear.format(new Date(date));
} else {
return getInstance().formatterBannedUntil.format(new Date(date));
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String stringForMessageListDate(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
if (Math.abs(System.currentTimeMillis() - date) >= 31536000000L) {
return getInstance().formatterYear.format(new Date(date));
} else {
int dayDiff = dateDay - day;
if (dayDiff == 0 || dayDiff == -1 && System.currentTimeMillis() - date < 60 * 60 * 8 * 1000) {
return getInstance().formatterDay.format(new Date(date));
} else if (dayDiff > -7 && dayDiff <= -1) {
return getInstance().formatterWeek.format(new Date(date));
} else {
return getInstance().formatterDayMonth.format(new Date(date));
}
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatShortNumber(int number, int[] rounded) {
if (NekoConfig.disableNumberRounding) {
if (rounded != null) {
rounded[0] = number;
}
return String.valueOf(number);
}
StringBuilder K = new StringBuilder();
int lastDec = 0;
int KCount = 0;
while (number / 1000 > 0) {
K.append("K");
lastDec = (number % 1000) / 100;
number /= 1000;
}
if (rounded != null) {
double value = number + lastDec / 10.0;
for (int a = 0; a < K.length(); a++) {
value *= 1000;
}
rounded[0] = (int) value;
}
if (lastDec != 0 && K.length() > 0) {
if (K.length() == 2) {
return String.format(Locale.US, "%d.%dM", number, lastDec);
} else {
return String.format(Locale.US, "%d.%d%s", number, lastDec, K.toString());
}
}
if (K.length() == 2) {
return String.format(Locale.US, "%dM", number);
} else {
return String.format(Locale.US, "%d%s", number, K.toString());
}
}
public static String formatUserStatus(int currentAccount, TLRPC.User user) {
return formatUserStatus(currentAccount, user, null);
}
public static String formatUserStatus(int currentAccount, TLRPC.User user, boolean[] isOnline) {
if (user != null && user.status != null && user.status.expires == 0) {
if (user.status instanceof TLRPC.TL_userStatusRecently) {
user.status.expires = -100;
} else if (user.status instanceof TLRPC.TL_userStatusLastWeek) {
user.status.expires = -101;
} else if (user.status instanceof TLRPC.TL_userStatusLastMonth) {
user.status.expires = -102;
}
}
if (user != null && user.status != null && user.status.expires <= 0) {
if (MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(user.id)) {
if (isOnline != null) {
isOnline[0] = true;
}
return getString("Online", R.string.Online);
}
}
if (user == null || user.status == null || user.status.expires == 0 || UserObject.isDeleted(user) || user instanceof TLRPC.TL_userEmpty) {
return getString("ALongTimeAgo", R.string.ALongTimeAgo);
} else {
int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime();
if (user.status.expires > currentTime) {
if (isOnline != null) {
isOnline[0] = true;
}
return getString("Online", R.string.Online);
} else {
if (user.status.expires == -1) {
return getString("Invisible", R.string.Invisible);
} else if (user.status.expires == -100) {
return getString("Lately", R.string.Lately);
} else if (user.status.expires == -101) {
return getString("WithinAWeek", R.string.WithinAWeek);
} else if (user.status.expires == -102) {
return getString("WithinAMonth", R.string.WithinAMonth);
} else {
return formatDateOnline(user.status.expires);
}
}
}
}
private String escapeString(String str) {
if (str.contains("[CDATA")) {
return str;
}
return str.replace("<", "&lt;").replace(">", "&gt;").replace("& ", "&amp; ");
}
public void saveRemoteLocaleStringsForCurrentLocale(final TLRPC.TL_langPackDifference difference, int currentAccount) {
if (currentLocaleInfo == null) {
return;
}
final String langCode = difference.lang_code.replace('-', '_').toLowerCase();
if (!langCode.equals(currentLocaleInfo.shortName) && !langCode.equals(currentLocaleInfo.baseLangCode)) {
return;
}
saveRemoteLocaleStrings(currentLocaleInfo, difference, currentAccount);
}
public void saveRemoteLocaleStrings(LocaleInfo localeInfo, final TLRPC.TL_langPackDifference difference, int currentAccount) {
if (difference == null || difference.strings.isEmpty() || localeInfo == null || localeInfo.isLocal()) {
return;
}
final String langCode = difference.lang_code.replace('-', '_').toLowerCase();
int type;
if (langCode.equals(localeInfo.shortName)) {
type = 0;
} else if (langCode.equals(localeInfo.baseLangCode)) {
type = 1;
} else {
type = -1;
}
if (type == -1) {
return;
}
File finalFile;
if (type == 0) {
finalFile = localeInfo.getPathToFile();
} else {
finalFile = localeInfo.getPathToBaseFile();
}
try {
final HashMap<String, String> values;
if (difference.from_version == 0) {
values = new HashMap<>();
} else {
values = getLocaleFileStrings(finalFile, true);
}
for (int a = 0; a < difference.strings.size(); a++) {
TLRPC.LangPackString string = difference.strings.get(a);
if (string instanceof TLRPC.TL_langPackString) {
values.put(string.key, escapeString(string.value));
} else if (string instanceof TLRPC.TL_langPackStringPluralized) {
values.put(string.key + "_zero", string.zero_value != null ? escapeString(string.zero_value) : "");
values.put(string.key + "_one", string.one_value != null ? escapeString(string.one_value) : "");
values.put(string.key + "_two", string.two_value != null ? escapeString(string.two_value) : "");
values.put(string.key + "_few", string.few_value != null ? escapeString(string.few_value) : "");
values.put(string.key + "_many", string.many_value != null ? escapeString(string.many_value) : "");
values.put(string.key + "_other", string.other_value != null ? escapeString(string.other_value) : "");
} else if (string instanceof TLRPC.TL_langPackStringDeleted) {
values.remove(string.key);
}
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("save locale file to " + finalFile);
}
BufferedWriter writer = new BufferedWriter(new FileWriter(finalFile));
writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
writer.write("<resources>\n");
for (HashMap.Entry<String, String> entry : values.entrySet()) {
writer.write(String.format("<string name=\"%1$s\">%2$s</string>\n", entry.getKey(), entry.getValue()));
}
writer.write("</resources>");
writer.close();
boolean hasBase = localeInfo.hasBaseLang();
final HashMap<String, String> valuesToSet = getLocaleFileStrings(hasBase ? localeInfo.getPathToBaseFile() : localeInfo.getPathToFile());
if (hasBase) {
valuesToSet.putAll(getLocaleFileStrings(localeInfo.getPathToFile()));
}
AndroidUtilities.runOnUIThread(() -> {
if (localeInfo != null) {
if (type == 0) {
localeInfo.version = difference.version;
} else {
localeInfo.baseVersion = difference.version;
}
}
saveOtherLanguages();
try {
if (currentLocaleInfo == localeInfo) {
Locale newLocale;
String[] args;
if (!TextUtils.isEmpty(localeInfo.pluralLangCode)) {
args = localeInfo.pluralLangCode.split("_");
} else if (!TextUtils.isEmpty(localeInfo.baseLangCode)) {
args = localeInfo.baseLangCode.split("_");
} else {
args = localeInfo.shortName.split("_");
}
if (args.length == 1) {
newLocale = new Locale(args[0]);
} else {
newLocale = new Locale(args[0], args[1]);
}
if (newLocale != null) {
languageOverride = localeInfo.shortName;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
editor.putString("language", localeInfo.getKey());
editor.apply();
}
if (newLocale != null) {
localeValues = valuesToSet;
currentLocale = newLocale;
currentLocaleInfo = localeInfo;
if (currentLocaleInfo != null && !TextUtils.isEmpty(currentLocaleInfo.pluralLangCode)) {
currentPluralRules = allRules.get(currentLocaleInfo.pluralLangCode);
}
if (currentPluralRules == null) {
currentPluralRules = allRules.get(currentLocale.getLanguage());
if (currentPluralRules == null) {
currentPluralRules = allRules.get("en");
}
}
changingConfiguration = true;
Locale.setDefault(currentLocale);
Configuration config = new Configuration();
config.locale = currentLocale;
ApplicationLoader.applicationContext.getResources().updateConfiguration(config, ApplicationLoader.applicationContext.getResources().getDisplayMetrics());
changingConfiguration = false;
}
}
} catch (Exception e) {
FileLog.e(e);
changingConfiguration = false;
}
recreateFormatters();
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.reloadInterface);
});
} catch (Exception ignore) {
}
}
public void loadRemoteLanguages(final int currentAccount) {
if (loadingRemoteLanguages) {
return;
}
loadingRemoteLanguages = true;
TLRPC.TL_langpack_getLanguages req = new TLRPC.TL_langpack_getLanguages();
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
if (response != null) {
AndroidUtilities.runOnUIThread(() -> {
loadingRemoteLanguages = false;
TLRPC.Vector res = (TLRPC.Vector) response;
for (int a = 0, size = remoteLanguages.size(); a < size; a++) {
remoteLanguages.get(a).serverIndex = Integer.MAX_VALUE;
}
for (int a = 0, size = res.objects.size(); a < size; a++) {
TLRPC.TL_langPackLanguage language = (TLRPC.TL_langPackLanguage) res.objects.get(a);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("loaded lang " + language.name);
}
LocaleInfo localeInfo = new LocaleInfo();
localeInfo.nameEnglish = language.name;
localeInfo.name = language.native_name;
localeInfo.shortName = language.lang_code.replace('-', '_').toLowerCase();
if (language.base_lang_code != null) {
localeInfo.baseLangCode = language.base_lang_code.replace('-', '_').toLowerCase();
} else {
localeInfo.baseLangCode = "";
}
localeInfo.pluralLangCode = language.plural_code.replace('-', '_').toLowerCase();
localeInfo.isRtl = language.rtl;
localeInfo.pathToFile = "remote";
localeInfo.serverIndex = a;
LocaleInfo existing = getLanguageFromDict(localeInfo.getKey());
if (existing == null) {
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
} else {
existing.nameEnglish = localeInfo.nameEnglish;
existing.name = localeInfo.name;
existing.baseLangCode = localeInfo.baseLangCode;
existing.pluralLangCode = localeInfo.pluralLangCode;
existing.pathToFile = localeInfo.pathToFile;
existing.serverIndex = localeInfo.serverIndex;
localeInfo = existing;
}
if (!remoteLanguagesDict.containsKey(localeInfo.getKey())) {
remoteLanguages.add(localeInfo);
remoteLanguagesDict.put(localeInfo.getKey(), localeInfo);
}
}
for (int a = 0; a < remoteLanguages.size(); a++) {
LocaleInfo info = remoteLanguages.get(a);
if (info.serverIndex != Integer.MAX_VALUE || info == currentLocaleInfo) {
continue;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("remove lang " + info.getKey());
}
remoteLanguages.remove(a);
remoteLanguagesDict.remove(info.getKey());
languages.remove(info);
languagesDict.remove(info.getKey());
a--;
}
saveOtherLanguages();
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.suggestedLangpack);
applyLanguage(currentLocaleInfo, true, false, currentAccount);
});
}
}, ConnectionsManager.RequestFlagWithoutLogin);
}
private void applyRemoteLanguage(LocaleInfo localeInfo, String langCode, boolean force, final int currentAccount) {
if (localeInfo == null || localeInfo != null && !localeInfo.isRemote() && !localeInfo.isUnofficial()) {
return;
}
if (localeInfo.hasBaseLang() && (langCode == null || langCode.equals(localeInfo.baseLangCode))) {
if (localeInfo.baseVersion != 0 && !force) {
if (localeInfo.hasBaseLang()) {
TLRPC.TL_langpack_getDifference req = new TLRPC.TL_langpack_getDifference();
req.from_version = localeInfo.baseVersion;
req.lang_code = localeInfo.getBaseLangCode();
req.lang_pack = "";
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
if (response != null) {
saveRemoteLocaleStrings(localeInfo, (TLRPC.TL_langPackDifference) response, currentAccount);
}
}, ConnectionsManager.RequestFlagWithoutLogin);
}
} else {
TLRPC.TL_langpack_getLangPack req = new TLRPC.TL_langpack_getLangPack();
req.lang_code = localeInfo.getBaseLangCode();
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (TLObject response, TLRPC.TL_error error) -> {
if (response != null) {
saveRemoteLocaleStrings(localeInfo, (TLRPC.TL_langPackDifference) response, currentAccount);
}
}, ConnectionsManager.RequestFlagWithoutLogin);
}
}
if (langCode == null || langCode.equals(localeInfo.shortName)) {
if (localeInfo.version != 0 && !force) {
TLRPC.TL_langpack_getDifference req = new TLRPC.TL_langpack_getDifference();
req.from_version = localeInfo.version;
req.lang_code = localeInfo.getLangCode();
req.lang_pack = "";
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
if (response != null) {
saveRemoteLocaleStrings(localeInfo, (TLRPC.TL_langPackDifference) response, currentAccount);
}
}, ConnectionsManager.RequestFlagWithoutLogin);
} else {
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
ConnectionsManager.setLangCode(localeInfo.getLangCode());
}
TLRPC.TL_langpack_getLangPack req = new TLRPC.TL_langpack_getLangPack();
req.lang_code = localeInfo.getLangCode();
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (TLObject response, TLRPC.TL_error error) -> {
if (response != null) {
saveRemoteLocaleStrings(localeInfo, (TLRPC.TL_langPackDifference) response, currentAccount);
}
}, ConnectionsManager.RequestFlagWithoutLogin);
}
}
}
private static String[] prebuilt;
private void loadPrebuiltLocaleFile(LocaleInfo localeInfo) {
if (prebuilt == null) {
try {
AssetManager assets = ApplicationLoader.applicationContext.getAssets();
prebuilt = assets.list("languages");
} catch (IOException e) {
FileLog.e(e);
return;
}
}
if (prebuilt == null) {
FileLog.w("empty prebuilt languages list");
return;
}
File pathToFile = localeInfo.getPathToFile();
File pathToBaseFile = localeInfo.getPathToBaseFile();
if ((pathToFile != null && !pathToFile.isFile()) || (pathToBaseFile != null && !pathToBaseFile.isFile())) {
try {
if (pathToBaseFile != null && !pathToBaseFile.isFile() && ArrayUtils.contains(prebuilt, pathToBaseFile.getName())) {
FileUtil.saveAsset("languages/" + pathToBaseFile.getName(), pathToBaseFile);
}
if (pathToFile != null && !pathToFile.isFile() && ArrayUtils.contains(prebuilt, pathToFile.getName())) {
FileUtil.saveAsset("languages/" + pathToFile.getName(), pathToFile);
}
} catch (Exception e) {
FileLog.e(e);
}
}
}
public String getTranslitString(String src) {
return getTranslitString(src, true, false);
}
public String getTranslitString(String src, boolean onlyEnglish) {
return getTranslitString(src, true, onlyEnglish);
}
public String getTranslitString(String src, boolean ru, boolean onlyEnglish) {
if (src == null) {
return null;
}
if (ruTranslitChars == null) {
ruTranslitChars = new HashMap<>(33);
ruTranslitChars.put("а", "a");
ruTranslitChars.put("б", "b");
ruTranslitChars.put("в", "v");
ruTranslitChars.put("г", "g");
ruTranslitChars.put("д", "d");
ruTranslitChars.put("е", "e");
ruTranslitChars.put("ё", "yo");
ruTranslitChars.put("ж", "zh");
ruTranslitChars.put("з", "z");
ruTranslitChars.put("и", "i");
ruTranslitChars.put("й", "i");
ruTranslitChars.put("к", "k");
ruTranslitChars.put("л", "l");
ruTranslitChars.put("м", "m");
ruTranslitChars.put("н", "n");
ruTranslitChars.put("о", "o");
ruTranslitChars.put("п", "p");
ruTranslitChars.put("р", "r");
ruTranslitChars.put("с", "s");
ruTranslitChars.put("т", "t");
ruTranslitChars.put("у", "u");
ruTranslitChars.put("ф", "f");
ruTranslitChars.put("х", "h");
ruTranslitChars.put("ц", "ts");
ruTranslitChars.put("ч", "ch");
ruTranslitChars.put("ш", "sh");
ruTranslitChars.put("щ", "sch");
ruTranslitChars.put("ы", "i");
ruTranslitChars.put("ь", "");
ruTranslitChars.put("ъ", "");
ruTranslitChars.put("э", "e");
ruTranslitChars.put("ю", "yu");
ruTranslitChars.put("я", "ya");
}
if (translitChars == null) {
translitChars = new HashMap<>(487);
translitChars.put("ȼ", "c");
translitChars.put("", "n");
translitChars.put("ɖ", "d");
translitChars.put("ỿ", "y");
translitChars.put("", "o");
translitChars.put("ø", "o");
translitChars.put("", "a");
translitChars.put("ʯ", "h");
translitChars.put("ŷ", "y");
translitChars.put("ʞ", "k");
translitChars.put("", "u");
translitChars.put("", "aa");
translitChars.put("ij", "ij");
translitChars.put("", "l");
translitChars.put("ɪ", "i");
translitChars.put("", "b");
translitChars.put("ʀ", "r");
translitChars.put("ě", "e");
translitChars.put("", "ffi");
translitChars.put("ơ", "o");
translitChars.put("", "r");
translitChars.put("", "o");
translitChars.put("ǐ", "i");
translitChars.put("", "p");
translitChars.put("ý", "y");
translitChars.put("", "e");
translitChars.put("", "o");
translitChars.put("", "a");
translitChars.put("ʙ", "b");
translitChars.put("", "e");
translitChars.put("ƈ", "c");
translitChars.put("ɦ", "h");
translitChars.put("", "b");
translitChars.put("", "s");
translitChars.put("đ", "d");
translitChars.put("", "o");
translitChars.put("ɟ", "j");
translitChars.put("", "a");
translitChars.put("ɏ", "y");
translitChars.put("ʌ", "v");
translitChars.put("", "p");
translitChars.put("", "fi");
translitChars.put("", "k");
translitChars.put("", "d");
translitChars.put("", "l");
translitChars.put("ė", "e");
translitChars.put("", "k");
translitChars.put("ċ", "c");
translitChars.put("ʁ", "r");
translitChars.put("ƕ", "hv");
translitChars.put("ƀ", "b");
translitChars.put("", "o");
translitChars.put("ȣ", "ou");
translitChars.put("ǰ", "j");
translitChars.put("", "g");
translitChars.put("", "n");
translitChars.put("ɉ", "j");
translitChars.put("ǧ", "g");
translitChars.put("dz", "dz");
translitChars.put("ź", "z");
translitChars.put("", "au");
translitChars.put("ǖ", "u");
translitChars.put("", "g");
translitChars.put("ȯ", "o");
translitChars.put("ɐ", "a");
translitChars.put("ą", "a");
translitChars.put("õ", "o");
translitChars.put("ɻ", "r");
translitChars.put("", "o");
translitChars.put("ǟ", "a");
translitChars.put("ȴ", "l");
translitChars.put("ʂ", "s");
translitChars.put("", "fl");
translitChars.put("ȉ", "i");
translitChars.put("", "e");
translitChars.put("", "n");
translitChars.put("ï", "i");
translitChars.put("ñ", "n");
translitChars.put("", "i");
translitChars.put("ʇ", "t");
translitChars.put("", "z");
translitChars.put("", "y");
translitChars.put("ȳ", "y");
translitChars.put("", "s");
translitChars.put("ɽ", "r");
translitChars.put("ĝ", "g");
translitChars.put("", "u");
translitChars.put("", "k");
translitChars.put("", "et");
translitChars.put("ī", "i");
translitChars.put("ť", "t");
translitChars.put("", "c");
translitChars.put("ʟ", "l");
translitChars.put("", "av");
translitChars.put("û", "u");
translitChars.put("æ", "ae");
translitChars.put("ă", "a");
translitChars.put("ǘ", "u");
translitChars.put("", "s");
translitChars.put("", "r");
translitChars.put("", "a");
translitChars.put("ƃ", "b");
translitChars.put("", "h");
translitChars.put("", "s");
translitChars.put("", "e");
translitChars.put("ʜ", "h");
translitChars.put("", "x");
translitChars.put("", "k");
translitChars.put("", "d");
translitChars.put("ƣ", "oi");
translitChars.put("", "p");
translitChars.put("ħ", "h");
translitChars.put("", "v");
translitChars.put("", "w");
translitChars.put("ǹ", "n");
translitChars.put("ɯ", "m");
translitChars.put("ɡ", "g");
translitChars.put("ɴ", "n");
translitChars.put("", "p");
translitChars.put("", "v");
translitChars.put("ū", "u");
translitChars.put("", "b");
translitChars.put("", "p");
translitChars.put("å", "a");
translitChars.put("ɕ", "c");
translitChars.put("", "o");
translitChars.put("", "a");
translitChars.put("ƒ", "f");
translitChars.put("ǣ", "ae");
translitChars.put("", "vy");
translitChars.put("", "ff");
translitChars.put("", "r");
translitChars.put("ô", "o");
translitChars.put("ǿ", "o");
translitChars.put("", "u");
translitChars.put("ȥ", "z");
translitChars.put("", "f");
translitChars.put("", "d");
translitChars.put("ȇ", "e");
translitChars.put("ȕ", "u");
translitChars.put("ȵ", "n");
translitChars.put("ʠ", "q");
translitChars.put("", "a");
translitChars.put("ǩ", "k");
translitChars.put("ĩ", "i");
translitChars.put("", "u");
translitChars.put("ŧ", "t");
translitChars.put("ɾ", "r");
translitChars.put("ƙ", "k");
translitChars.put("", "t");
translitChars.put("", "q");
translitChars.put("", "a");
translitChars.put("ʄ", "j");
translitChars.put("ƚ", "l");
translitChars.put("", "f");
translitChars.put("", "s");
translitChars.put("", "r");
translitChars.put("", "v");
translitChars.put("ɵ", "o");
translitChars.put("", "c");
translitChars.put("", "u");
translitChars.put("", "z");
translitChars.put("", "u");
translitChars.put("ň", "n");
translitChars.put("ʍ", "w");
translitChars.put("", "a");
translitChars.put("lj", "lj");
translitChars.put("ɓ", "b");
translitChars.put("ɼ", "r");
translitChars.put("ò", "o");
translitChars.put("", "w");
translitChars.put("ɗ", "d");
translitChars.put("", "ay");
translitChars.put("ư", "u");
translitChars.put("", "b");
translitChars.put("ǜ", "u");
translitChars.put("", "e");
translitChars.put("ǡ", "a");
translitChars.put("ɥ", "h");
translitChars.put("", "o");
translitChars.put("ǔ", "u");
translitChars.put("ʎ", "y");
translitChars.put("ȱ", "o");
translitChars.put("", "e");
translitChars.put("ế", "e");
translitChars.put("ĭ", "i");
translitChars.put("", "e");
translitChars.put("", "t");
translitChars.put("", "d");
translitChars.put("", "h");
translitChars.put("", "s");
translitChars.put("ë", "e");
translitChars.put("", "m");
translitChars.put("ö", "o");
translitChars.put("é", "e");
translitChars.put("ı", "i");
translitChars.put("ď", "d");
translitChars.put("", "m");
translitChars.put("", "y");
translitChars.put("ŵ", "w");
translitChars.put("", "e");
translitChars.put("", "u");
translitChars.put("ƶ", "z");
translitChars.put("ĵ", "j");
translitChars.put("", "d");
translitChars.put("ŭ", "u");
translitChars.put("ʝ", "j");
translitChars.put("ê", "e");
translitChars.put("ǚ", "u");
translitChars.put("ġ", "g");
translitChars.put("", "r");
translitChars.put("ƞ", "n");
translitChars.put("", "e");
translitChars.put("", "s");
translitChars.put("", "d");
translitChars.put("ķ", "k");
translitChars.put("", "ae");
translitChars.put("ɘ", "e");
translitChars.put("", "o");
translitChars.put("ḿ", "m");
translitChars.put("", "f");
translitChars.put("", "a");
translitChars.put("", "oo");
translitChars.put("", "m");
translitChars.put("", "p");
translitChars.put("", "u");
translitChars.put("", "k");
translitChars.put("", "h");
translitChars.put("ţ", "t");
translitChars.put("", "p");
translitChars.put("", "m");
translitChars.put("á", "a");
translitChars.put("", "n");
translitChars.put("", "v");
translitChars.put("è", "e");
translitChars.put("", "z");
translitChars.put("", "d");
translitChars.put("", "p");
translitChars.put("ɫ", "l");
translitChars.put("", "z");
translitChars.put("ɱ", "m");
translitChars.put("", "r");
translitChars.put("", "v");
translitChars.put("ũ", "u");
translitChars.put("ß", "ss");
translitChars.put("ĥ", "h");
translitChars.put("", "t");
translitChars.put("ʐ", "z");
translitChars.put("", "r");
translitChars.put("ɲ", "n");
translitChars.put("à", "a");
translitChars.put("", "y");
translitChars.put("", "y");
translitChars.put("", "oe");
translitChars.put("", "x");
translitChars.put("ȗ", "u");
translitChars.put("", "j");
translitChars.put("", "a");
translitChars.put("ʑ", "z");
translitChars.put("", "s");
translitChars.put("", "i");
translitChars.put("", "ao");
translitChars.put("ɀ", "z");
translitChars.put("ÿ", "y");
translitChars.put("ǝ", "e");
translitChars.put("ǭ", "o");
translitChars.put("", "d");
translitChars.put("", "l");
translitChars.put("ù", "u");
translitChars.put("", "a");
translitChars.put("", "b");
translitChars.put("", "u");
translitChars.put("", "a");
translitChars.put("", "t");
translitChars.put("ƴ", "y");
translitChars.put("", "t");
translitChars.put("", "l");
translitChars.put("ȷ", "j");
translitChars.put("", "z");
translitChars.put("", "h");
translitChars.put("", "w");
translitChars.put("", "k");
translitChars.put("", "o");
translitChars.put("î", "i");
translitChars.put("ģ", "g");
translitChars.put("ȅ", "e");
translitChars.put("ȧ", "a");
translitChars.put("", "a");
translitChars.put("ɋ", "q");
translitChars.put("", "t");
translitChars.put("", "um");
translitChars.put("", "c");
translitChars.put("", "x");
translitChars.put("", "u");
translitChars.put("", "i");
translitChars.put("", "r");
translitChars.put("ś", "s");
translitChars.put("", "o");
translitChars.put("", "y");
translitChars.put("", "s");
translitChars.put("nj", "nj");
translitChars.put("ȁ", "a");
translitChars.put("", "t");
translitChars.put("ĺ", "l");
translitChars.put("ž", "z");
translitChars.put("", "th");
translitChars.put("ƌ", "d");
translitChars.put("ș", "s");
translitChars.put("š", "s");
translitChars.put("", "u");
translitChars.put("", "e");
translitChars.put("", "s");
translitChars.put("ɇ", "e");
translitChars.put("", "u");
translitChars.put("", "o");
translitChars.put("ȿ", "s");
translitChars.put("", "v");
translitChars.put("", "is");
translitChars.put("", "o");
translitChars.put("ɛ", "e");
translitChars.put("ǻ", "a");
translitChars.put("", "ffl");
translitChars.put("", "o");
translitChars.put("ȋ", "i");
translitChars.put("", "ue");
translitChars.put("ȡ", "d");
translitChars.put("", "z");
translitChars.put("", "w");
translitChars.put("", "a");
translitChars.put("", "t");
translitChars.put("ğ", "g");
translitChars.put("ɳ", "n");
translitChars.put("ʛ", "g");
translitChars.put("", "u");
translitChars.put("", "a");
translitChars.put("", "n");
translitChars.put("ɨ", "i");
translitChars.put("", "r");
translitChars.put("ǎ", "a");
translitChars.put("ſ", "s");
translitChars.put("ȫ", "o");
translitChars.put("ɿ", "r");
translitChars.put("ƭ", "t");
translitChars.put("", "i");
translitChars.put("ǽ", "ae");
translitChars.put("", "v");
translitChars.put("ɶ", "oe");
translitChars.put("", "m");
translitChars.put("ż", "z");
translitChars.put("ĕ", "e");
translitChars.put("", "av");
translitChars.put("", "o");
translitChars.put("", "e");
translitChars.put("ɬ", "l");
translitChars.put("", "i");
translitChars.put("", "d");
translitChars.put("", "st");
translitChars.put("", "l");
translitChars.put("ŕ", "r");
translitChars.put("", "ou");
translitChars.put("ʈ", "t");
translitChars.put("ā", "a");
translitChars.put("", "e");
translitChars.put("", "o");
translitChars.put("ç", "c");
translitChars.put("", "s");
translitChars.put("", "a");
translitChars.put("ų", "u");
translitChars.put("", "a");
translitChars.put("ǥ", "g");
translitChars.put("", "k");
translitChars.put("", "z");
translitChars.put("ŝ", "s");
translitChars.put("", "e");
translitChars.put("ɠ", "g");
translitChars.put("", "l");
translitChars.put("", "f");
translitChars.put("", "x");
translitChars.put("ǒ", "o");
translitChars.put("ę", "e");
translitChars.put("", "o");
translitChars.put("ƫ", "t");
translitChars.put("ǫ", "o");
translitChars.put("", "i");
translitChars.put("", "n");
translitChars.put("ć", "c");
translitChars.put("", "g");
translitChars.put("", "w");
translitChars.put("", "d");
translitChars.put("", "l");
translitChars.put("œ", "oe");
translitChars.put("", "r");
translitChars.put("ļ", "l");
translitChars.put("ȑ", "r");
translitChars.put("ȭ", "o");
translitChars.put("", "n");
translitChars.put("", "ae");
translitChars.put("ŀ", "l");
translitChars.put("ä", "a");
translitChars.put("ƥ", "p");
translitChars.put("", "o");
translitChars.put("į", "i");
translitChars.put("ȓ", "r");
translitChars.put("dž", "dz");
translitChars.put("", "g");
translitChars.put("", "u");
translitChars.put("ō", "o");
translitChars.put("ľ", "l");
translitChars.put("", "w");
translitChars.put("ț", "t");
translitChars.put("ń", "n");
translitChars.put("ɍ", "r");
translitChars.put("ȃ", "a");
translitChars.put("ü", "u");
translitChars.put("", "l");
translitChars.put("", "o");
translitChars.put("", "o");
translitChars.put("", "b");
translitChars.put("ɹ", "r");
translitChars.put("", "r");
translitChars.put("ʏ", "y");
translitChars.put("", "f");
translitChars.put("", "h");
translitChars.put("ŏ", "o");
translitChars.put("ú", "u");
translitChars.put("", "r");
translitChars.put("ʮ", "h");
translitChars.put("ó", "o");
translitChars.put("ů", "u");
translitChars.put("", "o");
translitChars.put("", "p");
translitChars.put("", "i");
translitChars.put("", "u");
translitChars.put("ã", "a");
translitChars.put("", "i");
translitChars.put("", "t");
translitChars.put("", "e");
translitChars.put("", "u");
translitChars.put("í", "i");
translitChars.put("ɔ", "o");
translitChars.put("ɺ", "r");
translitChars.put("ɢ", "g");
translitChars.put("ř", "r");
translitChars.put("", "h");
translitChars.put("ű", "u");
translitChars.put("ȍ", "o");
translitChars.put("", "l");
translitChars.put("", "h");
translitChars.put("ȶ", "t");
translitChars.put("ņ", "n");
translitChars.put("", "e");
translitChars.put("ì", "i");
translitChars.put("", "w");
translitChars.put("ē", "e");
translitChars.put("", "e");
translitChars.put("ł", "l");
translitChars.put("", "o");
translitChars.put("ɭ", "l");
translitChars.put("", "y");
translitChars.put("", "j");
translitChars.put("", "k");
translitChars.put("ṿ", "v");
translitChars.put("ȩ", "e");
translitChars.put("â", "a");
translitChars.put("ş", "s");
translitChars.put("ŗ", "r");
translitChars.put("ʋ", "v");
translitChars.put("", "a");
translitChars.put("", "c");
translitChars.put("", "e");
translitChars.put("ɰ", "m");
translitChars.put("", "w");
translitChars.put("ȏ", "o");
translitChars.put("č", "c");
translitChars.put("ǵ", "g");
translitChars.put("ĉ", "c");
translitChars.put("", "o");
translitChars.put("", "k");
translitChars.put("", "q");
translitChars.put("", "o");
translitChars.put("", "s");
translitChars.put("", "o");
translitChars.put("ȟ", "h");
translitChars.put("ő", "o");
translitChars.put("", "tz");
translitChars.put("", "e");
}
StringBuilder dst = new StringBuilder(src.length());
int len = src.length();
boolean upperCase = false;
for (int a = 0; a < len; a++) {
String ch = src.substring(a, a + 1);
if (onlyEnglish) {
String lower = ch.toLowerCase();
upperCase = !ch.equals(lower);
ch = lower;
}
String tch = translitChars.get(ch);
if (tch == null && ru) {
tch = ruTranslitChars.get(ch);
}
if (tch != null) {
if (onlyEnglish && upperCase) {
if (tch.length() > 1) {
tch = tch.substring(0, 1).toUpperCase() + tch.substring(1);
} else {
tch = tch.toUpperCase();
}
}
dst.append(tch);
} else {
if (onlyEnglish) {
char c = ch.charAt(0);
if (((c < 'a' || c > 'z') || (c < '0' || c > '9')) && c != ' ' && c != '\'' && c != ',' && c != '.' && c != '&' && c != '-' && c != '/') {
return null;
}
if (upperCase) {
ch = ch.toUpperCase();
}
}
dst.append(ch);
}
}
return dst.toString();
}
abstract public static class PluralRules {
abstract int quantityForNumber(int n);
}
public static class PluralRules_Zero extends PluralRules {
public int quantityForNumber(int count) {
if (count == 0 || count == 1) {
return QUANTITY_ONE;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Welsh extends PluralRules {
public int quantityForNumber(int count) {
if (count == 0) {
return QUANTITY_ZERO;
} else if (count == 1) {
return QUANTITY_ONE;
} else if (count == 2) {
return QUANTITY_TWO;
} else if (count == 3) {
return QUANTITY_FEW;
} else if (count == 6) {
return QUANTITY_MANY;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Two extends PluralRules {
public int quantityForNumber(int count) {
if (count == 1) {
return QUANTITY_ONE;
} else if (count == 2) {
return QUANTITY_TWO;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Tachelhit extends PluralRules {
public int quantityForNumber(int count) {
if (count >= 0 && count <= 1) {
return QUANTITY_ONE;
} else if (count >= 2 && count <= 10) {
return QUANTITY_FEW;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Slovenian extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
if (rem100 == 1) {
return QUANTITY_ONE;
} else if (rem100 == 2) {
return QUANTITY_TWO;
} else if (rem100 >= 3 && rem100 <= 4) {
return QUANTITY_FEW;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Romanian extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
if (count == 1) {
return QUANTITY_ONE;
} else if ((count == 0 || (rem100 >= 1 && rem100 <= 19))) {
return QUANTITY_FEW;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Polish extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
int rem10 = count % 10;
if (count == 1) {
return QUANTITY_ONE;
} else if (rem10 >= 2 && rem10 <= 4 && !(rem100 >= 12 && rem100 <= 14)) {
return QUANTITY_FEW;
} else if (rem10 >= 0 && rem10 <= 1 || rem10 >= 5 && rem10 <= 9 || rem100 >= 12 && rem100 <= 14) {
return QUANTITY_MANY;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_One extends PluralRules {
public int quantityForNumber(int count) {
return count == 1 ? QUANTITY_ONE : QUANTITY_OTHER;
}
}
public static class PluralRules_None extends PluralRules {
public int quantityForNumber(int count) {
return QUANTITY_OTHER;
}
}
public static class PluralRules_Maltese extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
if (count == 1) {
return QUANTITY_ONE;
} else if (count == 0 || (rem100 >= 2 && rem100 <= 10)) {
return QUANTITY_FEW;
} else if (rem100 >= 11 && rem100 <= 19) {
return QUANTITY_MANY;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Macedonian extends PluralRules {
public int quantityForNumber(int count) {
if (count % 10 == 1 && count != 11) {
return QUANTITY_ONE;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Lithuanian extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
int rem10 = count % 10;
if (rem10 == 1 && !(rem100 >= 11 && rem100 <= 19)) {
return QUANTITY_ONE;
} else if (rem10 >= 2 && rem10 <= 9 && !(rem100 >= 11 && rem100 <= 19)) {
return QUANTITY_FEW;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Latvian extends PluralRules {
public int quantityForNumber(int count) {
if (count == 0) {
return QUANTITY_ZERO;
} else if (count % 10 == 1 && count % 100 != 11) {
return QUANTITY_ONE;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Langi extends PluralRules {
public int quantityForNumber(int count) {
if (count == 0) {
return QUANTITY_ZERO;
} else if (count == 1) {
return QUANTITY_ONE;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_French extends PluralRules {
public int quantityForNumber(int count) {
if (count >= 0 && count < 2) {
return QUANTITY_ONE;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Czech extends PluralRules {
public int quantityForNumber(int count) {
if (count == 1) {
return QUANTITY_ONE;
} else if (count >= 2 && count <= 4) {
return QUANTITY_FEW;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Breton extends PluralRules {
public int quantityForNumber(int count) {
if (count == 0) {
return QUANTITY_ZERO;
} else if (count == 1) {
return QUANTITY_ONE;
} else if (count == 2) {
return QUANTITY_TWO;
} else if (count == 3) {
return QUANTITY_FEW;
} else if (count == 6) {
return QUANTITY_MANY;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Balkan extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
int rem10 = count % 10;
if (rem10 == 1 && rem100 != 11) {
return QUANTITY_ONE;
} else if (rem10 >= 2 && rem10 <= 4 && !(rem100 >= 12 && rem100 <= 14)) {
return QUANTITY_FEW;
} else if ((rem10 == 0 || (rem10 >= 5 && rem10 <= 9) || (rem100 >= 11 && rem100 <= 14))) {
return QUANTITY_MANY;
} else {
return QUANTITY_OTHER;
}
}
}
public static class PluralRules_Arabic extends PluralRules {
public int quantityForNumber(int count) {
int rem100 = count % 100;
if (count == 0) {
return QUANTITY_ZERO;
} else if (count == 1) {
return QUANTITY_ONE;
} else if (count == 2) {
return QUANTITY_TWO;
} else if (rem100 >= 3 && rem100 <= 10) {
return QUANTITY_FEW;
} else if (rem100 >= 11 && rem100 <= 99) {
return QUANTITY_MANY;
} else {
return QUANTITY_OTHER;
}
}
}
public static String addNbsp(String src) {
return src.replace(' ', '\u00A0');
}
private static Boolean useImperialSystemType;
public static void resetImperialSystemType() {
useImperialSystemType = null;
}
public static String formatDistance(float distance) {
if (useImperialSystemType == null) {
if (SharedConfig.distanceSystemType == 0) {
try {
TelephonyManager telephonyManager = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
String country = telephonyManager.getSimCountryIso().toUpperCase();
useImperialSystemType = "US".equals(country) || "GB".equals(country) || "MM".equals(country) || "LR".equals(country);
}
} catch (Exception e) {
useImperialSystemType = false;
FileLog.e(e);
}
} else {
useImperialSystemType = SharedConfig.distanceSystemType == 2;
}
}
if (useImperialSystemType) {
distance *= 3.28084f;
if (distance < 1000) {
return formatString("FootsAway", R.string.FootsAway, String.format("%d", (int) Math.max(1, distance)));
} else {
String arg;
if (distance % 5280 == 0) {
arg = String.format("%d", (int) (distance / 5280));
} else {
arg = String.format("%.2f", distance / 5280.0f);
}
return formatString("MilesAway", R.string.MilesAway, arg);
}
} else {
if (distance < 1000) {
return formatString("MetersAway2", R.string.MetersAway2, String.format("%d", (int) Math.max(1, distance)));
} else {
String arg;
if (distance % 1000 == 0) {
arg = String.format("%d", (int) (distance / 1000));
} else {
arg = String.format("%.2f", distance / 1000.0f);
}
return formatString("KMetersAway2", R.string.KMetersAway2, arg);
}
}
}
}