[ALOY-980] Alloy: Builtin moment.js causes exception on device if language is not EN
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Low |
Status | Closed |
Resolution | Invalid |
Resolution Date | 2014-04-04T20:55:58.000+0000 |
Affected Version/s | Alloy 1.3.1 |
Fix Version/s | n/a |
Components | n/a |
Labels | alloy, android, community, ios, moment.js |
Reporter | Stefan Schüller |
Assignee | Unknown |
Created | 2014-04-02T12:40:50.000+0000 |
Updated | 2018-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
- Ritu Agrawal 2014-04-04 Moving this ticket to engineering as I can reproduce this issue on iPhone 5s with Italian language.
- 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');
- Tim Poulsen 2014-04-04 Marking invalid pending developer response
- 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
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 moment = require('alloy/moment/lang/nl');
index.xmlvar 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();
<Alloy> <Window class="container"> <Label id="label">Hello, World</Label> </Window> </Alloy>
- 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):
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.var moment = require('alloy/moment'); require('alloy/moment/lang/nl');
- 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.
Is there any way to circumvent this part?if (hasModule) { moment.lang(Ti.Locale.getCurrentLanguage()); module.exports = moment; }
- 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) ?
- Tim Poulsen 2014-05-06
- 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:
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]; };[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
moment.lang(Ti.Locale.getCurrentLanguage()); ```The question is, why the
try { .. } catch {}
doesn't catch theorg.test.kroll
exception? --- The immediate solution is to copy thealloy/builtins/moment/lang
from Alloy project in theapp/lib
directory... But, you theoritically have to copy all languages, not only yours, for this line of code: - 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
- 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);
- Eric Merriman 2018-03-07 Closing as invalid. If this is incorrect, please reopen.