How to change language in-game with I18NBundle in libGDX? - java

I've created a I18NBundle and some .properties files containing the strings. To create the bundle i wrote this:
baseFileHandle = Gdx.files.internal("Language/Lang");
da_DK = new Locale("da", "DK");
en_GB = new Locale("en", "GB");
Lang = I18NBundle.createBundle(baseFileHandle, en_GB);
This works perfectly well, and I can extract the values from the bundle to get my strings, and it also works by using da_DK instead of en_GB when i initialize the bundle.
My proplem is that I want to be able to change the language in game by pressing a button, but I have no idea how to do that.
I've googled the problem, but cant seem to find an answer.
I hope that you understood my problem, and that you can help me :)

If you have a look at the code (I18NBundle.setLocale(...), which is a private method) you will see this JavaDoc:
Sets the bundle locale. This method is private because a bundle can't change the locale during its life.
That means, what you want to do is not possible. What you can do of course, is creating a new I18NBundle supplying another Locale to the constructor and basically just replacing the current one. In case you are using an AssetManager to load it, this is also possible, you would just need to unload it and then load it once more with different parameters.

Related

How to make a JFileChooser with a different language?

I want to know how I can make a JFileChooser in the Swedish language.
Unfortunately it turns out that if I could use a JDK version 10 or earlier i could actually do this by creating a Locale object and make it the default.
But we are discouraged to use this old version for any new programs.
But from JDK version 11 and forward choosing Swedish Locale no longer works.
So I have seen that people have been able to change individual strings for the FileChooser like in this example:
https://coderanch.com/t/475470/java/customizing-JFIleChooser
But this feels unsatisfactory to me.
At least for as long as I do not know how I can learn about how I can find those Strings and where they are located.
Maybe I will run into the same problem again with some other GUI component and then I still don't know what to do.
This works with JDK v. 10 or earlier:
//This is in my Main:
Locale sverje = new Locale("sv", "SE"); //Creates a instance of Locale for Swedish, Sweden.
Locale.setDefault(sverje); //Sets this to default.
//Then I call a class that opens a Frame and handles the FileChooser.
This is an example of modifying an individual string:
UIManager.put("FileChooser.cancelButtonText", "Cancelar"); //Changing cancel button text to Portugese
If I need to use this method it would be nice to know how to find the strings like I said before.
It would also be nice to know what is going on when you "put" in the new String value like in the example.
I believe that the JFileChooser somehow inherits the Strings in several steps, and that is what allows us to write "FileChooser.cancelButtonText" even if there actually is no "cancelButtonText" in the FileChooser class, rather (I'm guessing!) it inherits it from a so called ResourceBundle and then from there to the Localeclass and from there to some other class or classes before the FileChooser uses it.
So is this a correct assumption and how can you trace the Key / name / location of those strings from the FileChooser class to where the actually are?
Is it the ResourceBundle or the FileChooser or some other part that was changed since it stopped working from version 11?
Can / should I try to make changes to the ResourceBundle to fix this in the most professional way?
You can find the full list (including FileChooser keys) in the first answer of this post: List of Java Swing UI properties?
I think it will be enough setting only the properties ending in "Text".
AFAIK UIManager.put is just updating UIDefaults (the map that contains all the default names) so, as long as there is just one language available in the application, there is no need to use a ResourceBundle.
So correct me if I am wrong.
But I think the answer is something like this:
If you want to use one of the languages that is supported for the Swing Component just set the correct Locale and you are done.
If not it seems like using UIManager.put is the best way to go.
I was hoping to find a resource bundle containing all of the text strings but now I do no longer think that such a thing exists.
So my understanding at the moment is this:
The JComponents such as the FileChooser are generalized Components that are meant to work on many different platforms and operative systems.
And they use classes called "Look & Feel" to get their final form depending on the intended Platform.
This is where the UIManager comes in.
It allows you to decide what "Look & Feel" you want to use.
So in my case it will use a look and feel called:
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel".
You can get this information using:
System.out.println(UIManager.getSystemLookAndFeelClassName());
And I believe that the UIManager will create classes called UIDefaults using some algorithm.
The UIDefaults will contain the values that gives the JComponents their "Look & Feel" i.e. their appearance & behaviour.
But the UIDefaults classes are not pre-existing.
They are created based on setup.
However I believe that they will get some of their data from a resource file that is not truly a ResourceBundle but at least extends the ResourceBundle class.
But this still does not contain all the necessary Strings to fully customize the FileChooser.
This link shows an example of these resource files that are specific to the Windows version (L&F) of the FileChooser:
https://code.yawk.at/java/6/com/sun/java/swing/plaf/windows/resources/
So the data is apparently split up and it does not come from a single source.
It is collected from different sources and put into the UIDefaults class that works like a Database for the values.
To sum it all up.
The best way to go might be to create a class that has a method to put all the String values into the UIDefaults using the UIManager.
And I suppose you could prepare for internationalization by letting this method get it's strings from a resource bundle that you have created yourself.
The best list of Keys seems to be this one:
https://thebadprogrammer.com/swing-uimanager-keys/
But unfortunately although seemingly exhausting there is still information missing.
To fully customize all the Strings in the FileChooser in addition to the Keys you will find in this list you will also need to change the value of this Key:
"saveInLabelText".
So these are all the String I changed and I believe they will customize most of the Strings for the Windows version of the FileChooser:
//Strings for Open file-dialogue: ***************************************************************************
//The numbers in the comments refers to the order of appearance of the Stirng values in the Frame
UIManager.put("FileChooser.openDialogTitleText","Open"); //1.
UIManager.put("FileChooser.lookInLabelText","Look in:"); //2.
UIManager.put("FileChooser.fileNameLabelText","File name:"); //3.
UIManager.put("FileChooser.filesOfTypeLabelText","Files of type:"); //4.
UIManager.put("FileChooser.openButtonText","Open"); //5.
UIManager.put("FileChooser.cancelButtonText", "Cancel"); //6.
UIManager.put("FileChooser.acceptAllFileFilterText","All Files"); //7.
//End of Open file-dialogue ***************************************************************************
//Strings for Save file-dialogue ***************************************************************************
UIManager.put("FileChooser.saveDialogTitleText","Save as"); //1.
UIManager.put("FileChooser.saveInLabelText","Save in:"); //2. This was not in the list but works!
// The strings with number 3 & 4 are the same as the ones for the Open file-dialogue so you do not need to set them here.
UIManager.put("FileChooser.saveButtonText","Save"); //5.

How to set a value programatically from resources string?

Lets say we have something like this in strings.xml:
<string name=“hello”>Hello world</string>
Now I want to set a value to a TextView using this string. Should I do it in java class like this:
TextView msgTextView = (TextView) findViewById(R.id.msg);
msgTextView.setText(R.string.hello);
or in xml file like below?
android:text="#string/hello"
Which approach is better? Or when it is better to use the first way and when the second one?
You should do neither. There is relatively new approach , called databinding (it was demo in 2015) and now this library is officially supported by Google. It is a manifestation of MVVM pattern and you should use it, because it limplifies your code and makes it more maintainable in long term. See https://developer.android.com/topic/libraries/data-binding/index.html . In few words- you create Java class with fields and accessirs and set its fields as xml attributes. By doing so, AndroidStudio will generate all .findViewbyId() boilerplate for you. you just create model and set it to that particular binding.
Regarding performance, it won't make any difference. I personally prefer to do it in XML, since it doesn't clutter your activity code.
Both approach is correct. If you want to internationalize your variable that time (change languages) both will be work. In reference of memory or speed dynamically change is correct(means using getResource() or R.string.hello).
at first you should set it in xml.(or leave it empty.) but if you want to change it when something else happens (for example when user click a button or anything else.) you should set it in java.
First method is generally used when you want your textview to be fixed and final .
Second method is recommended as the textview's value may change during the course of operation of app .Initially in second method , a value is shown by textview which shows its purpose or type . For e.g second one may be used in displaying progress of background task .

How to retrieve the string id you defined (not integer id) in AndroidStudio, and Object Tags

I'm new to Android development and I'm trying to make a calculator app in AndroidStudio. Originally, I used Buttons, and to retrieve the number of a button pressed, the function btn.getText() worked perfectly. I've since replaced the Buttons with ImageButtons, with the number now represented in the image.
My plan was to give all ImageButtons ids in the vein of 'btn0', 'btn1', and so on, then do something like
Character number = imgbtn.getId().charAt(imgbtn.length()-1);. This, however, fails miserably, as the id is apparently an automatically assigned int, and not the id I set.
Is there a way to access the string id property that I defined?
Alternatively, I saw mention of a getTag() function in my prior googling for solutions that looks like it might be useful in this situation, but I can't find an ImageButton tag property where I can set it.
Solved my specific issue: I just discovered that I can set the tag in the Text view, by adding android:tag="x" to the relevant ImageButtons (or that I could call imgbtn.setTag() to the same effect). I'm going to submit this anyway, in case someone has a similar issue in the future.
Lingering Questions
My question about accessing one's defined string id still stands. Is there a way to do that, in case I'd ever like to?
Also, what's an Object Tag, such as it would be used in imgbtn.setTag(<Object tag>)? I can't find any documentation.
At compile time, all resources are compiled in to a class called R.Java. When you say findViewById(R.id.xxx) what you are actually doing is pointing to a static reference of a final integer called "xxx" that has been hardcoded into this Java file. If you'd like to view this, navigate to the build directory after you've built your project and go to generated, source, debug (or release) then through your project until you see R.java
In other words, the String of the id is not present at runtime.

How To Set Default Language for Android app?

I've created an app in two languages. The second one (english), is used when user's default system language is english. If it's not, then the first one is used.
I want to set the second language (that's english) as a DEFAULT language,
which means that when user opens my app and his system language is not the first one, nor English, the English language will appear as a default one.
I tried:
Locale locale = new Locale("en_US");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext.getResources().updateConfiguration(config, null);
But got "context cannot be resolved" error everytime.. Is this piece of code right or..?
Okay,
to make everything clear,
I realized res/values is a DEFAULT directory and the others are just "in case of language". So everything I had to do was to switch the english to /res/values and the other language goes to res/values-es
You should define all languages you support using res folders, i.e res/values, res/values-en, res/values-fr. The system will take care of everything else, you don't need any code.
If you are in an activity you can do:
this.getApplicationContext().getResources().updateConfiguration(config, null);
...to fix your error.
Otherwise you need to pass in the context.
Make sure you add the parenthesis at the end of getApplicationContext(). You didn't do so in your code.
I've been in the same situation, my app was first created in portuguese (BR) so we went global and I had as second language En-Us, so my solution was creating a new language ( clicking in translation Editor + Brazil )... so I have my default language (Portuguese) second (English) third (Portuguese)
then I replaced the resource/ values to the english strings setting as default...

Displaying non-English strings in Android

My app is English only but some of the data that I am dynamically retrieving and displaying is from a different language (Eg: Korean). I am doing this before adding the string item to a list view:
test = new String(item.name.getBytes("UTF-8"));
When I use the Eclipse debugger to check the test string, I am able to view the string with the appropriate language characters but when I display the listview on the emulator, it turns into garbage.
I've read that Android automatically supports languages like Japanese, Telugu etc so I am assuming that I am doing something wrong here. Can anyone help? Thanks!
Why the hell are you doing this? You have a string, encode it in UTF-8 and THEN decode it with the platforms default encoding - this obviously will fail if the default encoding is anything but UTF-8.
Obvious fix: test = item.name.
Also correct but rather useless: test = new String(item.name.getBytes("UTF-8"), "UTF-8");

Categories

Resources