{ "id": "128596", "key": "ALOY-980", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "11113", "key": "ALOY", "name": "Alloy", "projectCategory": { "id": "10400", "description": "Tools for developing applications", "name": "Tooling" } }, "fixVersions": [], "resolution": { "id": "7", "description": "", "name": "Invalid" }, "resolutiondate": "2014-04-04T20:55:58.000+0000", "created": "2014-04-02T12:40:50.000+0000", "priority": { "name": "Low", "id": "4" }, "labels": [ "alloy", "android", "community", "ios", "moment.js" ], "versions": [ { "id": "15759", "description": "Alloy 1.3.1", "name": "Alloy 1.3.1", "archived": false, "released": true, "releaseDate": "2014-02-10" } ], "issuelinks": [], "assignee": null, "updated": "2018-03-07T22:28:26.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [], "description": "Steps to reproduce\r\n\r\n1. Create new Alloy project. Default Alloy Project\r\n2. edit index.js controller and add the following to the end:\r\n{code}\r\nmoment = require('alloy/moment');\r\nvar test = moment().format('YYYY-MM-DD HH:mm:ss');\r\nconsole.log(test);\r\n{code}\r\n3. Change language on IOS device to anything other than english (I used German)\r\n4. Debug on device.\r\n5. Execution will halt with:\r\n{code}\r\nThread [kroll$1] (Suspended (exception at line 72 in moment.js))\t\r\ngetLangDefinition(key) [moment.js:72]\t\r\n[Eval script] [moment.js:663]\t\r\n[Eval script] [moment.js:964]\t\r\n[Eval script] [moment.js:1]\t\r\n[Eval script] [moment.js:1]\t\r\nController() [index.js:7]\t\r\n[Eval script] [alloy.js:231]\t\r\n[Top-level script] [app.js:3]\r\n{code}\r\n\r\nProblem code is missing language files:\r\n{code}\r\n function getLangDefinition(key) {\r\n if (!key) return moment.fn._lang;\r\n if (!languages[key] && hasModule) try {\r\n >>>> loadLang(key, require(\"alloy/moment/lang/\" + key)); <<<<\r\n } catch (e) {\r\n return moment.fn._lang;\r\n }\r\n return languages[key];\r\n }\r\n{code}", "attachment": [], "flagged": false, "summary": "Alloy: Builtin moment.js causes exception on device if language is not EN", "creator": { "name": "sschueller", "key": "sschueller", "displayName": "Stefan Schüller", "active": true, "timeZone": "Europe/Berlin" }, "subtasks": [], "reporter": { "name": "sschueller", "key": "sschueller", "displayName": "Stefan Schüller", "active": true, "timeZone": "Europe/Berlin" }, "environment": "OSX 10.9.2, IOS 7.1, Ti SDK 3.2.2 GA, iPad with IOS 7.1", "comment": { "comments": [ { "id": "299846", "author": { "name": "ragrawal", "key": "ragrawal", "displayName": "Ritu Agrawal", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Moving this ticket to engineering as I can reproduce this issue on iPhone 5s with Italian language.", "updateAuthor": { "name": "ragrawal", "key": "ragrawal", "displayName": "Ritu Agrawal", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-04-04T05:54:54.000+0000", "updated": "2014-04-04T05:54:54.000+0000" }, { "id": "299950", "author": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "body": "I just tested the [advanced/moment.js sample app|https://github.com/appcelerator/alloy/tree/master/test/apps/advanced/momentjs] on my iPad, setting the iPad to Spanish. The app works fine. I suspect something with your code. Could you please compare your code to the sample app to confirm the problem is not with your code.\n\nLooking at the sample app, you must include:\n\n{code}\nvar moment = require('alloy/moment');\nvar langs = [\n\t'en', // default, included automatically\n\t'es',\n\t'de',\n\t'fr'\n];\nvar langIndex = 0;\n\n// If you plan to use a particular language in your app that is _not_\n// specified in your project's \"i18n\" folder, you need to explicitly\n// require() it in your code and Alloy's builtin system will pull in the\n// necessary files to use it. It needs to be an explicit string, you cannot\n// assemble it with variables. In other words,\n//\n// do this: require('alloy/moment/lang/es');\n// NOT this: require('alloy/moment/lang/' + locale);\nrequire('alloy/moment/lang/es');\nrequire('alloy/moment/lang/de');\nrequire('alloy/moment/lang/fr');\n{code}", "updateAuthor": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "created": "2014-04-04T20:55:30.000+0000", "updated": "2014-04-04T20:55:30.000+0000" }, { "id": "299951", "author": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "body": "Marking invalid pending developer response", "updateAuthor": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "created": "2014-04-04T20:55:58.000+0000", "updated": "2014-04-04T20:55:58.000+0000" }, { "id": "303526", "author": { "name": "tvm", "key": "tvm", "displayName": "TM", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I have the same error - only when debugging on device. It show the same error. My device is Dutch ('nl'). Using {code:javascript}var moment = require('alloy/moment/lang/nl');{code} instead of the line below doesn't work, it can't find the language files. I do not want a country-specific language. On the contrary, I just need it to format a date, and definitely don't want to include different files depending on the country the device of the user is set to...\r\n\r\nindex.js:\r\n{code:javascript}\r\nvar test = \"2014-01-23 14:45:01\";\r\nvar moment = require('alloy/moment');\r\n$.label.text = moment( test, 'YYYY-MM-DD HH:mm:ss' ).format( 'YYYY-MM-DD (HH:mm)' );\r\n$.index.open();\r\n{code}\r\n\r\nindex.xml\r\n{code:xml}\r\n\r\n\t\r\n\t\t\r\n\t\r\n\r\n{code}\r\n", "updateAuthor": { "name": "tvm", "key": "tvm", "displayName": "TM", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-05-05T19:07:24.000+0000", "updated": "2014-05-05T19:07:24.000+0000" }, { "id": "303533", "author": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "body": "Is that your actual code? If so, you're not requiring in moment correctly. You need to do this (not what you showed as line 1 above):\r\n\r\n{code}\r\nvar moment = require('alloy/moment');\r\nrequire('alloy/moment/lang/nl');\r\n{code}\r\n\r\nIf that doesn't fix your issue, please open a new ticket. That way I can track the work associated with it separately from this issue.", "updateAuthor": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "created": "2014-05-05T19:40:31.000+0000", "updated": "2014-05-05T19:41:57.000+0000" }, { "id": "303535", "author": { "name": "tvm", "key": "tvm", "displayName": "TM", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I'm using the syntax as described in the docs: [http://docs.appcelerator.com/titanium/3.0/#!/api/Alloy.builtins.moment]. Mind you: I definitely do not want localization. The problem is that localization is enforced, which means that a Dutch device has to include a (non-existent) /lang/nl file, and an Italian device a /lang/it file. Moreover, even if I want to go this way the /alloy/moment/lang/nl and other country versions gives an error (file doesn't exist).\r\n\r\nSo, I do not want localization, I just want to use the standard English 'en' language so that I can convert the date format on every device set to every country... I don't want to make an /lang/** file for every country my app can be downloaded, just to get the date in the correct format.\r\n\r\nThe problem seems to lie in the following part of the moment.js code in line #963, which makes localization a requirement instead of an option.\r\n{code:javascript}\r\nif (hasModule) {\r\n moment.lang(Ti.Locale.getCurrentLanguage());\r\n module.exports = moment;\r\n}\r\n{code}\r\n\r\nIs there any way to circumvent this part?", "updateAuthor": { "name": "tvm", "key": "tvm", "displayName": "TM", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-05-05T19:59:50.000+0000", "updated": "2014-05-05T19:59:50.000+0000" }, { "id": "303609", "author": { "name": "sschueller", "key": "sschueller", "displayName": "Stefan Schüller", "active": true, "timeZone": "Europe/Berlin" }, "body": "Can the include requirement please be added to the documentation (maybe here: http://docs.appcelerator.com/titanium/3.0/#!/api/Alloy.builtins.moment) ?", "updateAuthor": { "name": "sschueller", "key": "sschueller", "displayName": "Stefan Schüller", "active": true, "timeZone": "Europe/Berlin" }, "created": "2014-05-06T06:21:15.000+0000", "updated": "2014-05-06T06:21:15.000+0000" }, { "id": "303647", "author": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "updateAuthor": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "created": "2014-05-06T13:56:34.000+0000", "updated": "2014-05-06T13:56:34.000+0000" }, { "id": "354412", "author": { "name": "kopiro", "key": "kopiro", "displayName": "Flavio De Stefano", "active": true, "timeZone": "Europe/Rome" }, "body": "This is not resolved, and it is a very dangerous bug, \r\nbecause on devices with lang !== 'en', *it crashes immediately*!\r\n\r\nThis is the crash report:\r\n\r\n```\r\n[ERROR] The application has crashed with an uncaught exception 'org.test.kroll'.\r\n[ERROR] Reason:\r\n[ERROR] Couldn't find module: alloy/moment/lang/it for architecture: i386\r\n[ERROR] Stack trace:\r\n[ERROR]\r\n[ERROR] 0 CoreFoundation 0x04fcc72a __exceptionPreprocess + 154\r\n[ERROR] 1 libobjc.A.dylib 0x04b9fa97 objc_exception_throw + 44\r\n[ERROR] 2 APP 0x0004e6c0 -[KrollBridge require:path:] + 4496\r\n[ERROR] 3 APP 0x00057326 CommonJSRequireCallback + 230\r\n[ERROR] 4 APP 0x003ca5ca _ZN2TI19APICallbackFunction4callINS_18JSCallbackFunctionEEExPNS_9ExecStateE + 698\r\n[ERROR] 5 APP 0x003a55b6 _ZN2TI14handleHostCallEPNS_9ExecStateENS_7TiValueENS_22CodeSpecializationKindE + 630\r\n[ERROR] 6 APP 0x003a598c linkFor + 156\r\n[ERROR] 7 APP 0x003a0009 operationLinkCall + 25\r\n[ERROR] 8 ??? 0xca402214 0x0 + 3393200660\r\n[ERROR]\r\n[ERROR] 2015-06-05 12:41:04.435 APP[33782:443852] *** Terminating app due to uncaught exception 'org.test.kroll', reason: 'Couldn't find module: alloy/moment/lang/it for architecture: i386'\r\n[ERROR] *** First throw call stack:\r\n[ERROR] (\r\n[ERROR] 0 CoreFoundation 0x04fcc746 __exceptionPreprocess + 182\r\n[ERROR] 1 libobjc.A.dylib 0x04b9fa97 objc_exception_throw + 44\r\n[ERROR] 2 APP 0x0004e6c0 -[KrollBridge require:path:] + 4496\r\n[ERROR] 3 APP 0x00057326 CommonJSRequireCallback + 230\r\n[ERROR] 4 APP 0x003ca5ca _ZN2TI19APICallbackFunction4callINS_18JSCallbackFunctionEEExPNS_9ExecStateE + 698\r\n[ERROR] 5 APP 0x003a55b6 _ZN2TI14handleHostCallEPNS_9ExecStateENS_7TiValueENS_22CodeSpecializationKindE + 630\r\n[ERROR] 6 APP 0x003a598c linkFor + 156\r\n[ERROR] 7 APP 0x003a0009 operationLinkCall + 25\r\n[ERROR] 8 ??? 0xca402214 0x0 + 3393200660\r\n[ERROR] )\r\n[ERROR] libc++abi.dylib: terminating with uncaught exception of type NSException\r\n```\r\n\r\n\r\nThe problem is obviously here: \r\n\r\n\r\nfunction getLangDefinition(key) {\r\n var i = 0, j, lang, next, split,\r\n get = function (k) {\r\n if (!languages[k] && hasModule) {\r\n try {\r\n loadLang(k, require('alloy/moment/lang/' + k)); // The require fails\r\n } catch (e) {\r\n return moment.fn._lang;\r\n }\r\n }\r\n return languages[k];\r\n };\r\n```\r\n\r\nThe question is, why the `try { .. } catch {}` doesn't catch the `org.test.kroll` exception?\r\n\r\n---\r\n\r\nThe immediate solution is to copy the `alloy/builtins/moment/lang` from Alloy project in the `app/lib` directory...\r\nBut, you theoritically have to copy all languages, not only yours, for this line of code:\r\n\r\n```\r\nmoment.lang(Ti.Locale.getCurrentLanguage());\r\n```", "updateAuthor": { "name": "kopiro", "key": "kopiro", "displayName": "Flavio De Stefano", "active": true, "timeZone": "Europe/Rome" }, "created": "2015-06-05T10:49:43.000+0000", "updated": "2015-06-05T10:49:43.000+0000" }, { "id": "355208", "author": { "name": "sschueller", "key": "sschueller", "displayName": "Stefan Schüller", "active": true, "timeZone": "Europe/Berlin" }, "body": "This is not fixed and the solution above does not work in the cause where you want to support ALL languages without creating a i18n string file or load each language manually for moment. Since only an explicitly string can be used to load a moment language it is not possible to load a default. The language of the device is not know before compile time.\r\n\r\nPlease re-open this ticket", "updateAuthor": { "name": "sschueller", "key": "sschueller", "displayName": "Stefan Schüller", "active": true, "timeZone": "Europe/Berlin" }, "created": "2015-06-16T13:52:23.000+0000", "updated": "2015-06-16T13:52:23.000+0000" }, { "id": "385301", "author": { "name": "cthomas", "key": "cthomas", "displayName": "Christy Thomas", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I've seen this with 5.2.2 SDK and when debugging:\r\n\r\nThread [kroll$1] (Suspended (exception at line 134 in moment.js))\t\r\n\tloadLocale(name) [moment.js:134]\t\r\n\tlocale_locales__getLocale(key) [moment.js:163]\t\r\n\tlocale_locales__getSetGlobalLocale(key, values) [moment.js:142]\t\r\n\tController() [index.js:800]\t\r\n\tcreateController(name, args) [alloy.js:232]\t\r\n\tshowCustomDialog(args) [dialogUtils.js:114]\t\r\n\tshowAssociateProfile() [associatePopover.js:63]\t\r\n\r\nCaused by this call: moment.locale(Ti.Locale.currentLocale);\r\n\r\n", "updateAuthor": { "name": "cthomas", "key": "cthomas", "displayName": "Christy Thomas", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2016-05-10T17:10:30.000+0000", "updated": "2016-05-10T17:10:30.000+0000" }, { "id": "435333", "author": { "name": "emerriman", "key": "emerriman", "displayName": "Eric Merriman ", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Closing as invalid. If this is incorrect, please reopen.", "updateAuthor": { "name": "emerriman", "key": "emerriman", "displayName": "Eric Merriman ", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-03-07T22:28:26.000+0000", "updated": "2018-03-07T22:28:26.000+0000" } ], "maxResults": 12, "total": 12, "startAt": 0 } } }