Allow "System language" to be set as language option
Populate "System language" as a first class item in the language preference list so that users can select it in scenarios where they have previously selected a specific language, and wish to go back to the default.
This commit is contained in:
@@ -78,8 +78,8 @@ namespace keepass2android
|
||||
{
|
||||
if (!languageLoaded)
|
||||
{
|
||||
var language = PreferenceManager.GetDefaultSharedPreferences(c).GetString(c.GetString(Resource.String.app_language_pref_key), null);
|
||||
Language = language;
|
||||
var langPref = PreferenceManager.GetDefaultSharedPreferences(c).GetString(c.GetString(Resource.String.app_language_pref_key), null);
|
||||
Language = LanguageEntry.PrefCodeToLanguage(langPref);
|
||||
}
|
||||
return Language;
|
||||
}
|
||||
@@ -109,8 +109,68 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A small container/wrapper that helps with the building and sorting of the
|
||||
/// Language Preference list, and interoperability between it and LocaleManager
|
||||
/// </summary>
|
||||
class LanguageEntry
|
||||
{
|
||||
// "System language" preference code; maps to LocaleManager.Language = null
|
||||
private const string SYS_LANG_CODE = "SysLang";
|
||||
|
||||
public class Util {
|
||||
// Preference code (2-char lowercase, or SYS_LANG_CODE)
|
||||
public readonly string Code;
|
||||
// Localized display name
|
||||
public readonly string Name;
|
||||
// True if this LanguageEntry is the "System language", false otherwise
|
||||
public readonly bool IsSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a LanguageEntry from a Locale
|
||||
/// </summary>
|
||||
/// <param name="from"></param>
|
||||
/// <returns></returns>
|
||||
public static LanguageEntry OfLocale(Java.Util.Locale from)
|
||||
{
|
||||
return new LanguageEntry(from.Language, from.DisplayLanguage, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the "System language" LanguageEntry with the given localized display name,
|
||||
/// special preference code, marked as a System entry.
|
||||
/// </summary>
|
||||
/// <param name="displayName"></param>
|
||||
/// <returns></returns>
|
||||
public static LanguageEntry SystemDefault(string displayName)
|
||||
{
|
||||
return new LanguageEntry(SYS_LANG_CODE, displayName, true);
|
||||
}
|
||||
|
||||
private LanguageEntry(string code, string name, bool isSystem)
|
||||
{
|
||||
this.Code = code;
|
||||
this.Name = name;
|
||||
this.IsSystem = isSystem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a language preference code to a code that is compatible with LocaleManager.Language
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <returns>A converted code, possibly null</returns>
|
||||
public static string PrefCodeToLanguage(string code)
|
||||
{
|
||||
return string.IsNullOrEmpty(code) || SYS_LANG_CODE.Equals(code) ? null : code;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" + this.Code + ":" + this.Name + "}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Util {
|
||||
|
||||
|
||||
public const String KeyFilename = "fileName";
|
||||
|
||||
@@ -41,10 +41,12 @@ using KeePassLib.Cryptography.KeyDerivation;
|
||||
using KeePassLib.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
//http://stackoverflow.com/a/27422401/292233
|
||||
public class SettingsFragment : PreferenceFragment
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
public class SettingsFragment : PreferenceFragment
|
||||
{
|
||||
|
||||
|
||||
@@ -177,36 +179,8 @@ namespace keepass2android
|
||||
FindPreference(GetString(Resource.String.DebugLog_send_key)).PreferenceClick += OnSendDebug;
|
||||
|
||||
HashSet<string> supportedLocales = new HashSet<string>() { "en", "af", "ar", "az", "be", "bg", "ca", "cs", "da", "de", "el", "es", "eu", "fa", "fi", "fr", "gl", "he", "hr", "hu", "id", "in", "it", "iw", "ja", "ko", "ml", "nb", "nl", "nn", "no", "pl", "pt", "ro", "ru", "si", "sk", "sl", "sr", "sv", "tr", "uk", "vi", "zh" };
|
||||
|
||||
ListPreference appLanguagePref = (ListPreference)FindPreference(GetString(Resource.String.app_language_pref_key));
|
||||
|
||||
var localesByCode = new System.Collections.Generic.Dictionary<string, List<Java.Util.Locale>>();
|
||||
foreach (var loc in Java.Util.Locale.GetAvailableLocales())
|
||||
{
|
||||
if (!supportedLocales.Contains(loc.Language))
|
||||
continue;
|
||||
if (!localesByCode.ContainsKey(loc.Language))
|
||||
{
|
||||
localesByCode[loc.Language] = new List<Java.Util.Locale>();
|
||||
}
|
||||
localesByCode[loc.Language].Add(loc);
|
||||
|
||||
}
|
||||
var localesByCodeUnique = localesByCode.Select(l => new KeyValuePair<string, Java.Util.Locale>(l.Key, l.Value.First())).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
List<KeyValuePair<string, List<Java.Util.Locale>>> codesWithMultiple = localesByCode.Where(l => l.Value.Count > 1).ToList();
|
||||
List<KeyValuePair<string, Java.Util.Locale>> localesByLanguageList = localesByCodeUnique
|
||||
.OrderBy(kvp => kvp.Value.DisplayLanguage).ToList();
|
||||
appLanguagePref.SetEntries(localesByLanguageList.Select(kvp => kvp.Value.DisplayLanguage).ToArray());
|
||||
appLanguagePref.SetEntryValues(localesByLanguageList.Select(kvp => kvp.Value.Language).ToArray());
|
||||
string languageCode = appLanguagePref.Value;
|
||||
string summary = GetDisplayLanguage(localesByCodeUnique, languageCode);
|
||||
((ListPreference)FindPreference(GetString(Resource.String.app_language_pref_key))).Summary = summary;
|
||||
appLanguagePref.PreferenceChange += (sender, args) =>
|
||||
{
|
||||
((ListPreference)FindPreference(GetString(Resource.String.app_language_pref_key))).Summary = GetDisplayLanguage(localesByCodeUnique, (string)args.NewValue);
|
||||
LocaleManager.Language = (string)args.NewValue;
|
||||
};
|
||||
|
||||
var languagePref = (ListPreference)FindPreference(GetString(Resource.String.app_language_pref_key));
|
||||
new AppLanguageManager(this, languagePref, supportedLocales);
|
||||
|
||||
UpdateAutofillPref();
|
||||
|
||||
@@ -347,16 +321,6 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
private string GetDisplayLanguage(Dictionary<string, Java.Util.Locale> localesByCode, string languageCode)
|
||||
{
|
||||
return languageCode != null && localesByCode.ContainsKey(languageCode) ? localesByCode[languageCode]?.DisplayLanguage : GetString(Resource.String.SystemLanguage);
|
||||
}
|
||||
|
||||
private void AppLanguagePref_PreferenceChange(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void UpdateAutofillPref()
|
||||
{
|
||||
var autofillScreen = FindPreference(GetString(Resource.String.AutoFill_prefs_screen_key));
|
||||
@@ -897,10 +861,102 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
|
||||
/// </summary>
|
||||
/// <para>
|
||||
/// A helper class that manages language preference display and selection.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The idea is to provide a ListPreference with a "System language" item at the top, followed by
|
||||
/// the localized list of supported language names. The items are backed by their corresponding "code".
|
||||
/// For a langauge that's the 2-char lowercase language code, which is exactly the same code that
|
||||
/// LocaleManager.Language expects.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// "System language" is a special case. LocaleManager.Language expects null, but ListPreference
|
||||
/// does not support null as a valid code. To work around this, LanguageEntry.SYS_LANG_CODE
|
||||
/// is used as the preference code. LanguageEntry.PrefCodeToLanguage(string) is used to convert the
|
||||
/// preference codes to language codes as needed.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
internal class AppLanguageManager
|
||||
{
|
||||
private readonly PreferenceFragment _fragment;
|
||||
private readonly ListPreference _langPref;
|
||||
private readonly Dictionary<string, LanguageEntry> _langEntriesByCodeUnique;
|
||||
|
||||
public AppLanguageManager(PreferenceFragment fragment, ListPreference langPref, HashSet<string> supportedLocales)
|
||||
{
|
||||
this._fragment = fragment;
|
||||
this._langPref = langPref;
|
||||
this._langEntriesByCodeUnique = CreateCodeToEntryMapping(fragment, supportedLocales);
|
||||
|
||||
ConfigureLanguageList();
|
||||
}
|
||||
|
||||
private static Dictionary<string, LanguageEntry> CreateCodeToEntryMapping(PreferenceFragment fragment, HashSet<string> supportedLocales)
|
||||
{
|
||||
var localesByCode = new Dictionary<string, List<Java.Util.Locale>>();
|
||||
foreach (var loc in Java.Util.Locale.GetAvailableLocales())
|
||||
{
|
||||
if (!supportedLocales.Contains(loc.Language))
|
||||
continue;
|
||||
if (!localesByCode.ContainsKey(loc.Language))
|
||||
{
|
||||
localesByCode[loc.Language] = new List<Java.Util.Locale>();
|
||||
}
|
||||
localesByCode[loc.Language].Add(loc);
|
||||
}
|
||||
|
||||
var langEntriesByCodeUnique = localesByCode
|
||||
.Select(l => new KeyValuePair<string, LanguageEntry>(l.Key, LanguageEntry.OfLocale(l.Value.First())))
|
||||
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
|
||||
var sysLangEntry = LanguageEntry.SystemDefault(fragment.GetString(Resource.String.SystemLanguage));
|
||||
langEntriesByCodeUnique.Add(sysLangEntry.Code, sysLangEntry);
|
||||
|
||||
return langEntriesByCodeUnique;
|
||||
}
|
||||
|
||||
private void ConfigureLanguageList()
|
||||
{
|
||||
List<KeyValuePair<string, LanguageEntry>> langEntriesList = _langEntriesByCodeUnique
|
||||
.OrderByDescending(kvp => kvp.Value.IsSystem)
|
||||
.ThenBy(kvp => kvp.Value.Name)
|
||||
.ToList();
|
||||
|
||||
_langPref.SetEntries(langEntriesList
|
||||
.Select(kvp => kvp.Value.Name)
|
||||
.ToArray());
|
||||
_langPref.SetEntryValues(langEntriesList
|
||||
.Select(kvp => kvp.Value.Code)
|
||||
.ToArray());
|
||||
|
||||
_langPref.Summary = GetDisplayLanguage(LanguageEntry.PrefCodeToLanguage(_langPref.Value));
|
||||
_langPref.PreferenceChange += AppLanguagePrefChange;
|
||||
}
|
||||
|
||||
private string GetDisplayLanguage(string languageCode)
|
||||
{
|
||||
if (languageCode != null && this._langEntriesByCodeUnique.ContainsKey(languageCode))
|
||||
return this._langEntriesByCodeUnique[languageCode]?.Name;
|
||||
else
|
||||
return _fragment.GetString(Resource.String.SystemLanguage);
|
||||
}
|
||||
|
||||
private void AppLanguagePrefChange(object sender, Preference.PreferenceChangeEventArgs args)
|
||||
{
|
||||
string langCode = LanguageEntry.PrefCodeToLanguage((string)args.NewValue);
|
||||
LocaleManager.Language = langCode;
|
||||
_langPref.Summary = GetDisplayLanguage(langCode);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
|
||||
/// </summary>
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)]
|
||||
public class DatabaseSettingsActivity : LockCloseActivity
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user