When working on the Android platform, you often come across the need to fill in strings.xml string constants. Everything would be nothing, but the rules that Android imposes on the contents of these files are very limited. Some of them are obvious, for example, the apostrophe sign must be escaped with a slash, while others are related to both the XML format device and Android features. About these features and will be discussed in the article below.
So, let's say we have a set of strings received from the customer as a text file or iOS PLIST or even an Excel document. In my case, these were the lines imported into the project from PhraseApp. The name fields are automatically filled in based on the names given by the developer of the locales and the PhraseApp rule set. It is worth noting that for other platforms, on which there are not so many restrictions, export occurs successfully, which significantly speeds up the development and localization in a multiplatform environment. Unfortunately, looking for errors in strings using AndroidStudio is still inconvenient as many versions ago, the studio simply does not show the number of erroneous strings in XML, so Eclipse can still help a tired developer. So, let's take a closer look at the pitfalls.
Spaces in names
<string name="confirm exit">Are you sure?</string>
space between confirm and exit is not allowed, replace it with an underscore
')
<string name="confirm_exit">Are you sure?</string>
Dots in names
In general, dots in names are valid, the environment will gladly accept the option
<string name="gender.male">Male</string>
but the devil, as you know, is in the details, having tried to assemble an array of strings or plurals with a dot in the name, we get an error like
Error retrieved parent for item: no. <string-array name="age.array"> <item>0-13</item> <item>14-18</item> <item>19-21</item> <item>22+</item> </string-array>
for all string-array and plurals, change the point in the names to the same underscore
<string-array name="age_array">
Java keywords in names
This is not entirely obvious, but you cannot use Java keywords in names. The next line will not allow the project to assemble.
<string name="else">Else</string>
The only way out is to provide the else with an underscore at the beginning of _else and the project will be assembled again.
Formatted output
Formatting output makes it much easier to read the source code, but here too we face problems. Let's output two and more values ​​with substitution in one line at the same time, for example, the time from and to. We get an error
Multiple substitutions specified in non-positional format; Did you mean to add the formatted = "false" attribute? <string name="time_to_time">Time from %s to %s</string>
adding the attribute formatted = “false” corrects the situation, but we still have plurals and a string-array, complicate the example and try to build
<plurals name="api_arror"> <item quantity="one">Error %s occured</item> <item quantity="other">%s errors ocurreds in %s</item> </plurals>
we get two errors at once
Multiple substitutions specified in non-positional format; Did you mean to add the formatted = "false" attribute?
Found tag </ item> where </ plurals> is expected "attribute?Adding the attribute formatted = “false” does not fix anything, but Google suggests that the parameters must be set with their sequence numbers, so that the system understands what and where to substitute. The principle is simple, the parameters are numbered starting from one and use the dollar sign. For the first parameter, the replacement will be% 1 $ s - for the second% 2 $ s, for the subsequent% (i + 1) $ s. Correct entry
<plurals name="api_arror"> <item quantity="one">Error %s occured</item> <item quantity="other">%1$s errors ocurreds in %2$s</item> </plurals>
Back to PhraseApp, when using the current version of the plug-in, all the above errors await a careless developer if the lines were created without taking into account the specific Android requirements. These errors require correction every time resources are updated. This is clearly ineffective. Begs automation. Unfortunately, I could not write a sane script for sed. In addition, Windows users are not eager to search for this very sed and add to the launch paths.
As an alternative, I bring to your attention another bike for working with strings in Java. The project is open and lies on
GitHub . All code is in one file ignoring OOP, work with string.xml is done head-on, without DOM or SAX. In the utility, there are three modes of operation: by feeding the catalog to the input, we will process all the strings in all subdirectories in the files named strings.xml, after feeding two files - take the first one and copy it into the second one with error correction, and substituting one file we will process it and overwrite it. To start it is enough to put the collected utility in the root of Eclipse or AndroidStudio and execute with the parameter in the form of a dot
java -jar AndroidCleanFixXml.jar.
For PhraseApp users, it may not be possible to edit the source code of the utility. Often, those who fill in locales create a template for formatted output in the form of% {location} -% {duration}, such a substitution will not work with String.format, so all of them have to be replaced. Since it is impossible to understand in general form which type of data will be substituted, the code contains three static constants PHRASE_FLOAT, PHRASE_DECIMAL and PHRASE_STRING. All substitutions found in your localization files must be manually added to the constant.
No temporary files are created at work - so remember about backups or commits to the repository before use. Pleasant use, write issue on github, I will try to correct as much as possible.