How do I avoid (some) of my string resources getting localized?
Sometimes I need the same string multiple places. For instance when defining a preference I need the preference key both in my preferences.xml and in my java code in order to get the preference value. Either I can manually define the key twice (which I do now) but I feel that my list of keys is getting large and error prone.
I could also define the key in my strins.xml but then I fear it will get translated (sooner or later (by mistake?)). I fear this could cause problems to have the same preference value store multiple times with different keys. What if the user changes language and all the settings got reset?
Is there a way to define a string - accessible both in code and xml - which will not get translated as a part of the localization process?
In general, if you provide the string only in your default strings.xml it will appear the same on all locales. In addition you can use the "translatable" attribute which will tell Lint that this string is not designed to be translated, and will serve for documentation purposes.
Just use translatable=false. And I suggest putting your preferences keys to separate resource file as it would be easier to manage.
<string name="Key" translatable="false">my key</string>
Related
I have heard that using editor.putString("Message","Hello"); is bad practice, and you should instead do editor.putString(getString(R.string.messagestring),"Hello");. But why? It is longer and has the same result, and looks more messy imo. Is it because it's harder to make a typo?
Here is an example from Signal:
Source
if (params[0] < SCREENSHOTS) {
boolean screenSecurity = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(TextSecurePreferences.SCREEN_SECURITY_PREF, true);
TextSecurePreferences.setScreenSecurityEnabled(getApplicationContext(), screenSecurity);
}
String values in code for human readable text are bad.
Doing so makes localization impossible.
Values from R.string. on the other hand automagically use the right language (given that you use values, values-es, values-fr, ... and put translations)
Note: You should probably not translate the key of a SharedPreference but the value ("Hello") part since that's presumably the human readable thing.
editor.putString("message", getString(R.string.messagestring));
The key could change if the user changes device language which means the old stored value will no longer be found under the new key. If you want keys in a central place it's a good idea to have them defined as static final constants in code.
editor.putString(MyPrefConstants.PREF_MESSAGE, getString(R.string.messagestring));
I would actually consider using keys that come from R.string a very questionable design decision. This applies to anything that is intended to be machine-consumed rather than visible text to the user. There are a few exceptions but they are rare.
It's Not Necessary but Good Practice.
eg.
editor.putString("Message","Hello");
here the key -> "Message"
it is possible that sometimes you make a TYPING ERROR or SPELLING MISTAKE of writing "Message" to "Massage" or something else.
to avoid these type of situations, we should write in this way
editor.putString(getString(R.string.messagestring),"Hello");
It's all about maintenance, reusability, cleanness and if needed easier localization. Take for example "Message".
How many times would you use this string in your code if it is the key for Preferences? More than 1, right? Imagine that you write over and over "Message". Isn't it possible to misspell it at least once? Well you can't misspell a string resource, because the compiler won't let you.
Another thing: you know where all your UI strings are so you know where to look when you need to change 1 of them and once you do it is changed throughout the app.
Finally if you want your up to be multilingual this is the only way with the Editor provided by AS.
Edit: As for the question if strings like keys for Preferences should be in the Resources my answer is yes. It's up to the programmer to give proper ids to the string resources so to distinguish the UI items from the in-app items.
I'm wondering what the drawbacks are for using strings that are defined in the java files in Android code.
I like to use plain old Java strings for things that are not visible strings like e.g. names in XML documents that I'm parsing, or keys for bundles. Seems to be a good idea to just keep all those things in the java file where they are used instead of moving them out into an XML file and making the code more complicated.
Yet, I see many examples of Android code that seem to put every string into a resource file.
What's the issue with having strings in java files? What are the reasons that people don't do it? I've been doing it in my apps and haven't seen any issues yet so far.
Note that I'm aware that XML files make a ton of sense for stuff that needs to be translated. This question is for cases where the strings stay the same.
Let me try to make this question clearer:
Are there any reasons except:
Because it's a standard / best practise etc. - my question is basically: why is it a best practise, only because of i8n, or are there other reasons?
Because it allows you to use the resources framework for translation, device-dependent strings etc.
Because it allows you to use non-ASCII characters.
The simple answer to your question is its a standard to put all your string into resource. Also there are many reason that if you are keeping your string in xml/java file you have to update each and every reference in these file for a single string.
for eg. if You want to change "Ok" to "confirm" which are used in 5 different file you have to change in all those 5 files but for String resource you just have to update one file which string.xml.
Edit
Please find below some of reasons we should use String.xml
1) To update single reference to multiple occurrences. As according to the #treesAreEverywhere It can be done with public static String, but it will take memory on startup of application and till application is closed. But String written in String.xml will be loaded at time of use.
2) Multiple language support. You can create multiple language resource folder to support your multiple language application so language changed using Locale will be dynamically maintained by OS at run time according to language resource folder.
3) Please check Localization document which provide you more information about using string.xml
4) Strings don’t clutter up your application code, leaving it clear and easy to maintain.
It's a kind of coding standard like any other language has. But you can ignore it if you want and can create your code with public static string variable in code. It is not compulsory to use string.xml but its a good coding practice to use it. Good practice like closing the if block with parenthesis containing single statement rather than leaving it as it is.
if(condition){ statement; } rather than if(condition) statement;
Actually, good practices is a good reason to do it, but there are more.
For example, one reason that I can recall right now is that strings.xml is UTF-8 codified. Hardcoded strings doesn't show some characters properly.
The purpose of strings.xml (and other *.xml resource files) is to regroup similar values in one place. This facilitates finding values that would be otherwise buried in the code. Those resource files also makes the maintainability better, since a modification to one value can have app-wide effects (such as changing the title of the app or the theme). Finally, as you mentioned, it provides a framework for translating your app to other languages.
If you know your app will not be translated and won't be modified, it's not a bad thing to hard-code them. However, if you think your app will get a lot of updates, it is better to start using good foundations and use XML resource files.
Besides these reasons and the ones mentioned by #Zinc (which I am unaware of and cannot confirm), there are no other reasons regarding why you would want to use XML resource files.
The drawback of using resource files is that is is theoretically is slower and requires a bit more memory. Read android - strings.xml vs static constants and Does hard coding of string affect performance?
If you put all your strings which are related to your application, then you can implement I18N kind of applications very easily and it is very useful while doing application changes (Company takeover some other company). It is just change names in xml files. No need to touch any java file.
I have a Java Desktop App, the users of the application have the availability to set the aplications language.
By now i manage it in the database, i call the value of a field called - userLanguage - which is an Integer, and when the user has logged in depending on this value i set the corresponding text to each element on the app by using a switch ( case 1: set labels text ENGLISH, case 2: set labels text SPANISH ... etc)
But i've heard that control the language from the database is an insult, and i would like to know which's a nice way to do it, or what's the best way to do so, it doesn't matter how difficult it would be but the efficence of the method to internationallize an app is what metters for me.
I would actually handle this problem using the Java Preferences. It keeps the preferences for each user separately in a system independent way (for you at least). If you use XML you need to create a SAX/DOM parser or if you use a DB you need to use jdbc. Neither XML or the DB is a bad or a tough solution, I just think the preferences are the easiest.
For internationalization, I would use a ResourceBundle that localized for different Locales. It is a pretty big topic see The Java internationalization (I18n) tutorial
Java Preferences is what you are looking for then.
Or, instead of using XML file you can use Properties.
...i've heard that control the language from the database is an insult...
I do not agree with that. I think it is scenario dependent, and in your case I think you should keep it the way it is to avoid unnecessary work, unless there is an absolute need for keeping the preferred idiom outside your DB.
You've received two answers, both of which are plainly wrong. If you have Java Desktop Application, you should this code:
Locale locale = Locale.getDefault(Locale.Category.DISPLAY);
This will give you valid User Interface language for your application - the one user set in his OS preferences. If you want to keep the language in a database or in some kind of preferences, you'll be forcing users to chose language. What for? I've already set what language I want. If you don't have it, let Java fall back to your application's default.
In case you wonder, if you use ResourceBundle, the default would be the one without a Locale in its name. That is unless you override this process by using custom ResourceBundle.Control.
I've taken a look at the following post to grasp a basic idea of how to deal with I18N:
Where to place i18n key strings in Java
But more than that, I have an intention of automatically generating a Java class with constants storing key strings of I18n property files. I know it could be feasibly done using Java itself, however, I wonder which is the best approach (using Ant, Batch or something else...)?
The best approach is to give the identifiers yourself.
The ID can give hint to the translator what the string is about.
In fact, some consistency in naming convention is best:
dialog.print.title = Print
menu.file.print = Print
The two entries have to be translated differently in some languages (for instance in French it would be "Imprimer" for a button and "Impression" for a label / title).
Think it it this way: would you like to maintain some code where all variable names are machine generated?
I have a String is like String data="apps";
i know loading String in Android in two ways..
First one is
so it is a constant i defined it as
public static final String data="apps";
And another type is defing it in res/vslues/strings.xml file like..
<string name="data">apps</string>
<string name="hello_world">Hello world!</string>
if i want to use it..
for the first way ClassName.data
for second way context.getResources().getString(resourceid)
Question:
so now my question is I want to use same String in 30 times in different classes.And I have more number of variables.so which will load faster and take lesser memory in the above methods..
However, speed shouldn't really be an issue in either case. I would recommend organizing based on what makes sense.
Constants class
Put strings constants that will be used internally, like database column names or other keys.
strings.xml
Put strings that are displayed for the user. This way you can take advantage of localization, etc.
As per requirement you should be prefer second approach means XML
based.
The XML string values are meant to be display strings that can be overridden based on locale. This way you can refer to a translatable display value by a constant key.
You should consider using XML strings as a way to display something to the user and change it depending on locale.
Never the less, public static final String data="apps"; should be used in order to hide some not-for-user data like db connections, log messages etc.
I'd suggest that you leverage the Android resource system.
To quote the book Android In Practice:
Resources in Android are efficient and fast. XML resources are compiled into a binary format. This makes them friendly at development time, without being slow at Runtime.
I think the speed and memory usage would be the same. The constant in a class is just like a constant in the string.xml which is stored once and referenced whenever you need it elsewhere.
However, the advantage of storing in string.xml over the other would be the extra import lines of code which would be avoided. Meanwhile, you have to remember that with string.xml storage you can only use it where the context of an activity is accessible.