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?
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've got a simple string coming in from a UI component as The device id is %{test}. Assume %{test} is a dynamic variable and the values for it are being assigned from the backend code. The final string should look like:
The device id is some text
----------------------------^ should be replaced with %{test} and appended to the whole string
I've read a bit and tried out some of the libraries which were pointed out here, such as Velocity and FreeMarker. But I'm quite unaware in terms of efficiency and performance on using those libraries.
Hope I could get some insights on this since I'm pretty new to this. Any help could be appreciated.
I suggest you to take a look at Arco Template Engine: It compiles the template in compile-time, producing a .java (or .class) file. And so, at run-time, the expansion is done very fast.
The templates should be coded in JSP format. Thus, all variables references must be written ${variable} (not %{variable}).
The only thing to take in account is that templates must be staticly generated (in order to be processed at compile-time).
(Read the FAQ and the examples).
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.
Ok, so coming from a background of mostly perl, and mostly writing dirty little apps to automate my tasks, I've read the pages about the evils of eval(), and I always use a hash (in perl). I'm currently working on a little project (mostly for me and a couple of other technical people at work), for creating "canned response" e-mails. To allow for additions, subtractions, edits, etc., I'd like to essentially describe the response form(s) in XML, and have my app parse the XML and create the response forms at runtime. I want to use Java (to integrate it into an existing Java tool that I created), and boiled down to a trivial example, what I'm trying to do is take some XML like:
<Form Name="first" Title="Title!">
<Label Name="before">Your Request:</Label>
<Textbox Name="input"/>
<Label Name="after">has been completed.</Label>
<Output>%before%%input%%after%</Output>
</Form>
<Form Name="second">
...
and from parsing that, I want to create a JFrame named first, which contains a JLabel named before with the obvious text, then a textbox, then another JLabel... you get the idea (I eventually want to use the output tag to control exactly how the response is formatted).
I can parse the XML, and get the element name and such, but I don't know how to instantiate the Objects with a name that is the value of a variable, effectively:
JFrame $(thisNode.getAttributes().getNamedItem("Name").getNodeValue()) = new JFrame(thisNode.getAttributes().getNamedItem("Title").getNodeValue());
I've read basically the whole first page of google results on java reflection, but I haven't come across anyone doing quite what I'm looking for (at least not that I could tell). Having basically zero experience with reflection, I'm curious if this is something that can be accomplished using it, or if I should take the same approach as I would in Perl, and create a HashMap or HashTable of Objects, and tie them to a entry in a Hash of JFrames. Or, I'm open to ideas that don't fall into those two categories. The Hash is sort of my stand-by answer, because I've done it in Perl plenty of times, and I'm sure I can make it work in Java, but if there's a feature (like reflection) that's made to do this task, then why not do it the way it was intended to be done?
What you're asking isn't possible in Java. It doesn't work that way and these sorts of tricks, which are common in dynamic languages, aren't the Java way. You can certainly do:
JFrame frame = JFrameBuilder.buildFromTemplate("frame.xml");
where you create a JFrameBuilder class that reads the XML and creates an object from it but the variable name can't be dynamic. You have to remember that there are two steps in Java.
Java source files are compiled into bytecode;
The bytecode is read by a Java interpreter (JVM) and executed.
What you want is essentially asking to execute code in step (1). Now annotations can do things in a compile step (like adding interfaces, implementing methods and so on) but local variable naming is not one of those things.
You could (not necessarily that you should) generate Java source based on your XML, compile the generated code, and finally, execute the compiled code. This could be more efficient if you saved the generated .class files and reused them instead of parsing the XML every time the program is run (it can check the timestamp on the XML and only generate and compile if it's been modified since the last code generation).
Using Java, I need to encode a Map<String, String> of name value pairs to store into a String, and be able to decode it again. These will be stored in a database column, and will probably usually be short and simple, so the common case should produce a simple nice looking line, but shouldn't corrupt the data, even if it contains unexpected characters, etc.
How would you choose to do it such that:
The encoded form is a single, human readable line
It doesn't require a big library or much context to encode / decode
Any delimeters are properly escaped
Url encoding? JSON? Do it yourself? Please specify any helper libraries or methods you'd use.
(Edited to specify more context and requirements as requested.)
As #Uri says, additional context would be good. I think your primary concerns are less about the particular encoding scheme, as rolling your own for most encodings is pretty easy for a simple Map<String, String>.
An interesting question is: what will this intermediate string encoding be used for?
if it's purely internal, an ad-hoc format is fine eg simple concatenation:
key1|value1|key2|value2
if humans night read it, a format like Ruby's map declaration is nice:
{ first_key => first_value,
second_key => second_value }
if the encoding is to send a serialised map over the wire to another application, the XML suggestion makes a lot of sense as it's standard-ish and reasonably self-documenting, at the cost of XML's verbosity.
<map>
<entry key='foo' value='bar'/>
<entry key='this' value='that'/>
</map>
if the map is going to be flushed to file and read back later by another Java application, #Cletus' suggestion of the Properties class is a good one, and has the additional benefit of being easy to open and inspect by human beings.
Edit: you've added the information that this is to store in a database column - is there a reason to use a single column, rather than three columns like so:
CREATE TABLE StringMaps
(
map_id NUMBER NOT NULL, -- ditch this if you only store one map...
key VARCHAR2 NOT NULL,
value VARCHAR2
);
As well as letting you store more semantically meaningful data, this moves the encoding/decoding into your data access layer more formally, and allows other database readers to easily see the data without having to understand any custom encoding scheme you might use. You can also easily query by key or value if you want to.
Edit again: you've said that it really does need to fit into a single column, in which case I'd either:
use the first pipe-separated encoding (or whatever exotic character you like, maybe some unprintable-in-English unicode character). Simplest thing that works. Or...
if you're using a database like Oracle that recognises XML as a real type (and so can give you XPath evaluations against it and so on) and need to be able to read the data well from the database layer, go with XML. Writing XML parsers for decoding is never fun, but shouldn't be too painful with such a simple schema.
Even if your database doesn't support XML natively, you can just throw it into any old character-like column-type...
Why not just use the Properties class? That does exactly what you want.
I have been contemplating a similar need of choosing a common representation for the conversations (transport content) between my clients and servers via a facade pattern. I want a representation that is standardized, human-readable (brief), robust, fast. I want it to be lightweight to implement and run, easy to test, and easy to "wrap". Note that I have already eliminated XML by my definition, and by explicit intent.
By "wrap", I mean that I want to support other transport content representations such as XML, SOAP, possibly Java properties or Windows INI formats, comma-separated values (CSV) and that ilk, Google protocol buffers, custom binary formats, proprietary binary formats like Microsoft Excel workbooks, and whatever else may come along. I would implement these secondary representations using wrappers/decorators around the primary facade. Each of these secondary representations is desirable, especially to integrate with other systems in certain circumstances, but none of them is desirable as a primary representation due to various shortcomings (failure to meet one or more of my criteria listed above).
Therefore, so far, I am opting for the JSON format as my primary transport content representation. I intend to explore that option in detail in the near future.
Only in cases of extreme performance considerations would I skip translating the underlying conventional format. The advantages of a clean design include good performance (no wasted effort, ease of maintainability) for which a decent hardware selection should be the only necessary complement. When performance needs become extreme (e.g., processing forty thousand incoming data files totaling forty million transactions per day), then EVERYTHING has to be revisited anyway.
As a developer, DBA, architect, and more, I have built systems of practically every size and description. I am confident in my selection of criteria, and eagerly await confirmation of its suitability. Indeed, I hope to publish an implementation as open-source (but don't hold your breath quite yet).
Note that this design discussion ignores the transport medium (HTTP, SMTP, RMI, .Net Remoting, etc.), which is intentional. I find that it is much more effective to treat the transport medium and the transport content as completely separate design considerations, from each other and from the system in question. Indeed, my intent is to make these practically "pluggable".
Therefore, I encourage you to strongly consider JSON. Best wishes.
Some additional context for the question would help.
If you're going to be encoding and decoding at the entire-map granularity, why not just use XML?
As #DanVinton says, if you need this in internal use (I mean "
internal use
as
it's used only by my components, not components written by others
you can concate key and value.
I prefer use different separator between key and key and key and value:
Instead of
key1+SEPARATOR+value1+SEPARATOR+key2 etc
I code
key1+SEPARATOR_KEY_AND_VALUE+value1+SEPARATOR_KEY(n)_AND_KEY(N+1)+key2 etc
if you must debug, this way is clearer (by design too)
Check out the apache commons configuration package. This will allow you to read/save a file as XML or properties format. It also gives you an option of automatically saving the property changes to a file.
Apache Configuration
A realise this is an old "deadish" thread, but I've got a solution not posited previously which I think is worth throwing in the ring.
We store "arbitrary" attributes (i.e. created by the user at runtime) of geographic features in a single CLOB column in the DB in the standard XML attributes format. That is:
name="value" name="value" name="value"
To create an XML element you just "wrap up" the attributes in an xml element. That is:
String xmlString += "<arbitraryAttributes" + arbitraryAttributesString + " />"
"Serialising" a Properties instance to an xml-attributes-string is a no-brainer... it's like ten lines of code. We're lucky in that we can impose on the users the rule that all attribute names must be valid xml-element-names; and we xml-escape (i.e. "e; etc) each "value" to avoid problems from double-quotes and whatever in the value strings.
It's effective, flexible, fast (enough) and simple.
Now, having said all that... if we had the time again, we'd just totally divorce ourselves from the whole "metadata problem" by storing the complete unadulterated uninterpreted metadata xml-document in a CLOB and use one of the open-source metadata editors to handle the whole mess.
Cheers. Keith.