Browse Source

Updates #849

Refactor locales code to store the currently chosen locale as
`_converse.locale` and use that in converse-notifications.js
JC Brand 8 years ago
parent
commit
f0deac9ec5
5 changed files with 76 additions and 68 deletions
  1. 1 1
      docs/CHANGES.md
  2. 13 26
      src/converse-core.js
  3. 4 4
      src/converse-notification.js
  4. 57 36
      src/utils.js
  5. 1 1
      tests/mock.js

+ 1 - 1
docs/CHANGES.md

@@ -10,7 +10,7 @@
 - eslint 3.19.0
 
 - #842 Persistent muc room creation not working [jcbrand]
-
+- #849 `TypeError: _converse.i18n.locale_data is undefined` when reconnecting. [jcbrand]
 
 ## 3.0.1 (2017-04-04)
 

+ 13 - 26
src/converse-core.js

@@ -10,7 +10,6 @@
             "jquery-private",
             "lodash",
             "polyfill",
-            "locales",
             "utils",
             "moment_with_locales",
             "strophe",
@@ -19,7 +18,7 @@
             "backbone.browserStorage",
             "backbone.overview",
     ], factory);
-}(this, function (sizzle, $, _, polyfill, locales, utils, moment, Strophe, pluggable) {
+}(this, function (sizzle, $, _, polyfill, utils, moment, Strophe, pluggable) {
     /* Cannot use this due to Safari bug.
      * See https://github.com/jcbrand/converse.js/issues/196
      */
@@ -194,6 +193,16 @@
             'INACTIVE':   90000
         };
 
+        // Internationalization
+        this.locale = utils.getLocale(settings.i18n, utils.isConverseLocale);
+        if (!moment.locale) {
+            //moment.lang is deprecated after 2.8.1, use moment.locale instead
+            moment.locale = moment.lang;
+        }
+        moment.locale(utils.getLocale(settings.i18n, utils.isMomentLocale));
+        var __ = _converse.__ = utils.__.bind(_converse);
+        _converse.___ = utils.___;
+
         // XEP-0085 Chat states
         // http://xmpp.org/extensions/xep-0085.html
         this.INACTIVE = 'inactive';
@@ -202,28 +211,6 @@
         this.PAUSED = 'paused';
         this.GONE = 'gone';
 
-        // Detect support for the user's locale
-        // ------------------------------------
-        locales = _.isUndefined(locales) ? {} : locales;
-        this.isConverseLocale = function (locale) {
-            return !_.isUndefined(locales[locale]);
-        };
-        this.isMomentLocale = function (locale) { return moment.locale() !== moment.locale(locale); };
-        if (!moment.locale) { //moment.lang is deprecated after 2.8.1, use moment.locale instead
-            moment.locale = moment.lang;
-        }
-        moment.locale(utils.detectLocale(this.isMomentLocale));
-        if (_.includes(_.keys(locales), settings.i18n)) {
-            settings.i18n = locales[settings.i18n];
-        }
-        this.i18n = settings.i18n ? settings.i18n : locales[utils.detectLocale(this.isConverseLocale)] || {};
-
-        // Translation machinery
-        // ---------------------
-        var __ = _converse.__ = utils.__.bind(_converse);
-        _converse.___ = utils.___;
-        var DESC_GROUP_TOGGLE = __('Click to hide these contacts');
-
         // Default configuration values
         // ----------------------------
         this.default_settings = {
@@ -260,6 +247,7 @@
             rid: undefined,
             roster_groups: true,
             show_only_online_users: false,
+            show_send_button: false,
             sid: undefined,
             storage: 'session',
             strict_plugin_dependencies: false,
@@ -268,7 +256,6 @@
             whitelisted_plugins: [],
             xhr_custom_status: false,
             xhr_custom_status_url: '',
-            show_send_button: false
         };
         _.assignIn(this, this.default_settings);
         // Allow only whitelisted configuration attributes to be overwritten
@@ -1310,7 +1297,7 @@
         this.RosterGroup = Backbone.Model.extend({
             initialize: function (attributes) {
                 this.set(_.assignIn({
-                    description: DESC_GROUP_TOGGLE,
+                    description: __('Click to hide these contacts'),
                     state: _converse.OPENED
                 }, attributes));
                 // Collection of contacts belonging to this group.

+ 4 - 4
src/converse-notification.js

@@ -163,7 +163,7 @@
                 }
                 var n = new Notification(title, {
                         body: message.querySelector('body').textContent,
-                        lang: _.isEmpty(converse.i18n) ? 'en' : _converse.i18n.locale_data.converse[""].lang,
+                        lang: _converse.locale,
                         icon: _converse.notification_icon
                     });
                 setTimeout(n.close.bind(n), 5000);
@@ -193,7 +193,7 @@
                 }
                 var n = new Notification(contact.fullname, {
                         body: message,
-                        lang: _converse.i18n.locale_data.converse[""].lang,
+                        lang: _converse.locale,
                         icon: _converse.notification_icon
                     });
                 setTimeout(n.close.bind(n), 5000);
@@ -202,7 +202,7 @@
             _converse.showContactRequestNotification = function (contact) {
                 var n = new Notification(contact.fullname, {
                         body: __('wants to be your contact'),
-                        lang: _converse.i18n.locale_data.converse[""].lang,
+                        lang: _converse.locale,
                         icon: _converse.notification_icon
                     });
                 setTimeout(n.close.bind(n), 5000);
@@ -212,7 +212,7 @@
                 if (data.klass === 'error' || data.klass === 'warn') {
                     var n = new Notification(data.subject, {
                             body: data.message,
-                            lang: _converse.i18n.locale_data.converse[""].lang,
+                            lang: _converse.locale,
                             icon: _converse.notification_icon
                         });
                     setTimeout(n.close.bind(n), 5000);

+ 57 - 36
src/utils.js

@@ -4,6 +4,8 @@
         "jquery-private",
         "jquery.browser",
         "lodash",
+        "locales",
+        "moment_with_locales",
         "tpl!field",
         "tpl!select_option",
         "tpl!form_select",
@@ -14,7 +16,7 @@
         "tpl!form_captcha"
     ], factory);
 }(this, function (
-        $, dummy, _,
+        $, dummy, _, locales, moment,
         tpl_field,
         tpl_select_option,
         tpl_form_select,
@@ -156,15 +158,11 @@
         // Translation machinery
         // ---------------------
         __: function (str) {
-            if (typeof Jed === "undefined" || _.isUndefined(this.i18n) || this.i18n === 'en') {
+            if (typeof Jed === "undefined" || !utils.isConverseLocale(this.locale) || this.locale === 'en') {
                 return str;
             }
-            // Translation factory
-            if (typeof this.i18n === "string") {
-                this.i18n = window.JSON.parse(this.i18n);
-            }
             if (typeof this.jed === "undefined") {
-                this.jed = new Jed(this.i18n);
+                this.jed = new Jed(window.JSON.parse(locales[this.locale]));
             }
             var t = this.jed.translate(str);
             if (arguments.length>1) {
@@ -201,34 +199,6 @@
             }
         },
 
-        detectLocale: function (library_check) {
-            /* Determine which locale is supported by the user's system as well
-             * as by the relevant library (e.g. converse.js or moment.js).
-             *
-             * Parameters:
-             *      (Function) library_check - returns a boolean indicating whether the locale is supported
-             */
-            var locale, i;
-            if (window.navigator.userLanguage) {
-                locale = utils.isLocaleAvailable(window.navigator.userLanguage, library_check);
-            }
-            if (window.navigator.languages && !locale) {
-                for (i=0; i<window.navigator.languages.length && !locale; i++) {
-                    locale = utils.isLocaleAvailable(window.navigator.languages[i], library_check);
-                }
-            }
-            if (window.navigator.browserLanguage && !locale) {
-                locale = utils.isLocaleAvailable(window.navigator.browserLanguage, library_check);
-            }
-            if (window.navigator.language && !locale) {
-                locale = utils.isLocaleAvailable(window.navigator.language, library_check);
-            }
-            if (window.navigator.systemLanguage && !locale) {
-                locale = utils.isLocaleAvailable(window.navigator.systemLanguage, library_check);
-            }
-            return locale || 'en';
-        },
-
         fadeIn: function (el, callback) {
             if ($.fx.off) {
                 el.classList.remove('hidden');
@@ -446,13 +416,64 @@
         }
     };
 
+    utils.detectLocale = function (library_check) {
+        /* Determine which locale is supported by the user's system as well
+         * as by the relevant library (e.g. converse.js or moment.js).
+         *
+         * Parameters:
+         *      (Function) library_check - returns a boolean indicating whether
+         *          the locale is supported.
+         */
+        var locale, i;
+        if (window.navigator.userLanguage) {
+            locale = utils.isLocaleAvailable(window.navigator.userLanguage, library_check);
+        }
+        if (window.navigator.languages && !locale) {
+            for (i=0; i<window.navigator.languages.length && !locale; i++) {
+                locale = utils.isLocaleAvailable(window.navigator.languages[i], library_check);
+            }
+        }
+        if (window.navigator.browserLanguage && !locale) {
+            locale = utils.isLocaleAvailable(window.navigator.browserLanguage, library_check);
+        }
+        if (window.navigator.language && !locale) {
+            locale = utils.isLocaleAvailable(window.navigator.language, library_check);
+        }
+        if (window.navigator.systemLanguage && !locale) {
+            locale = utils.isLocaleAvailable(window.navigator.systemLanguage, library_check);
+        }
+        return locale || 'en';
+    };
+
+    utils.isConverseLocale = function (locale) {
+        if (!_.isString(locale)) { return false; }
+        return _.includes(_.keys(locales || {}), locale)
+    };
+
+    utils.isMomentLocale  = function (locale) {
+        if (!_.isString(locale)) { return false; }
+        return moment.locale() !== moment.locale(locale);
+    }
+
+    utils.getLocale = function (preferred_locale, isSupportedByLibrary) {
+        if (isSupportedByLibrary(preferred_locale)) {
+            return preferred_locale;
+        } else if (_.isObject(preferred_locale)) {
+            try {
+                return preferred_locale.locale_data.converse[""].lang;
+            } catch (e) {
+                console.log(e);
+            }
+        }
+        return utils.detectLocale(isSupportedByLibrary) || 'en';
+    };
+
     utils.contains.not = function (attr, query) {
         return function (item) {
             return !(utils.contains(attr, query)(item));
         };
     };
 
-
     utils.createElementsFromString = function (element, html) {
         // http://stackoverflow.com/questions/9334645/create-node-from-markup-string
         var frag = document.createDocumentFragment(),

+ 1 - 1
tests/mock.js

@@ -80,7 +80,7 @@
         window.localStorage.clear();
         window.sessionStorage.clear();
         var converse = converse_api.initialize(_.extend({
-            i18n: window.locales.en,
+            i18n: 'en',
             auto_subscribe: false,
             bosh_service_url: 'localhost',
             connection: mock.mock_connection(),