Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-6945] Android: i18n - Multi-string substitution using String.format() fails

GitHub Issuen/a
TypeBug
PriorityLow
StatusReopened
ResolutionUnresolved
Affected Version/sRelease 1.7.2, Release 1.8.0.1
Fix Version/sn/a
ComponentsAndroid
Labelscb-tooling
ReporterAndreas
AssigneeIngo Muschenetz
Created2011-07-30T05:16:02.000+0000
Updated2016-08-22T22:16:48.000+0000

Description

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)));

Comments

  1. Paul Dowsett 2011-08-02

    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
  2. Andreas 2011-08-03

    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
  3. Paul Dowsett 2011-08-03

    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
  4. Joël Bohrer 2011-08-22

    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
  5. Paul Dowsett 2011-09-07

    Andreas When you have had time to address the issues I mentioned before, you are welcome to reopen this ticket. Many thanks.
  6. Paul Dowsett 2011-12-27

    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.
  7. Paul Dowsett 2012-03-15

    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 * v8

    Test case

       <?xml version="1.0" encoding="UTF-8"?>
       <resources>
       	<string name="nonPositionalSubstitutionThreeString">%s %s %d</string>
       </resources>
       
    With an empty app.js, launch the application.

    Log

       [ERROR] Error generating R.java from manifest
       [ERROR] /home/appcel/Titanium Studio Workspace/testing10/build/android/res/values/strings.xml:5: 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:5: error: Unexpected end tag string
       
  8. Ygor Lemos 2013-10-04

    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.

JSON Source