Skip to content

Commit

Permalink
feat: allow runtime language switching
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDead committed Jan 20, 2025
1 parent cee75d5 commit 99c3822
Show file tree
Hide file tree
Showing 18 changed files with 377 additions and 123 deletions.
247 changes: 221 additions & 26 deletions src/main/java/com/codedead/opal/controller/MainWindowController.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -184,19 +184,23 @@ private void loadSettings() {
private void resetSettingsAction() {
logger.info("Attempting to reset all settings");
if (FxUtils.showConfirmationAlert(translationBundle.getString("ConfirmReset"), getClass().getResourceAsStream(SharedVariables.ICON_URL))) {
showAlertIfLanguageMismatch(DEFAULT_LOCALE);

Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
try {
settingsController.createDefaultProperties();
settingsController.setProperties(settingsController.readPropertiesFile());

final Locale locale = Locale.forLanguageTag(DEFAULT_LOCALE);
final ResourceBundle translationBundle = ResourceBundle.getBundle("translations.OpalApplication", locale);

mainWindowController.updateResourceBundle(translationBundle);

mainWindowController.loadMediaButtonVisibility(Boolean.parseBoolean(settingsController.getProperties().getProperty("mediaButtons", "true")));
mainWindowController.setAudioBalance(Double.parseDouble(settingsController.getProperties().getProperty("audioBalance", "0.0")));

trayIconController.hideTrayIcon();

loadSettings();
Stage stage = (Stage) sldAudioBalance.getScene().getWindow();
stage.close();
} catch (final IOException ex) {
logger.error("Unable to reset all settings", ex);
FxUtils.showErrorAlert(translationBundle.getString("ResetSettingsError"), ex.toString(), getClass().getResourceAsStream(SharedVariables.ICON_URL));
Expand Down Expand Up @@ -228,9 +232,13 @@ private void saveSettingsAction() {
trayIconController.hideTrayIcon();
}

showAlertIfLanguageMismatch(settingsController.getProperties().getProperty("locale", DEFAULT_LOCALE));
final String languageTag = LanguageController.getLocaleFromLanguageIndex(cboLanguage.getSelectionModel().getSelectedIndex());
final Locale locale = Locale.forLanguageTag(languageTag);
final ResourceBundle translationBundle = ResourceBundle.getBundle("translations.OpalApplication", locale);

mainWindowController.updateResourceBundle(translationBundle);

settingsController.getProperties().setProperty("locale", LanguageController.getLocaleFromLanguageIndex(cboLanguage.getSelectionModel().getSelectedIndex()));
settingsController.getProperties().setProperty("locale", languageTag);

settingsController.getProperties().setProperty("theme", cboTheme.getSelectionModel().getSelectedItem());
settingsController.getProperties().setProperty("loglevel", cboLogLevel.getValue());
Expand Down Expand Up @@ -281,19 +289,6 @@ private void saveSettingsAction() {
}
}

/**
* Show an information alert if a restart is required
*
* @param languageToMatch The language that needs to be matched to the combobox
*/
private void showAlertIfLanguageMismatch(final String languageToMatch) {
final String newLanguage = LanguageController.getLocaleFromLanguageIndex(cboLanguage.getSelectionModel().getSelectedIndex());

if (!languageToMatch.equals(newLanguage)) {
FxUtils.showInformationAlert(translationBundle.getString("RestartRequired"), getClass().getResourceAsStream(SharedVariables.ICON_URL));
}
}

/**
* Method that is invoked when the window should be closed
*
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/com/codedead/opal/controller/TrayIconController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.codedead.opal.controller;

import com.codedead.opal.domain.ObservableResourceFactory;
import com.codedead.opal.interfaces.TrayIconListener;
import javafx.application.Platform;
import org.apache.logging.log4j.LogManager;
Expand All @@ -11,28 +12,27 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.ResourceBundle;

public final class TrayIconController {

private TrayIcon trayIcon;
private final ResourceBundle resourceBundle;
private final ObservableResourceFactory resourceFactory;
private final TrayIconListener trayIconListener;
private final Logger logger;

/**
* Initialize a new TrayIconController
*
* @param resourceBundle The {@link ResourceBundle} object
* @param resourceFactory The {@link ObservableResourceFactory} object
* @param trayIconListener The {@link TrayIconListener} interface
*/
public TrayIconController(final ResourceBundle resourceBundle, final TrayIconListener trayIconListener) {
if (resourceBundle == null)
throw new NullPointerException("ResourceBundle cannot be null!");
public TrayIconController(final ObservableResourceFactory resourceFactory, final TrayIconListener trayIconListener) {
if (resourceFactory == null)
throw new NullPointerException("ResourceFactory cannot be null!");
if (trayIconListener == null)
throw new NullPointerException("TrayIconListener cannot be null!");

this.resourceBundle = resourceBundle;
this.resourceFactory = resourceFactory;
this.trayIconListener = trayIconListener;
this.logger = LogManager.getLogger(TrayIconController.class);
}
Expand All @@ -54,10 +54,10 @@ private void createTrayIcon() throws IOException {
final PopupMenu popup = new PopupMenu();
final BufferedImage trayIconImage = ImageIO.read(Objects.requireNonNull(getClass().getResource("/images/opal.png")));
final TrayIcon localTrayIcon = new TrayIcon(trayIconImage.getScaledInstance(trayIconSize.width, trayIconSize.height, java.awt.Image.SCALE_SMOOTH));
final java.awt.MenuItem displayItem = new java.awt.MenuItem(resourceBundle.getString("Display"));
final java.awt.MenuItem settingsItem = new java.awt.MenuItem(resourceBundle.getString("Settings"));
final java.awt.MenuItem aboutItem = new java.awt.MenuItem(resourceBundle.getString("About"));
final java.awt.MenuItem exitItem = new java.awt.MenuItem(resourceBundle.getString("Exit"));
final java.awt.MenuItem displayItem = new java.awt.MenuItem(resourceFactory.getResources().getString("Display"));
final java.awt.MenuItem settingsItem = new java.awt.MenuItem(resourceFactory.getResources().getString("Settings"));
final java.awt.MenuItem aboutItem = new java.awt.MenuItem(resourceFactory.getResources().getString("About"));
final java.awt.MenuItem exitItem = new java.awt.MenuItem(resourceFactory.getResources().getString("Exit"));

if (trayIconListener != null) {
// Platform.runLater to run on the JavaFX thread
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.codedead.opal.domain;

import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;

import java.util.ResourceBundle;

public final class ObservableResourceFactory {

private final ObjectProperty<ResourceBundle> resources;

/**
* Initialize a new ObservableResourceFactory
*/
public ObservableResourceFactory() {
resources = new SimpleObjectProperty<>();
}

/**
* Get the resources property
*
* @return The resources property
*/
public ObjectProperty<ResourceBundle> resourcesProperty() {
return resources;
}

/**
* Get the resources
*
* @return The resources
*/
public ResourceBundle getResources() {
return resourcesProperty().get();
}

/**
* Set the resources
*
* @param resources The resources
*/
public void setResources(final ResourceBundle resources) {
resourcesProperty().set(resources);
}

/**
* Get a string binding for the given key
*
* @param key The key
* @return The {@link StringBinding} for the given key
*/
public StringBinding getStringBinding(final String key) {
return new StringBinding() {
{
bind(resourcesProperty());
}

@Override
public String computeValue() {
return getResources().getString(key);
}
};
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/codedead/opal/domain/SoundPane.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ public String getName() {
return lblName.getText();
}

/**
* Get the name {@link Label} object
*
* @return The name {@link Label} object
*/
public Label getNameLabel() {
return lblName;
}

/**
* Set the name
*
Expand Down
1 change: 0 additions & 1 deletion src/main/resources/translations/OpalApplication.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Phone
Rain=Rain
Reset=Reset
ResetSettingsError=Unable to reset all settings!
RestartRequired=A restart is required in order to change the language!
Save=Save
SaveSettingsError=Unable to save settings!
SaveSoundPreset=Save sound settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Telefon
Rain=Regen
Reset=Zurücksetzen
ResetSettingsError=Einstellungen konnten nicht zurückgesetzt werden!
RestartRequired=Zur Änderung der Sprache muss das Programm neu gestartet werden!
Save=Speichern
SaveSettingsError=Einstellungen konnten nicht gespeichert werden!
SaveSoundPreset=Toneinstellungen speichern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Phone
Rain=Rain
Reset=Reset
ResetSettingsError=Unable to reset all settings!
RestartRequired=A restart is required in order to change the language!
Save=Save
SaveSettingsError=Unable to save settings!
SaveSoundPreset=Save sound settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Teléfono
Rain=Lluvia
Reset=Restablecer
ResetSettingsError=¡No se pueden restablecer todas las configuraciones!
RestartRequired=¡Es necesario reiniciar para cambiar el idioma!
Save=Guardar
SaveSettingsError=¡No se puede guardar la configuración!
SaveSoundPreset=Guardar configuración de sonido
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Téléphone
Rain=Pluie
Reset=Réinitialiser
ResetSettingsError=Impossible de réinitialiser tous les paramètres!
RestartRequired=Un redémarrage est nécessaire pour changer la langue!
Save=Sauvegarder
SaveSettingsError=Impossible d'enregistrer les paramètres!
SaveSoundPreset=Enregistrer les paramètres sonores
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=फ़ोन
Rain=बारिश
Reset=रीसेट
ResetSettingsError=सभी सेटिंग्स रीसेट करने में असमर्थ!
RestartRequired=भाषा बदलने के लिए पुनः आरंभ करना आवश्यक है!
Save=बचाना
SaveSettingsError=सेटिंग्स सहेजने में असमर्थ!
SaveSoundPreset=ध्वनि सेटिंग सहेजें
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=電話
Rain=雨
Reset=リセット
ResetSettingsError=すべての設定をリセットできません!
RestartRequired=言語を変更するには再起動が必要です!
Save=保存
SaveSettingsError=設定を保存できません!
SaveSoundPreset=サウンド設定を保存
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Telefoon
Rain=Regen
Reset=Reset
ResetSettingsError=Kan de instellingen niet resetten!
RestartRequired=Gelieve de applicatie te herstarten om te taal te wijzigen!
Save=Opslaan
SaveSettingsError=Kan instellingen niet opslaan!
SaveSoundPreset=Sla geluidsinstellingen op
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Телефон
Rain=Дождь
Reset=Перезагрузить
ResetSettingsError=Невозможно сбросить все настройки!
RestartRequired=Для смены языка требуется перезагрузка!
Save=Сохранять
SaveSettingsError=Не удалось сохранить настройки!
SaveSoundPreset=Сохранить настройки звука
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Telefon
Rain=Yağmur
Reset=Sıfırla
ResetSettingsError=Tüm ayarlar sıfırlanamıyor!
RestartRequired=Dili değiştirmek için yeniden başlatma gereklidir!
Save=Kaydetmek
SaveSettingsError=Ayarlar kaydedilemiyor!
SaveSoundPreset=Ses ayarlarını kaydet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=Телефон
Rain=Дощ
Reset=Скинути
ResetSettingsError=Неможливо скинути всі налаштування!
RestartRequired=Щоб змінити мову, потрібен перезапуск!
Save=Збережіть
SaveSettingsError=Не вдалося зберегти налаштування!
SaveSoundPreset=Зберегти налаштування звуку
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Phone=电话
Rain=雨
Reset=重置
ResetSettingsError=无法重置所有设置!
RestartRequired=需要重新启动才能更改语言!
Save=节省
SaveSettingsError=无法保存设置!
SaveSoundPreset=保存声音设置
Expand Down
Loading

0 comments on commit 99c3822

Please sign in to comment.