Browse Source

Merge pull request #2882 from bluen/develop

Respect user's locale when sorting language list
Tobias Hagemann 1 year ago
parent
commit
532ffb1202

+ 26 - 12
src/main/java/org/cryptomator/launcher/SupportedLanguages.java

@@ -1,39 +1,53 @@
 package org.cryptomator.launcher;
 package org.cryptomator.launcher;
 
 
 import org.cryptomator.common.settings.Settings;
 import org.cryptomator.common.settings.Settings;
-import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 
 
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
+import java.text.Collator;
+import java.util.Collections;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
+import java.util.stream.Collectors;
 
 
 @Singleton
 @Singleton
 public class SupportedLanguages {
 public class SupportedLanguages {
 
 
 	private static final Logger LOG = LoggerFactory.getLogger(SupportedLanguages.class);
 	private static final Logger LOG = LoggerFactory.getLogger(SupportedLanguages.class);
-	// these are BCP 47 language codes, not ISO. Note the "-" instead of the "_":
-	public static final List<String> LANGUAGAE_TAGS = List.of("en", "ar", "be", "bn", "bs", "ca", "cs", "da", "de", "el", "es", "fil", "fa", "fr", "gl", "he", //
+	// these are BCP 47 language codes, not ISO. Note the "-" instead of the "_".
+	// "en" is not part of this list - it is always inserted at the top.
+	public static final List<String> LANGUAGE_TAGS = List.of("ar", "be", "bn", "bs", "ca", "cs", "da", "de", "el", "es", "fil", "fa", "fr", "gl", "he", //
 			"hi", "hr", "hu", "id", "it", "ja", "ko", "lv", "mk", "nb", "nl", "nn", "no", "pa", "pl", "pt", "pt-BR", "ro", "ru", "si", "sk", "sr", "sr-Latn", "sv", "sw", //
 			"hi", "hr", "hu", "id", "it", "ja", "ko", "lv", "mk", "nb", "nl", "nn", "no", "pa", "pl", "pt", "pt-BR", "ro", "ru", "si", "sk", "sr", "sr-Latn", "sv", "sw", //
 			"ta", "te", "th", "tr", "uk", "vi", "zh", "zh-HK", "zh-TW");
 			"ta", "te", "th", "tr", "uk", "vi", "zh", "zh-HK", "zh-TW");
+	public static final String ENGLISH = "en";
 
 
-	@Nullable
-	private final String preferredLanguage;
+	private final List<String> sortedLanguageTags;
+
+	private final Locale preferredLocale;
 
 
 	@Inject
 	@Inject
 	public SupportedLanguages(Settings settings) {
 	public SupportedLanguages(Settings settings) {
-		this.preferredLanguage = settings.languageProperty().get();
+		var preferredLanguage = settings.languageProperty().get();
+		preferredLocale = preferredLanguage == null ? Locale.getDefault() : Locale.forLanguageTag(preferredLanguage);
+		var collator = Collator.getInstance(preferredLocale);
+		collator.setStrength(Collator.PRIMARY);
+		var sorted = LANGUAGE_TAGS.stream() //
+				.sorted((a, b) -> collator.compare(Locale.forLanguageTag(a).getDisplayName(), Locale.forLanguageTag(b).getDisplayName())) //
+				.collect(Collectors.toList());
+		sorted.add(0, Settings.DEFAULT_LANGUAGE);
+		sorted.add(1, ENGLISH);
+		sortedLanguageTags = Collections.unmodifiableList(sorted);
 	}
 	}
 
 
 	public void applyPreferred() {
 	public void applyPreferred() {
-		if (preferredLanguage == null) {
-			LOG.debug("Using system locale");
-			return;
-		}
-		var preferredLocale = Locale.forLanguageTag(preferredLanguage);
-		LOG.debug("Applying preferred locale {}", preferredLocale.getDisplayName(Locale.ENGLISH));
+		LOG.debug("Using locale {}", preferredLocale);
 		Locale.setDefault(preferredLocale);
 		Locale.setDefault(preferredLocale);
 	}
 	}
+
+	public List<String> getLanguageTags() {
+		return sortedLanguageTags;
+	}
+
 }
 }

+ 5 - 7
src/main/java/org/cryptomator/ui/preferences/InterfacePreferencesController.java

@@ -1,6 +1,5 @@
 package org.cryptomator.ui.preferences;
 package org.cryptomator.ui.preferences;
 
 
-import com.google.common.base.Strings;
 import org.cryptomator.common.LicenseHolder;
 import org.cryptomator.common.LicenseHolder;
 import org.cryptomator.common.settings.Settings;
 import org.cryptomator.common.settings.Settings;
 import org.cryptomator.common.settings.UiTheme;
 import org.cryptomator.common.settings.UiTheme;
@@ -35,6 +34,7 @@ public class InterfacePreferencesController implements FxController {
 	private final ObjectProperty<SelectedPreferencesTab> selectedTabProperty;
 	private final ObjectProperty<SelectedPreferencesTab> selectedTabProperty;
 	private final LicenseHolder licenseHolder;
 	private final LicenseHolder licenseHolder;
 	private final ResourceBundle resourceBundle;
 	private final ResourceBundle resourceBundle;
+	private final SupportedLanguages supportedLanguages;
 	public ChoiceBox<UiTheme> themeChoiceBox;
 	public ChoiceBox<UiTheme> themeChoiceBox;
 	public CheckBox showMinimizeButtonCheckbox;
 	public CheckBox showMinimizeButtonCheckbox;
 	public CheckBox showTrayIconCheckbox;
 	public CheckBox showTrayIconCheckbox;
@@ -44,13 +44,14 @@ public class InterfacePreferencesController implements FxController {
 	public RadioButton nodeOrientationRtl;
 	public RadioButton nodeOrientationRtl;
 
 
 	@Inject
 	@Inject
-	InterfacePreferencesController(Settings settings, TrayMenuComponent trayMenu, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ResourceBundle resourceBundle) {
+	InterfacePreferencesController(Settings settings, SupportedLanguages supportedLanguages, TrayMenuComponent trayMenu, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ResourceBundle resourceBundle) {
 		this.settings = settings;
 		this.settings = settings;
 		this.trayMenuInitialized = trayMenu.isInitialized();
 		this.trayMenuInitialized = trayMenu.isInitialized();
 		this.trayMenuSupported = trayMenu.isSupported();
 		this.trayMenuSupported = trayMenu.isSupported();
 		this.selectedTabProperty = selectedTabProperty;
 		this.selectedTabProperty = selectedTabProperty;
 		this.licenseHolder = licenseHolder;
 		this.licenseHolder = licenseHolder;
 		this.resourceBundle = resourceBundle;
 		this.resourceBundle = resourceBundle;
+		this.supportedLanguages = supportedLanguages;
 	}
 	}
 
 
 	@FXML
 	@FXML
@@ -66,8 +67,7 @@ public class InterfacePreferencesController implements FxController {
 
 
 		showTrayIconCheckbox.selectedProperty().bindBidirectional(settings.showTrayIcon());
 		showTrayIconCheckbox.selectedProperty().bindBidirectional(settings.showTrayIcon());
 
 
-		preferredLanguageChoiceBox.getItems().add(null);
-		preferredLanguageChoiceBox.getItems().addAll(SupportedLanguages.LANGUAGAE_TAGS);
+		preferredLanguageChoiceBox.getItems().addAll(supportedLanguages.getLanguageTags());
 		preferredLanguageChoiceBox.valueProperty().bindBidirectional(settings.languageProperty());
 		preferredLanguageChoiceBox.valueProperty().bindBidirectional(settings.languageProperty());
 		preferredLanguageChoiceBox.setConverter(new LanguageTagConverter(resourceBundle));
 		preferredLanguageChoiceBox.setConverter(new LanguageTagConverter(resourceBundle));
 
 
@@ -141,9 +141,7 @@ public class InterfacePreferencesController implements FxController {
 				return resourceBundle.getString("preferences.interface.language.auto");
 				return resourceBundle.getString("preferences.interface.language.auto");
 			} else {
 			} else {
 				var locale = Locale.forLanguageTag(tag);
 				var locale = Locale.forLanguageTag(tag);
-				var lang = locale.getDisplayLanguage(locale);
-				var region = locale.getDisplayCountry(locale);
-				return lang + (Strings.isNullOrEmpty(region) ? "" : " (" + region + ")");
+				return locale.getDisplayName();
 			}
 			}
 		}
 		}
 
 

+ 1 - 1
src/test/java/org/cryptomator/launcher/SupportedLanguagesTest.java

@@ -25,7 +25,7 @@ public class SupportedLanguagesTest {
 	}
 	}
 
 
 	public static Stream<String> languageTags() {
 	public static Stream<String> languageTags() {
-		return SupportedLanguages.LANGUAGAE_TAGS.stream() //
+		return SupportedLanguages.LANGUAGE_TAGS.stream() //
 				.filter(tag -> !"en".equals(tag)); // english uses the default bundle
 				.filter(tag -> !"en".equals(tag)); // english uses the default bundle
 	}
 	}
 }
 }