-
Notifications
You must be signed in to change notification settings - Fork 13
For developers
I would like to use this space to 'brag' about some of the things I created in this project and I think may be useful for others. I think I figured out interesting solutions for a few things. I do not say my implementation is the best, just that I think the idea is good.
If you are writing a program that you want to support multiple languages you quickly realize that placing if statements around all string the user will see is to much work, here is a snippet from one of the first programs I wrote (its in VisualBasic):
If My.Settings.PåSvenska = True Then generera_tal.Text = "Tryck igen för att genererar ett nytt tal" Else generera_tal.Text = "Click again to generate a new number"
Java have something called resource bundles that can help you, in the beginning you load the bundle for the users language and then you just get the strings from it:
welcomeLabel.setText(bundle.getString("welcome"));
usernameLabel.setText(bundle.getString("enterUsername"));
passwordLabel.setText(bundle.getString("enterPassword"));
logInButton.setText(bundle.getString("loginBtn"));
// etc.
Doing like this its easier to manage but writing this for all nodes in a complex window? Too many lines and it just looks ugly. What if you could translate a whole Java FX window in one line of code?
translation.autoTranslate(mainWindowPane);
My translation system does this. By assuming that the translation keys in the resource bundle have the same name as the node it is related to it is able to automate the translation for you. My translation class first recursively finds all the children to the given node and then iterates over all translation keys. But there is more, I also added some extra features to this! Lets say we have a Node called logInButton and we create a translation with the key logInButton_tt the translator will find that it ends with _tt and that it exists a node called logInButton, so it attempts to attach a ToolTip to logInButton with the text in the translation key logInButton_tt. Similarly if a translation key ends with _pt it will attempt to attach a prompt text to the node. Here is a very simple example, look at the javaDoc and code for more details on how it works and how to use:
// ResourceBundle "loginWindow.properties"
txtField_username_pt = "Username"
txtField_username_tt = "Enter Your username"
logInButton = "Log in"
logInButton_tt = "Click here to log in"
// Controller class
public TextField txtField_username;
public Button logInButton;
public Pane loginWindowPane;
//Controller class (init method)
Translations myTranslations = new Translations("loginWindow");
myTranslations.autoTranslate(loginWindowPane);
The presets and uploads in the program have a set of buttons and when one of them is clicked all of them may need to be changed. initially I created buttons where I needed them and replaced the old once, but it took to many lines of code:
// Change buttons
Button editButton = new Button(transBasic.getString("edit"));
editButton.setId(parentId + BUTTON_EDIT);
editButton.setOnMouseClicked(event -> onEdit(editButton.getId()));
Button deleteButton = new Button(transBasic.getString("delete"));
deleteButton.setId(parentId + BUTTON_DELETE);
deleteButton.setOnMouseClicked(event -> onDelete(deleteButton.getId()));
Button startUploadButton = new Button(transBasic.getString("startUpload"));
startUploadButton.setId(parentId + BUTTON_START_UPLOAD);
startUploadButton.setOnMouseClicked(event -> onStartUpload(startUploadButton.getId()));
uploadQueueVideos.get(selected).setButton1(editButton);
uploadQueueVideos.get(selected).setButton2(deleteButton);
uploadQueueVideos.get(selected).setButton3(startUploadButton);
This way I also have to change the code in multiple places if I wanted to change the edit button for example. This way the edit button is set in the cancel button's method, the save button's method and in the method that adds a new upload. If I could define a set of buttons to use in specific cases and then set them all at the same time it would make section like this not needed, I would only need to modify code in one place. But I would need to set it up somewhere:
buttonStates = new VideoUploadState();
// Define Locked from editing
buttonStates.defineLocked(new ButtonProperties[]{
new ButtonProperties(BUTTON_EDIT, transBasic.getString("edit"), this::onEdit),
new ButtonProperties(BUTTON_DELETE, transBasic.getString("delete"), this::onDelete),
new ButtonProperties(BUTTON_START_UPLOAD, transBasic.getString("startUpload"), this::onStartUpload)
});
// ... the other states ...
But now it look like this:
buttonStates.setLocked(uploadQueueVideos.get(selected));