Problem
Multi-string i18n substitution (demonstrated in [#Test case 2] and [#Test case 3]) using String.format() fails, while single string substitution ([#Test case 1]) works as expected.
{panel}
Note that the project must be manually cleaned after any strings.xml files have been modified
{panel}
Test case
Test case 1
* Single string, non-positional substitution works as expected
* Single string, positional substitution works as expected
Ti.API.info('The result of the string substitution is: ' + String.format(L('nonPositionalSubstitutionOneString'), 'String1'));
Ti.API.info('The result of the string substitution is: ' + String.format(L('positionalSubstitutionOneString'), 'String1'));
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="nonPositionalSubstitutionOneString">%s</string>
<string name="positionalSubstitutionOneString">%1$s</string>
</resources>
883 TiAPI I The result of the string substitution is: String1
883 TiAPI I The result of the string substitution is: String1
Test case 2
* Multiple string, non-positional substitution fails
Ti.API.info('The result of the string substitution is: ' + String.format(L('nonPositionalSubstitutionThreeString'), 'String1', 'String2', 3));
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="nonPositionalSubstitutionThreeString">%s %s %d</string>
</resources>
[ERROR] Error generating R.java from manifest
[ERROR] /home/appcel/Titanium Studio Workspace/testing10/build/android/res/values/strings.xml:3: error: Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?
[ERROR] /home/appcel/Titanium Studio Workspace/testing10/build/android/res/values/strings.xml:3: error: Unexpected end tag string
909 TitaniumModule E (KrollRuntimeThread) [248,1369] Error in string format
909 TitaniumModule E java.lang.NullPointerException
909 TitaniumModule E at ti.modules.titanium.TitaniumModule.stringFormat(TitaniumModule.java:285)
909 TitaniumModule E at org.appcelerator.kroll.runtime.v8.V8Runtime.nativeRunModule(Native Method)
909 TitaniumModule E at org.appcelerator.kroll.runtime.v8.V8Runtime.doRunModule(V8Runtime.java:107)
909 TitaniumModule E at org.appcelerator.kroll.KrollRuntime.handleMessage(KrollRuntime.java:207)
909 TitaniumModule E at org.appcelerator.kroll.runtime.v8.V8Runtime.handleMessage(V8Runtime.java:127)
909 TitaniumModule E at android.os.Handler.dispatchMessage(Handler.java:95)
909 TitaniumModule E at android.os.Looper.loop(Looper.java:123)
909 TitaniumModule E at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:102)
909 TiAPI I The result of the string substitution is: null
Test case 3
* Multiple string, positional substitution fails
Ti.API.info('The result of the string substitution is: ' + String.format(L('positionalSubstitutionThreeString'), 'String1', 'String2', 3));
<string name="positionalSubstitutionThreeString">%3$d %2$s %1$s</string>
No error produced in console.
983 TitaniumModule E (KrollRuntimeThread) [280,1472] Error in string format
983 TitaniumModule E java.lang.NullPointerException
983 TitaniumModule E at ti.modules.titanium.TitaniumModule.stringFormat(TitaniumModule.java:285)
983 TitaniumModule E at org.appcelerator.kroll.runtime.v8.V8Runtime.nativeRunModule(Native Method)
983 TitaniumModule E at org.appcelerator.kroll.runtime.v8.V8Runtime.doRunModule(V8Runtime.java:107)
983 TitaniumModule E at org.appcelerator.kroll.KrollRuntime.handleMessage(KrollRuntime.java:207)
983 TitaniumModule E at org.appcelerator.kroll.runtime.v8.V8Runtime.handleMessage(V8Runtime.java:127)
983 TitaniumModule E at android.os.Handler.dispatchMessage(Handler.java:95)
983 TitaniumModule E at android.os.Looper.loop(Looper.java:123)
983 TitaniumModule E at org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:102)
983 TiAPI I The result of the string substitution is: null
Discussions
The original reporter prompted the above investigation, and provided the following information about Titanium 1.7.X where there was a slightly different message
* Titanium SDK version: 1.7.2
* Platform & version: Android 2.3
* Device Details: Android emulator
* Host Operating System: Windows Vista
* Titanium Studio version: Titanium Studio, build: 1.0.2.201107130739
If i use % placeholder inside the language strings, the building is stopped! If i remove the %, everything works like expected
The following configuration of my string.xml dont work!
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="gpUiPageIntOfInt">Page %d of %d</string>
</resources>
This is the output in my adb log.
The errormessage is *"Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?"
*
[DEBUG] D:\development\enviroment\Android\android-sdk\platform-tools\aapt.exe package -m -J D:\development\workspaces\titanium-studio\meintest\build\android\gen
-M D:\development\workspaces\titanium-studio\meintest\build\android\AndroidManifest.xml -S D:\development\workspaces\titanium-studio\meintest\build\android\res
-I D:\development\enviroment\Android\android-sdk\platforms\android-7\android.jar
[ERROR] D:\development\workspaces\titanium-studio\meintest\build\android\res\values\strings.xml:23: error: Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?
[ERROR] D:\development\workspaces\titanium-studio\meintest\build\android\res\values\strings.xml:23: error: Unexpected end tag string
[ERROR] Error generating R.java from manifest
Workaround
See [this stackoverflow.com thread](
http://stackoverflow.com/questions/4414389/android-xml-percent-symbol/4417333#4417333)
Use
formatted="false"
for each element of the
strings.xml
file where multiple placeholders are used.
Works as expected on Android 2.2+ & Titanium SDK version: 2.0.0 (03/15/12 07:02 c822d01).
Test Case 4
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="phrase" formatted="false">You say %2$s and I say %1$s!</string>
<string name="greeting">hello</string>
<string name="signoff">goodbye</string>
</resources>
var i18nError = '<no translation available for the current system locale>';
Ti.API.info(String.format(L('phrase'), L('greeting', i18nError), L('signoff', i18nError)));
Thank you for raising this ticket. In order to progress it, please add the missing information in the format and places requested in the guidelines at [Jira Ticket Checklist](http://wiki.appcelerator.org/display/guides/Contributing+to+Titanium#ContributingtoTitanium-Summary%3AJiraTicketChecklist). Many thanks in advance
Titanium SDK version: 1.7.2 Platform & version: Android 2.3 Device Details: Android emulator Host Operating System: Windows Vista Titanium Studio version: Titanium Studio, build: 1.0.2.201107130739
Thank you, Andreas. So that tickets are consistent for the core team, would you move this information to the environment field? Please provide a usecase that demonstrates this issue. See [Creating Good Use-cases](http://wiki.appcelerator.org/display/guides/Contributing+to+Titanium#ContributingtoTitanium-CreatingGoodUsecases) for info about this. Please provide the full log, in a code block as per the checklist instructions. Then I can move this ticket. Cheers
Hi, I've the same issue. In fact, it's only if you have 2 time "%" in the same string (with only one, everything works). Joel
Andreas When you have had time to address the issues I mentioned before, you are welcome to reopen this ticket. Many thanks.
In order for me to escalate it to the core team, all the fields must be complete. Please check it against the [JIRA Ticket Checklist](https://wiki.appcelerator.org/display/guides/How+to+Submit+a+Bug+Report#HowtoSubmitaBugReport-JIRATicketChecklist), and add any missing information. Furthermore, a test case must run without modification, as per the [Creating a Test Case](https://wiki.appcelerator.org/display/guides/How+to+Submit+a+Bug+Report#HowtoSubmitaBugReport-CreatingaTestCase) section.
The following test case, where multiple substitution placemarks are used in strings.xml, gives the error message below.
Environment
* Titanium SDK version: 2.0.0 (03/15/12 07:02 c822d01) * Android APIs 2.3.3 * v8Test case
With an empty app.js, launch the application.
Log
Any updates on this? If using formatted="true" is required for Android now, it should be reflected on the documentation. I have searched the 3.X docs and the appcelerator wiki and found no mentions of the formatted="false" problem with Android, had to find this on JIRA in order to fix my printf localized strings. Please at least update https://wiki.appcelerator.org/display/guides/Internationalization so users know this is the way to solve it for now.