Titanium JIRA Archive
Alloy (ALOY)

[ALOY-980] Alloy: Builtin moment.js causes exception on device if language is not EN

GitHub Issuen/a
TypeBug
PriorityLow
StatusClosed
ResolutionInvalid
Resolution Date2014-04-04T20:55:58.000+0000
Affected Version/sAlloy 1.3.1
Fix Version/sn/a
Componentsn/a
Labelsalloy, android, community, ios, moment.js
ReporterStefan Schüller
AssigneeUnknown
Created2014-04-02T12:40:50.000+0000
Updated2018-03-07T22:28:26.000+0000

Description

Steps to reproduce 1. Create new Alloy project. Default Alloy Project 2. edit index.js controller and add the following to the end:
moment = require('alloy/moment');
var test = moment().format('YYYY-MM-DD HH:mm:ss');
console.log(test);
3. Change language on IOS device to anything other than english (I used German) 4. Debug on device. 5. Execution will halt with:
Thread [kroll$1] (Suspended (exception at line 72 in moment.js))	
getLangDefinition(key) [moment.js:72]	
[Eval script] [moment.js:663]	
[Eval script] [moment.js:964]	
[Eval script] [moment.js:1]	
[Eval script] [moment.js:1]	
Controller() [index.js:7]	
[Eval script] [alloy.js:231]	
[Top-level script] [app.js:3]
Problem code is missing language files:
    function getLangDefinition(key) {
        if (!key) return moment.fn._lang;
        if (!languages[key] && hasModule) try {
   >>>>         loadLang(key, require("alloy/moment/lang/" + key));      <<<<
        } catch (e) {
            return moment.fn._lang;
        }
        return languages[key];
    }

Comments

  1. Ritu Agrawal 2014-04-04

    Moving this ticket to engineering as I can reproduce this issue on iPhone 5s with Italian language.
  2. Tim Poulsen 2014-04-04

    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. Looking at the sample app, you must include:
       var moment = require('alloy/moment');
       var langs = [
       	'en', // default, included automatically
       	'es',
       	'de',
       	'fr'
       ];
       var langIndex = 0;
       
       // If you plan to use a particular language in your app that is _not_
       // specified in your project's "i18n" folder, you need to explicitly
       // require() it in your code and Alloy's builtin system will pull in the
       // necessary files to use it. It needs to be an explicit string, you cannot
       // assemble it with variables. In other words,
       //
       // do this:  require('alloy/moment/lang/es');
       // NOT this: require('alloy/moment/lang/' + locale);
       require('alloy/moment/lang/es');
       require('alloy/moment/lang/de');
       require('alloy/moment/lang/fr');
       
  3. Tim Poulsen 2014-04-04

    Marking invalid pending developer response
  4. TM 2014-05-05

    I have the same error - only when debugging on device. It show the same error. My device is Dutch ('nl'). Using
    var moment = require('alloy/moment/lang/nl');
    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... index.js:
       var test = "2014-01-23 14:45:01";
       var moment = require('alloy/moment');
       $.label.text = moment( test, 'YYYY-MM-DD HH:mm:ss' ).format( 'YYYY-MM-DD (HH:mm)' );
       $.index.open();
       
    index.xml
       <Alloy>
       	<Window class="container">
       		<Label id="label">Hello, World</Label>
       	</Window>
       </Alloy>
       
  5. Tim Poulsen 2014-05-05

    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):
       var moment = require('alloy/moment');
       require('alloy/moment/lang/nl');
       
    If 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.
  6. TM 2014-05-05

    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). So, 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. The 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.
       if (hasModule) {
           moment.lang(Ti.Locale.getCurrentLanguage());
           module.exports = moment;
       }
       
    Is there any way to circumvent this part?
  7. Stefan Schüller 2014-05-06

    Can the include requirement please be added to the documentation (maybe here: http://docs.appcelerator.com/titanium/3.0/#!/api/Alloy.builtins.moment) ?
  8. Tim Poulsen 2014-05-06

  9. Flavio De Stefano 2015-06-05

    This is not resolved, and it is a very dangerous bug, because on devices with lang !== 'en', *it crashes immediately*! This is the crash report:
       [ERROR] The application has crashed with an uncaught exception 'org.test.kroll'.
       [ERROR] Reason:
       [ERROR] Couldn't find module: alloy/moment/lang/it for architecture: i386
       [ERROR] Stack trace:
       [ERROR]
       [ERROR] 0   CoreFoundation                      0x04fcc72a __exceptionPreprocess + 154
       [ERROR] 1   libobjc.A.dylib                     0x04b9fa97 objc_exception_throw + 44
       [ERROR] 2   APP                                0x0004e6c0 -[KrollBridge require:path:] + 4496
       [ERROR] 3   APP                                0x00057326 CommonJSRequireCallback + 230
       [ERROR] 4   APP                                0x003ca5ca _ZN2TI19APICallbackFunction4callINS_18JSCallbackFunctionEEExPNS_9ExecStateE + 698
       [ERROR] 5   APP                                0x003a55b6 _ZN2TI14handleHostCallEPNS_9ExecStateENS_7TiValueENS_22CodeSpecializationKindE + 630
       [ERROR] 6   APP                                0x003a598c linkFor + 156
       [ERROR] 7   APP                                0x003a0009 operationLinkCall + 25
       [ERROR] 8   ???                                 0xca402214 0x0 + 3393200660
       [ERROR]
       [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'
       [ERROR] *** First throw call stack:
       [ERROR] (
       [ERROR]         0   CoreFoundation                      0x04fcc746 __exceptionPreprocess + 182
       [ERROR]         1   libobjc.A.dylib                     0x04b9fa97 objc_exception_throw + 44
       [ERROR]         2   APP                                0x0004e6c0 -[KrollBridge require:path:] + 4496
       [ERROR]         3   APP                                0x00057326 CommonJSRequireCallback + 230
       [ERROR]         4   APP                                0x003ca5ca _ZN2TI19APICallbackFunction4callINS_18JSCallbackFunctionEEExPNS_9ExecStateE + 698
       [ERROR]         5   APP                                0x003a55b6 _ZN2TI14handleHostCallEPNS_9ExecStateENS_7TiValueENS_22CodeSpecializationKindE + 630
       [ERROR]         6   APP                                0x003a598c linkFor + 156
       [ERROR]         7   APP                                0x003a0009 operationLinkCall + 25
       [ERROR]         8   ???                                 0xca402214 0x0 + 3393200660
       [ERROR] )
       [ERROR] libc++abi.dylib: terminating with uncaught exception of type NSException
       
    The problem is obviously here: function getLangDefinition(key) { var i = 0, j, lang, next, split, get = function (k) { if (!languages[k] && hasModule) { try { loadLang(k, require('alloy/moment/lang/' + k)); // The require fails } catch (e) { return moment.fn._lang; } } return languages[k]; };
       
       The question is, why the try { .. } catch {} doesn't catch the org.test.kroll exception?
       
       ---
       
       The immediate solution is to copy the alloy/builtins/moment/lang from Alloy project in the app/lib directory...
       But, you theoritically have to copy all languages, not only yours, for this line of code:
       
       
    moment.lang(Ti.Locale.getCurrentLanguage()); ```
  10. Stefan Schüller 2015-06-16

    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. Please re-open this ticket
  11. Christy Thomas 2016-05-10

    I've seen this with 5.2.2 SDK and when debugging: Thread [kroll$1] (Suspended (exception at line 134 in moment.js)) loadLocale(name) [moment.js:134] locale_locales__getLocale(key) [moment.js:163] locale_locales__getSetGlobalLocale(key, values) [moment.js:142] Controller() [index.js:800] createController(name, args) [alloy.js:232] showCustomDialog(args) [dialogUtils.js:114] showAssociateProfile() [associatePopover.js:63] Caused by this call: moment.locale(Ti.Locale.currentLocale);
  12. Eric Merriman 2018-03-07

    Closing as invalid. If this is incorrect, please reopen.

JSON Source