{ "id": "78544", "key": "TIMOB-6945", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": null, "resolutiondate": null, "created": "2011-07-30T05:16:02.000+0000", "priority": { "name": "Low", "id": "4" }, "labels": [ "cb-tooling" ], "versions": [ { "id": "11570", "description": "", "name": "Release 1.7.2", "archived": true, "released": true, "releaseDate": "2011-07-21" }, { "id": "12580", "description": "Dual Runtime 1.8.0", "name": "Release 1.8.0.1", "archived": true, "released": true, "releaseDate": "2011-12-22" } ], "issuelinks": [], "assignee": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2016-08-22T22:16:48.000+0000", "status": { "description": "This issue was once resolved, but the resolution was deemed incorrect. From here issues are either marked assigned or resolved.", "name": "Reopened", "id": "4", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "h2. Problem\r\n\r\nMulti-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.\r\n\r\n{panel}\r\nNote that the project must be manually cleaned after any strings.xml files have been modified\r\n{panel}\r\n\r\nh2. Test case\r\n\r\nh3. Test case 1\r\n\r\n* Single string, non-positional substitution works as expected\r\n* Single string, positional substitution works as expected\r\n\r\n{code:lang=javascript|title=app.js}\r\nTi.API.info('The result of the string substitution is: ' + String.format(L('nonPositionalSubstitutionOneString'), 'String1'));\r\nTi.API.info('The result of the string substitution is: ' + String.format(L('positionalSubstitutionOneString'), 'String1'));\r\n{code}\r\n\r\n{code:lang=xml|title=i18n/en/strings.xml}\r\n\r\n\r\n\t%s\r\n\t%1$s\r\n\r\n{code}\r\n\r\n{code:lang=none|title=logcat}\r\n 883 TiAPI I The result of the string substitution is: String1\r\n 883 TiAPI I The result of the string substitution is: String1\r\n{code}\r\n\r\nh2. Test case 2\r\n\r\n* Multiple string, non-positional substitution fails\r\n\r\n{code:lang=javascript|title=app.js}\r\nTi.API.info('The result of the string substitution is: ' + String.format(L('nonPositionalSubstitutionThreeString'), 'String1', 'String2', 3));\r\n{code}\r\n\r\n{code:lang=xml|title=i18n/en/strings.xml}\r\n\r\n\r\n\t%s %s %d\r\n\r\n{code}\r\n\r\n{code:lang=none|title=console}\r\n[ERROR] Error generating R.java from manifest\r\n[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?\r\n[ERROR] /home/appcel/Titanium Studio Workspace/testing10/build/android/res/values/strings.xml:3: error: Unexpected end tag string\r\n{code}\r\n\r\n{code:lang=none|title=logcat}\r\n 909 TitaniumModule E (KrollRuntimeThread) [248,1369] Error in string format\r\n 909 TitaniumModule E java.lang.NullPointerException\r\n 909 TitaniumModule E \tat ti.modules.titanium.TitaniumModule.stringFormat(TitaniumModule.java:285)\r\n 909 TitaniumModule E \tat org.appcelerator.kroll.runtime.v8.V8Runtime.nativeRunModule(Native Method)\r\n 909 TitaniumModule E \tat org.appcelerator.kroll.runtime.v8.V8Runtime.doRunModule(V8Runtime.java:107)\r\n 909 TitaniumModule E \tat org.appcelerator.kroll.KrollRuntime.handleMessage(KrollRuntime.java:207)\r\n 909 TitaniumModule E \tat org.appcelerator.kroll.runtime.v8.V8Runtime.handleMessage(V8Runtime.java:127)\r\n 909 TitaniumModule E \tat android.os.Handler.dispatchMessage(Handler.java:95)\r\n 909 TitaniumModule E \tat android.os.Looper.loop(Looper.java:123)\r\n 909 TitaniumModule E \tat org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:102)\r\n 909 TiAPI I The result of the string substitution is: null\r\n{code}\r\n\r\nh2. Test case 3\r\n\r\n* Multiple string, positional substitution fails\r\n\r\n{code:lang=javascript|title=app.js}\r\nTi.API.info('The result of the string substitution is: ' + String.format(L('positionalSubstitutionThreeString'), 'String1', 'String2', 3));\r\n{code}\r\n\r\n{code:lang=xml|title=i18n/en/strings.xml}\r\n%3$d %2$s %1$s\r\n{code}\r\n\r\nNo error produced in console.\r\n\r\n{code:lang=none|title=logcat}\r\n 983 TitaniumModule E (KrollRuntimeThread) [280,1472] Error in string format\r\n 983 TitaniumModule E java.lang.NullPointerException\r\n 983 TitaniumModule E \tat ti.modules.titanium.TitaniumModule.stringFormat(TitaniumModule.java:285)\r\n 983 TitaniumModule E \tat org.appcelerator.kroll.runtime.v8.V8Runtime.nativeRunModule(Native Method)\r\n 983 TitaniumModule E \tat org.appcelerator.kroll.runtime.v8.V8Runtime.doRunModule(V8Runtime.java:107)\r\n 983 TitaniumModule E \tat org.appcelerator.kroll.KrollRuntime.handleMessage(KrollRuntime.java:207)\r\n 983 TitaniumModule E \tat org.appcelerator.kroll.runtime.v8.V8Runtime.handleMessage(V8Runtime.java:127)\r\n 983 TitaniumModule E \tat android.os.Handler.dispatchMessage(Handler.java:95)\r\n 983 TitaniumModule E \tat android.os.Looper.loop(Looper.java:123)\r\n 983 TitaniumModule E \tat org.appcelerator.kroll.KrollRuntime$KrollRuntimeThread.run(KrollRuntime.java:102)\r\n 983 TiAPI I The result of the string substitution is: null\r\n{code}\r\n\r\n\r\n\r\nh2. Discussions\r\n\r\nThe original reporter prompted the above investigation, and provided the following information about Titanium 1.7.X where there was a slightly different message\r\n\r\n{code}\r\n* Titanium SDK version: 1.7.2\r\n* Platform & version: Android 2.3\r\n* Device Details: Android emulator\r\n* Host Operating System: Windows Vista\r\n* Titanium Studio version: Titanium Studio, build: 1.0.2.201107130739\r\n{code}\r\n\r\n{code}\r\nIf i use % placeholder inside the language strings, the building is stopped! If i remove the %, everything works like expected\r\n\r\nThe following configuration of my string.xml dont work!\r\n\r\n\r\n\r\n Page %d of %d\r\n\r\n\r\nThis is the output in my adb log.\r\n\r\nThe errormessage is *{{\"Multiple substitutions specified in non-positional format; did you mean to add the formatted=\"false\" attribute?\"}}*\r\n\r\n[DEBUG] D:\\development\\enviroment\\Android\\android-sdk\\platform-tools\\aapt.exe package -m -J D:\\development\\workspaces\\titanium-studio\\meintest\\build\\android\\gen\r\n -M D:\\development\\workspaces\\titanium-studio\\meintest\\build\\android\\AndroidManifest.xml -S D:\\development\\workspaces\\titanium-studio\\meintest\\build\\android\\res\r\n -I D:\\development\\enviroment\\Android\\android-sdk\\platforms\\android-7\\android.jar\r\n[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?\r\n[ERROR] D:\\development\\workspaces\\titanium-studio\\meintest\\build\\android\\res\\values\\strings.xml:23: error: Unexpected end tag string\r\n[ERROR] Error generating R.java from manifest\r\n\r\n{code} \r\n\r\n\r\nh2. Workaround\r\n\r\nSee [this stackoverflow.com thread|http://stackoverflow.com/questions/4414389/android-xml-percent-symbol/4417333#4417333]\r\n\r\nUse {{formatted=\"false\"}} for each element of the {{strings.xml}} file where multiple placeholders are used.\r\n\r\nWorks as expected on Android 2.2+ & Titanium SDK version: 2.0.0 (03/15/12 07:02 c822d01).\r\n\r\nh3. Test Case 4\r\n\r\n{code:lang=xml|title=/i18n/en/strings.xml}\r\n\r\n\r\n\tYou say %2$s and I say %1$s!\r\n\thello\r\n\tgoodbye\r\n\r\n{code}\r\n\r\n{code:lang=javascript|title=app.js}\r\nvar i18nError = '';\r\nTi.API.info(String.format(L('phrase'), L('greeting', i18nError), L('signoff', i18nError)));\r\n{code}\r\n\r\n", "attachment": [], "flagged": false, "summary": "Android: i18n - Multi-string substitution using String.format() fails", "creator": { "name": "greenphp", "key": "greenphp", "displayName": "Andreas", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "greenphp", "key": "greenphp", "displayName": "Andreas", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "* Titanium SDK version: 1.8.0.1 (12/22/11 13:09 fbdc96f) (official release)\r\n* Runtime: v8\r\n* Google APIs Android 2.2\r\n* Titanium Studio, build: 1.0.8.201112282257\r\n* Ubuntu 10.04\r\n\r\n", "comment": { "comments": [ { "id": "161603", "author": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "body": "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].\r\n\r\nMany thanks in advance", "updateAuthor": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "created": "2011-08-02T16:54:17.000+0000", "updated": "2011-08-02T16:54:17.000+0000" }, { "id": "161649", "author": { "name": "greenphp", "key": "greenphp", "displayName": "Andreas", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Titanium SDK version: 1.7.2\r\nPlatform & version: Android 2.3\r\nDevice Details: Android emulator\r\nHost Operating System: Windows Vista\r\nTitanium Studio version: Titanium Studio, build: 1.0.2.201107130739", "updateAuthor": { "name": "greenphp", "key": "greenphp", "displayName": "Andreas", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-08-03T04:27:00.000+0000", "updated": "2011-08-03T04:27:00.000+0000" }, { "id": "161679", "author": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "body": "Thank you, Andreas. So that tickets are consistent for the core team, would you move this information to the environment field?\r\n\r\nPlease 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.\r\n\r\nPlease provide the full log, in a code block as per the checklist instructions.\r\n\r\nThen I can move this ticket.\r\n\r\nCheers", "updateAuthor": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "created": "2011-08-03T07:38:06.000+0000", "updated": "2011-08-03T07:38:06.000+0000" }, { "id": "163597", "author": { "name": "joel.bohrer", "key": "joel.bohrer", "displayName": "Joël Bohrer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Hi,\r\n\r\nI've the same issue. In fact, it's only if you have 2 time \"%\" in the same string (with only one, everything works).\r\n\r\nJoel", "updateAuthor": { "name": "joel.bohrer", "key": "joel.bohrer", "displayName": "Joël Bohrer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-08-22T02:35:53.000+0000", "updated": "2011-08-22T02:35:53.000+0000" }, { "id": "165198", "author": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "body": "Andreas\n\nWhen you have had time to address the issues I mentioned before, you are welcome to reopen this ticket. Many thanks.", "updateAuthor": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "created": "2011-09-07T07:01:22.000+0000", "updated": "2011-09-07T07:01:22.000+0000" }, { "id": "177239", "author": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "body": "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.\r\n\r\nFurthermore, 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.\r\n", "updateAuthor": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "created": "2011-12-27T06:32:59.000+0000", "updated": "2011-12-27T06:32:59.000+0000" }, { "id": "186602", "author": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "body": "\r\nThe following test case, where multiple substitution placemarks are used in strings.xml, gives the error message below.\r\n\r\nh4. Environment\r\n\r\n* Titanium SDK version: 2.0.0 (03/15/12 07:02 c822d01)\r\n* Android APIs 2.3.3\r\n* v8\r\n\r\nh4. Test case\r\n\r\n{code:lang=xml|title=/i18n/en/strings.xml}\r\n\r\n\r\n\t%s %s %d\r\n\r\n{code}\r\n\r\nWith an empty app.js, launch the application.\r\n\r\nh4. Log\r\n\r\n{code:lang=none|title=console}\r\n[ERROR] Error generating R.java from manifest\r\n[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?\r\n[ERROR] /home/appcel/Titanium Studio Workspace/testing10/build/android/res/values/strings.xml:5: error: Unexpected end tag string\r\n{code}\r\n", "updateAuthor": { "name": "pdowsett", "key": "pdowsett", "displayName": "Paul Dowsett", "active": true, "timeZone": "Europe/London" }, "created": "2012-03-15T07:52:27.000+0000", "updated": "2012-03-15T07:52:27.000+0000" }, { "id": "273899", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "Any updates on this? If using formatted=\"true\" is required for Android now, it should be reflected on the documentation.\r\n\r\nI 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.\r\n\r\nPlease at least update https://wiki.appcelerator.org/display/guides/Internationalization so users know this is the way to solve it for now.", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-10-04T22:51:01.000+0000", "updated": "2013-10-04T22:51:01.000+0000" } ], "maxResults": 10, "total": 10, "startAt": 0 } } }