Bladeren bron

Merge branch 'split-muc' into bootstrap4

JC Brand 7 jaren geleden
bovenliggende
commit
d4d3d4c838
64 gewijzigde bestanden met toevoegingen van 8936 en 5435 verwijderingen
  1. 18 5
      CHANGES.md
  2. 1 1
      COPYRIGHT
  3. 1 1
      Makefile
  4. 2 2
      css/converse.css
  5. 2 2
      css/fonts.css
  6. 2 2
      css/inverse.css
  7. 275 33
      dist/converse-muc-embedded.js
  8. 333 76
      dist/converse-no-dependencies.js
  9. 333 76
      dist/converse.js
  10. 2 2
      docs/source/conf.py
  11. 2 2
      docs/source/quickstart.rst
  12. 0 3
      index.html
  13. 2 2
      inverse.html
  14. 217 217
      locale/af/LC_MESSAGES/converse.po
  15. 0 0
      locale/bg/LC_MESSAGES/converse.json
  16. 1343 0
      locale/bg/LC_MESSAGES/converse.po
  17. 235 235
      locale/ca/LC_MESSAGES/converse.po
  18. 283 283
      locale/converse.pot
  19. 0 0
      locale/de/LC_MESSAGES/converse.json
  20. 247 249
      locale/de/LC_MESSAGES/converse.po
  21. 282 282
      locale/es/LC_MESSAGES/converse.po
  22. 0 0
      locale/fr/LC_MESSAGES/converse.json
  23. 245 249
      locale/fr/LC_MESSAGES/converse.po
  24. 282 282
      locale/he/LC_MESSAGES/converse.po
  25. 282 282
      locale/hu/LC_MESSAGES/converse.po
  26. 282 282
      locale/id/LC_MESSAGES/converse.po
  27. 260 260
      locale/it/LC_MESSAGES/converse.po
  28. 235 235
      locale/ja/LC_MESSAGES/converse.po
  29. 0 0
      locale/nb/LC_MESSAGES/converse.json
  30. 239 239
      locale/nb/LC_MESSAGES/converse.po
  31. 0 0
      locale/nl/LC_MESSAGES/converse.json
  32. 244 248
      locale/nl/LC_MESSAGES/converse.po
  33. 235 235
      locale/pl/LC_MESSAGES/converse.po
  34. 235 235
      locale/pt_BR/LC_MESSAGES/converse.po
  35. 235 235
      locale/ru/LC_MESSAGES/converse.po
  36. 0 0
      locale/tr/LC_MESSAGES/converse.json
  37. 1333 0
      locale/tr/LC_MESSAGES/converse.po
  38. 235 235
      locale/uk/LC_MESSAGES/converse.po
  39. 0 0
      locale/zh_CN/LC_MESSAGES/converse.json
  40. 292 292
      locale/zh_CN/LC_MESSAGES/converse.po
  41. 282 282
      locale/zh_TW/LC_MESSAGES/converse.po
  42. 334 325
      package-lock.json
  43. 4 2
      package.json
  44. 1 1
      sass/_fonts.scss
  45. 26 12
      spec/chatroom.js
  46. 27 0
      spec/presence.js
  47. 2 2
      src/converse-bookmarks.js
  48. 1 0
      src/converse-chatview.js
  49. 8 7
      src/converse-core.js
  50. 2 1
      src/converse-disco.js
  51. 1 1
      src/converse-fullscreen.js
  52. 1 1
      src/converse-mam.js
  53. 1 1
      src/converse-minimize.js
  54. 4 2
      src/converse-muc-views.js
  55. 2 3
      src/converse-muc.js
  56. 1 3
      src/converse-otr.js
  57. 1 1
      src/converse-roomslist.js
  58. 1 0
      src/converse.js
  59. 2 0
      src/i18n.js
  60. 11 0
      src/polyfill.js
  61. 1 1
      src/start.frag
  62. 1 1
      src/templates/chatroom_features.html
  63. 1 0
      src/templates/toolbar_otr.html
  64. 7 7
      tests/transpiled.html

+ 18 - 5
CHANGES.md

@@ -19,13 +19,26 @@ with regards to sponsoring development on reintroducing them.
 * Removed the `xhr_user_search` and `xhr_user_search_url` configuration options.
 
 
-## 3.3.4 (Unreleased)
+## 3.3.4 (2018-03-05)
 
-- Avoid `eval` (via `_.template` from lodash).
-- Bugfix. Avatars weren't being shown.
-- Bugfix. Bookmarks list and open rooms list weren't recreated after logging in for a 2nd time (without reloading the browser).
 - Don't show bookmark toggles when PEP bookmarking not supported by the XMPP server.
-- Add LibreJS support
+- Emojis are now sent in unicode instead of short names (also in MUCs)
+
+### Bugfixes
+
+- Server field in `Rooms` tab showed MUC supporting clients instead of only components.
+- Avatars weren't being shown.
+- Bookmarks list and open rooms list weren't recreated after logging in for a 2nd time (without reloading the browser).
+- #1022 Status message not sent out on subsequent presences
+- #1024 null reference on MUC Invite
+- #1025 OTR lock icon disappears
+- #1027 `new Event` not supported in IE11
+- #1028 Avoid `eval` (crept in via `_.template` from lodash).
+
+### Translation changes
+
+- New locale: Bulgarian
+- Updated German, Russian, Chinese (traditional), Norwegian Bokmål and French translations.
 
 ## 3.3.3 (2018-02-14)
 

+ 1 - 1
COPYRIGHT

@@ -2,7 +2,7 @@
  *
  *  An XMPP chat client that runs in the browser.
  *
- *  Version: 3.3.3
+ *  Version: 3.3.4
  *
  *  Copyright: JC Brand 2012-2017
  *  Except for 3rd party dependencies.

+ 1 - 1
Makefile

@@ -72,7 +72,7 @@ serve_bg: dev
 ########################################################################
 ## Translation machinery
 
-GETTEXT = xgettext --language="JavaScript" --keyword=__ --keyword=___ --from-code=UTF-8 --output=locale/converse.pot dist/converse-no-dependencies.js --package-name=Converse.js --copyright-holder="Jan-Carel Brand" --package-version=3.3.3 -c
+GETTEXT = xgettext --language="JavaScript" --keyword=__ --keyword=___ --from-code=UTF-8 --output=locale/converse.pot dist/converse-no-dependencies.js --package-name=Converse.js --copyright-holder="Jan-Carel Brand" --package-version=3.3.4 -c
 
 .PHONY: pot
 pot: dist/converse-no-dependencies.js

+ 2 - 2
css/converse.css

@@ -149,8 +149,8 @@
 #converse-embedded-chat .icon-legal:before,
 #conversejs .icon-legal:before {
   content: "\f0e3"; }
-#converse-embedded-chat .icon-lock-2:before,
-#conversejs .icon-lock-2:before {
+#converse-embedded-chat .icon-lock:before,
+#conversejs .icon-lock:before {
   content: "\e027"; }
 #converse-embedded-chat .icon-minus:before,
 #conversejs .icon-minus:before {

+ 2 - 2
css/fonts.css

@@ -142,8 +142,8 @@
 #converse-embedded-chat .icon-legal:before,
 #conversejs .icon-legal:before {
   content: "\f0e3"; }
-#converse-embedded-chat .icon-lock-2:before,
-#conversejs .icon-lock-2:before {
+#converse-embedded-chat .icon-lock:before,
+#conversejs .icon-lock:before {
   content: "\e027"; }
 #converse-embedded-chat .icon-minus:before,
 #conversejs .icon-minus:before {

+ 2 - 2
css/inverse.css

@@ -149,8 +149,8 @@
 #converse-embedded-chat .icon-legal:before,
 #conversejs .icon-legal:before {
   content: "\f0e3"; }
-#converse-embedded-chat .icon-lock-2:before,
-#conversejs .icon-lock-2:before {
+#converse-embedded-chat .icon-lock:before,
+#conversejs .icon-lock:before {
   content: "\e027"; }
 #converse-embedded-chat .icon-minus:before,
 #conversejs .icon-minus:before {

+ 275 - 33
dist/converse-muc-embedded.js

@@ -2,7 +2,7 @@
  *
  *  An XMPP chat client that runs in the browser.
  *
- *  Version: 3.3.3
+ *  Version: 3.3.4
  */
 
 /* jshint ignore:start */
@@ -22063,6 +22063,17 @@ define('lodash.fp',['lodash', 'lodash.converter'], function (_, lodashConverter)
     return fp;
 });
 
+function CustomEvent ( event, params ) {
+    params = params || { bubbles: false, cancelable: false, detail: undefined };
+    var evt = document.createEvent( 'CustomEvent' );
+    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+    return evt;
+}
+if ( typeof window.CustomEvent !== "function" ) {
+    CustomEvent.prototype = window.Event.prototype;
+    window.CustomEvent = CustomEvent;
+}
+
 if (!String.prototype.includes) {
   String.prototype.includes = function(search, start) {
         'use strict';
@@ -27679,6 +27690,97 @@ return af;
 
 })));
 
+//! moment.js locale configuration
+//! locale : Bulgarian [bg]
+//! author : Krasen Borisov : https://github.com/kraz
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define('moment/locale/bg',['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var bg = moment.defineLocale('bg', {
+    months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+    monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+    weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+    weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+    weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+    longDateFormat : {
+        LT : 'H:mm',
+        LTS : 'H:mm:ss',
+        L : 'D.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY H:mm',
+        LLLL : 'dddd, D MMMM YYYY H:mm'
+    },
+    calendar : {
+        sameDay : '[Днес в] LT',
+        nextDay : '[Утре в] LT',
+        nextWeek : 'dddd [в] LT',
+        lastDay : '[Вчера в] LT',
+        lastWeek : function () {
+            switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
+            }
+        },
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'след %s',
+        past : 'преди %s',
+        s : 'няколко секунди',
+        m : 'минута',
+        mm : '%d минути',
+        h : 'час',
+        hh : '%d часа',
+        d : 'ден',
+        dd : '%d дни',
+        M : 'месец',
+        MM : '%d месеца',
+        y : 'година',
+        yy : '%d години'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+    ordinal : function (number) {
+        var lastDigit = number % 10,
+            last2Digits = number % 100;
+        if (number === 0) {
+            return number + '-ев';
+        } else if (last2Digits === 0) {
+            return number + '-ен';
+        } else if (last2Digits > 10 && last2Digits < 20) {
+            return number + '-ти';
+        } else if (lastDigit === 1) {
+            return number + '-ви';
+        } else if (lastDigit === 2) {
+            return number + '-ри';
+        } else if (lastDigit === 7 || lastDigit === 8) {
+            return number + '-ми';
+        } else {
+            return number + '-ти';
+        }
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
+
+return bg;
+
+})));
+
 //! moment.js locale configuration
 //! locale : Catalan [ca]
 //! author : Juan G. Hurtado : https://github.com/juanghurtado
@@ -28968,6 +29070,97 @@ return ru;
 
 })));
 
+//! moment.js locale configuration
+//! locale : Turkish [tr]
+//! authors : Erhan Gundogan : https://github.com/erhangundogan,
+//!           Burak Yiğit Kaya: https://github.com/BYK
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define('moment/locale/tr',['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+    1: '\'inci',
+    5: '\'inci',
+    8: '\'inci',
+    70: '\'inci',
+    80: '\'inci',
+    2: '\'nci',
+    7: '\'nci',
+    20: '\'nci',
+    50: '\'nci',
+    3: '\'üncü',
+    4: '\'üncü',
+    100: '\'üncü',
+    6: '\'ncı',
+    9: '\'uncu',
+    10: '\'uncu',
+    30: '\'uncu',
+    60: '\'ıncı',
+    90: '\'ıncı'
+};
+
+var tr = moment.defineLocale('tr', {
+    months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+    monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+    weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+    weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+    weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd, D MMMM YYYY HH:mm'
+    },
+    calendar : {
+        sameDay : '[bugün saat] LT',
+        nextDay : '[yarın saat] LT',
+        nextWeek : '[haftaya] dddd [saat] LT',
+        lastDay : '[dün] LT',
+        lastWeek : '[geçen hafta] dddd [saat] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s sonra',
+        past : '%s önce',
+        s : 'birkaç saniye',
+        m : 'bir dakika',
+        mm : '%d dakika',
+        h : 'bir saat',
+        hh : '%d saat',
+        d : 'bir gün',
+        dd : '%d gün',
+        M : 'bir ay',
+        MM : '%d ay',
+        y : 'bir yıl',
+        yy : '%d yıl'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
+    ordinal : function (number) {
+        if (number === 0) {  // special case for zero
+            return number + '\'ıncı';
+        }
+        var a = number % 10,
+            b = number % 100 - a,
+            c = number >= 100 ? 100 : null;
+        return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
+
+return tr;
+
+})));
+
 //! moment.js locale configuration
 //! locale : Ukrainian [uk]
 //! author : zemlanin : https://github.com/zemlanin
@@ -29348,7 +29541,7 @@ return zhTw;
 
 /*global define */
 (function (root, factory) {
-  define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
+  define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/bg', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/tr', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
 })(this, function (Promise, Jed, _, moment) {
   'use strict';
 
@@ -36494,6 +36687,42 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     return promise;
   };
 
+  u.interpolate = function (string, o) {
+    return string.replace(/{{{([^{}]*)}}}/g, function (a, b) {
+      var r = o[b];
+      return typeof r === 'string' || typeof r === 'number' ? r : a;
+    });
+  };
+
+  u.onMultipleEvents = function () {
+    var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
+    var callback = arguments.length > 1 ? arguments[1] : undefined;
+
+    /* Call the callback once all the events have been triggered
+     *
+     * Parameters:
+     *  (Array) events: An array of objects, with keys `object` and
+     *      `event`, representing the event name and the object it's
+     *      triggered upon.
+     *  (Function) callback: The function to call once all events have
+     *      been triggered.
+     */
+    var triggered = [];
+
+    function handler(result) {
+      triggered.push(result);
+
+      if (events.length === triggered.length) {
+        callback(triggered);
+        triggered = [];
+      }
+    }
+
+    _.each(events, function (map) {
+      return map.object.on(map.event, handler);
+    });
+  };
+
   u.safeSave = function (model, attributes) {
     if (u.isPersistableModel(model)) {
       model.save(attributes);
@@ -36503,7 +36732,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
   };
 
   u.isVisible = function (el) {
-    // XXX: Taken from jQuery's "visible" implementation
+    if (u.hasClass('hidden', el)) {
+      return false;
+    } // XXX: Taken from jQuery's "visible" implementation
+
+
     return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
   };
 
@@ -39196,7 +39429,7 @@ return Backbone.BrowserStorage;
 /*global Backbone, define, window, JSON */
 (function (root, factory) {
   define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory);
-})(this, function (sizzle, Promise, _, f, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {
+})(this, function (sizzle, Promise, _, f, polyfill, i18n, u, moment, Strophe, pluggable, Backbone) {
   /* Cannot use this due to Safari bug.
    * See https://github.com/jcbrand/converse.js/issues/196
    */
@@ -39368,7 +39601,7 @@ return Backbone.BrowserStorage;
     /* Private function, used to add a new promise to the ones already
      * available via the `waitUntil` api method.
      */
-    _converse.promises[promise] = utils.getResolveablePromise();
+    _converse.promises[promise] = u.getResolveablePromise();
   }
 
   _converse.emit = function (name) {
@@ -39390,7 +39623,7 @@ return Backbone.BrowserStorage;
     var _this = this;
 
     settings = !_.isUndefined(settings) ? settings : {};
-    var init_promise = utils.getResolveablePromise();
+    var init_promise = u.getResolveablePromise();
 
     _.each(PROMISES, addPromise);
 
@@ -39474,7 +39707,7 @@ return Backbone.BrowserStorage;
       jid: undefined,
       keepalive: true,
       locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
-      locales: ['af', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'uk', 'zh_CN', 'zh_TW'],
+      locales: ['af', 'bg', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'],
       message_carbons: true,
       message_storage: 'session',
       password: undefined,
@@ -39821,7 +40054,7 @@ return Backbone.BrowserStorage;
 
     this.initStatus = function () {
       return new Promise(function (resolve, reject) {
-        var promise = new utils.getResolveablePromise();
+        var promise = new u.getResolveablePromise();
         _this.xmppstatus = new _this.XMPPStatus();
         var id = b64_sha1("converse.xmppstatus-".concat(_converse.bare_jid));
         _this.xmppstatus.id = id; // Appears to be necessary for backbone.browserStorage
@@ -39866,7 +40099,10 @@ return Backbone.BrowserStorage;
         _converse.connection.disconnect();
       } else {
         _converse._tearDown();
-      }
+      } // Recreate all the promises
+
+
+      _.each(_.keys(_converse.promises), addPromise);
 
       _converse.emit('logout');
     };
@@ -40117,9 +40353,9 @@ return Backbone.BrowserStorage;
       initialize: function initialize(attributes) {
         var _this3 = this;
 
-        var jid = attributes.jid;
-        var bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
-        var resource = Strophe.getResourceFromJid(jid);
+        var jid = attributes.jid,
+            bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase(),
+            resource = Strophe.getResourceFromJid(jid);
         attributes.jid = bare_jid;
         this.set(_.assignIn({
           'fullname': bare_jid,
@@ -40392,7 +40628,7 @@ return Backbone.BrowserStorage;
         return true;
       },
       isSelf: function isSelf(jid) {
-        return utils.isSameBareJID(jid, _converse.connection.jid);
+        return u.isSameBareJID(jid, _converse.connection.jid);
       },
       addAndSubscribe: function addAndSubscribe(jid, name, groups, message, attributes) {
         /* Add a roster contact and then once we have confirmation from
@@ -40796,7 +41032,7 @@ return Backbone.BrowserStorage;
       constructPresence: function constructPresence(type, status_message) {
         var presence;
         type = _.isString(type) ? type : this.get('status') || _converse.default_state;
-        status_message = _.isString(status_message) ? status_message : undefined; // Most of these presence types are actually not explicitly sent,
+        status_message = _.isString(status_message) ? status_message : this.get('status_message'); // Most of these presence types are actually not explicitly sent,
         // but I add all of them here for reference and future proofing.
 
         if (type === 'unavailable' || type === 'probe' || type === 'error' || type === 'unsubscribe' || type === 'unsubscribed' || type === 'subscribe' || type === 'subscribed') {
@@ -41165,7 +41401,7 @@ return Backbone.BrowserStorage;
     } else if (_.isUndefined(i18n)) {
       finishInitialization();
     } else {
-      i18n.fetchTranslations(_converse.locale, _converse.locales, _.template(_converse.locales_url)({
+      i18n.fetchTranslations(_converse.locale, _converse.locales, u.interpolate(_converse.locales_url, {
         'locale': _converse.locale
       })).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(finishInitialization).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
     }
@@ -41233,9 +41469,9 @@ return Backbone.BrowserStorage;
     },
     'settings': {
       'update': function update(settings) {
-        utils.merge(_converse.default_settings, settings);
-        utils.merge(_converse, settings);
-        utils.applyUserSettings(_converse, settings, _converse.user_settings);
+        u.merge(_converse.default_settings, settings);
+        u.merge(_converse, settings);
+        u.applyUserSettings(_converse, settings, _converse.user_settings);
       },
       'get': function get(key) {
         if (_.includes(_.keys(_converse.default_settings), key)) {
@@ -41359,10 +41595,10 @@ return Backbone.BrowserStorage;
       'b64_sha1': b64_sha1,
       'moment': moment,
       'sizzle': sizzle,
-      'utils': utils
+      'utils': u
     }
   };
-  window.dispatchEvent(new Event('converse-loaded'));
+  window.dispatchEvent(new CustomEvent('converse-loaded'));
   return window.converse;
 });
 //# sourceMappingURL=converse-core.js.map;
@@ -41617,6 +41853,7 @@ return Backbone.BrowserStorage;
       _converse.ChatBox = Backbone.Model.extend({
         defaults: {
           'type': 'chatbox',
+          'show_avatar': true,
           'bookmarked': false,
           'chat_state': undefined,
           'num_unread': 0,
@@ -44470,9 +44707,9 @@ __e(o.avatar_height) +
 'px" width="' +
 __e(o.avatar_width) +
 'px"\n            src="data:' +
-__e(o.image_type) +
+__e(o.image_type || o._converse.DEFAULT_IMAGE_TYPE) +
 ';base64,' +
-__e(o.image) +
+__e(o.image || o._converse.DEFAULT_IMAGE) +
 '"/>\n    ';
  } ;
 __p += '\n    <div class="chat-title">\n        ';
@@ -44938,6 +45175,7 @@ return __p
         },
         render: function render() {
           this.el.innerHTML = tpl_chatbox_head(_.extend(this.model.toJSON(), {
+            '_converse': _converse,
             'avatar_width': _converse.chatview_avatar_width,
             'avatar_height': _converse.chatview_avatar_height,
             'info_close': __('Close this chat box')
@@ -46266,7 +46504,7 @@ Strophe.addConnectionPlugin('disco',
           this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
           this.features = new Backbone.Collection();
           this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.features-".concat(this.get('jid'))));
-          this.features.on('add', this.onFeatureAdded);
+          this.features.on('add', this.onFeatureAdded, this);
           this.identities = new Backbone.Collection();
           this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.identities-".concat(this.get('jid'))));
           this.fetchFeatures();
@@ -46323,6 +46561,8 @@ Strophe.addConnectionPlugin('disco',
           });
         },
         onFeatureAdded: function onFeatureAdded(feature) {
+          feature.entity = this;
+
           _converse.emit('serviceDiscovered', feature);
         },
         fetchFeatures: function fetchFeatures() {
@@ -47531,7 +47771,7 @@ __p += '\n<ul class="features-list">\n';
  if (o.passwordprotected) { ;
 __p += '\n<li class="feature" title="' +
 __e( o.tt_passwordprotected ) +
-'"><span class="icon-lock-2"></span>' +
+'"><span class="icon-lock"></span>' +
 __e( o.label_passwordprotected ) +
 '</li>\n';
  } ;
@@ -49598,8 +49838,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
  * specified in XEP-0045 Multi-user chat.
  */
 (function (root, factory) {
-  define('converse-muc',["form-utils", "converse-core", "lodash.fp", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_join_form", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!rooms_results", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
-})(this, function (u, converse, fp, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_join_form, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) {
+  define('converse-muc',["form-utils", "converse-core", "emojione", "lodash.fp", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_join_form", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!rooms_results", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
+})(this, function (u, converse, emojione, f, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_join_form, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) {
   "use strict";
 
   var ROOMS_PANEL_ID = 'chatrooms';
@@ -50526,6 +50766,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
            * Parameters:
            *  (String) text: The message text to be sent.
            */
+          text = emojione.shortnameToUnicode(text);
+
           var msgid = _converse.connection.getUniqueId();
 
           var msg = $msg({
@@ -52255,11 +52497,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
         renderTab: function renderTab() {
           var controlbox = _converse.chatboxes.get('controlbox');
 
-          var chatrooms = fp.filter(_.partial(u.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
+          var chatrooms = f.filter(_.partial(u.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
           this.tab_el.innerHTML = tpl_chatrooms_tab({
             'label_rooms': __('Rooms'),
             'is_current': controlbox.get('active-panel') === ROOMS_PANEL_ID,
-            'num_unread': fp.sum(fp.map(fp.curry(u.getAttribute)('num_unread'), chatrooms))
+            'num_unread': f.sum(f.map(f.curry(u.getAttribute)('num_unread'), chatrooms))
           });
         },
         insertIntoDOM: function insertIntoDOM() {
@@ -52491,7 +52733,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
          *  (XMLElement) message: The message stanza containing the
          *        invitation.
          */
-        var x_el = message.querySelector('x[xmlns="jabber:x:conference"]'),
+        var x_el = sizzle('x[xmlns="jabber:x:conference"]', message).pop(),
             from = Strophe.getBareJidFromJid(message.getAttribute('from')),
             room_jid = x_el.getAttribute('jid'),
             reason = x_el.getAttribute('reason');
@@ -52695,11 +52937,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
 
       function setMUCDomainFromDisco(controlboxview) {
         /* Check whether service discovery for the user's domain
-            * returned MUC information and use that to automatically
-            * set the MUC domain for the "Rooms" panel of the controlbox.
-            */
+         * returned MUC information and use that to automatically
+         * set the MUC domain for the "Rooms" panel of the controlbox.
+         */
         function featureAdded(feature) {
-          if (feature.get('var') === Strophe.NS.MUC) {
+          if (feature.get('var') === Strophe.NS.MUC && f.includes('conference', feature.entity.identities.pluck('category'))) {
             setMUCDomain(feature.get('from'), controlboxview);
           }
         }

+ 333 - 76
dist/converse-no-dependencies.js

@@ -2,7 +2,7 @@
  *
  *  An XMPP chat client that runs in the browser.
  *
- *  Version: 3.3.3
+ *  Version: 3.3.4
  */
 
 /* jshint ignore:start */
@@ -2735,6 +2735,17 @@ define('lodash.fp',['lodash', 'lodash.converter'], function (_, lodashConverter)
     return fp;
 });
 
+function CustomEvent ( event, params ) {
+    params = params || { bubbles: false, cancelable: false, detail: undefined };
+    var evt = document.createEvent( 'CustomEvent' );
+    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+    return evt;
+}
+if ( typeof window.CustomEvent !== "function" ) {
+    CustomEvent.prototype = window.Event.prototype;
+    window.CustomEvent = CustomEvent;
+}
+
 if (!String.prototype.includes) {
   String.prototype.includes = function(search, start) {
         'use strict';
@@ -3885,6 +3896,97 @@ return af;
 
 })));
 
+//! moment.js locale configuration
+//! locale : Bulgarian [bg]
+//! author : Krasen Borisov : https://github.com/kraz
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define('moment/locale/bg',['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var bg = moment.defineLocale('bg', {
+    months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+    monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+    weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+    weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+    weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+    longDateFormat : {
+        LT : 'H:mm',
+        LTS : 'H:mm:ss',
+        L : 'D.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY H:mm',
+        LLLL : 'dddd, D MMMM YYYY H:mm'
+    },
+    calendar : {
+        sameDay : '[Днес в] LT',
+        nextDay : '[Утре в] LT',
+        nextWeek : 'dddd [в] LT',
+        lastDay : '[Вчера в] LT',
+        lastWeek : function () {
+            switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
+            }
+        },
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'след %s',
+        past : 'преди %s',
+        s : 'няколко секунди',
+        m : 'минута',
+        mm : '%d минути',
+        h : 'час',
+        hh : '%d часа',
+        d : 'ден',
+        dd : '%d дни',
+        M : 'месец',
+        MM : '%d месеца',
+        y : 'година',
+        yy : '%d години'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+    ordinal : function (number) {
+        var lastDigit = number % 10,
+            last2Digits = number % 100;
+        if (number === 0) {
+            return number + '-ев';
+        } else if (last2Digits === 0) {
+            return number + '-ен';
+        } else if (last2Digits > 10 && last2Digits < 20) {
+            return number + '-ти';
+        } else if (lastDigit === 1) {
+            return number + '-ви';
+        } else if (lastDigit === 2) {
+            return number + '-ри';
+        } else if (lastDigit === 7 || lastDigit === 8) {
+            return number + '-ми';
+        } else {
+            return number + '-ти';
+        }
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
+
+return bg;
+
+})));
+
 //! moment.js locale configuration
 //! locale : Catalan [ca]
 //! author : Juan G. Hurtado : https://github.com/juanghurtado
@@ -5174,6 +5276,97 @@ return ru;
 
 })));
 
+//! moment.js locale configuration
+//! locale : Turkish [tr]
+//! authors : Erhan Gundogan : https://github.com/erhangundogan,
+//!           Burak Yiğit Kaya: https://github.com/BYK
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define('moment/locale/tr',['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+    1: '\'inci',
+    5: '\'inci',
+    8: '\'inci',
+    70: '\'inci',
+    80: '\'inci',
+    2: '\'nci',
+    7: '\'nci',
+    20: '\'nci',
+    50: '\'nci',
+    3: '\'üncü',
+    4: '\'üncü',
+    100: '\'üncü',
+    6: '\'ncı',
+    9: '\'uncu',
+    10: '\'uncu',
+    30: '\'uncu',
+    60: '\'ıncı',
+    90: '\'ıncı'
+};
+
+var tr = moment.defineLocale('tr', {
+    months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+    monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+    weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+    weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+    weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd, D MMMM YYYY HH:mm'
+    },
+    calendar : {
+        sameDay : '[bugün saat] LT',
+        nextDay : '[yarın saat] LT',
+        nextWeek : '[haftaya] dddd [saat] LT',
+        lastDay : '[dün] LT',
+        lastWeek : '[geçen hafta] dddd [saat] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s sonra',
+        past : '%s önce',
+        s : 'birkaç saniye',
+        m : 'bir dakika',
+        mm : '%d dakika',
+        h : 'bir saat',
+        hh : '%d saat',
+        d : 'bir gün',
+        dd : '%d gün',
+        M : 'bir ay',
+        MM : '%d ay',
+        y : 'bir yıl',
+        yy : '%d yıl'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
+    ordinal : function (number) {
+        if (number === 0) {  // special case for zero
+            return number + '\'ıncı';
+        }
+        var a = number % 10,
+            b = number % 100 - a,
+            c = number >= 100 ? 100 : null;
+        return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
+
+return tr;
+
+})));
+
 //! moment.js locale configuration
 //! locale : Ukrainian [uk]
 //! author : zemlanin : https://github.com/zemlanin
@@ -5554,7 +5747,7 @@ return zhTw;
 
 /*global define */
 (function (root, factory) {
-  define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
+  define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/bg', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/tr', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
 })(this, function (Promise, Jed, _, moment) {
   'use strict';
 
@@ -6356,6 +6549,42 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     return promise;
   };
 
+  u.interpolate = function (string, o) {
+    return string.replace(/{{{([^{}]*)}}}/g, function (a, b) {
+      var r = o[b];
+      return typeof r === 'string' || typeof r === 'number' ? r : a;
+    });
+  };
+
+  u.onMultipleEvents = function () {
+    var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
+    var callback = arguments.length > 1 ? arguments[1] : undefined;
+
+    /* Call the callback once all the events have been triggered
+     *
+     * Parameters:
+     *  (Array) events: An array of objects, with keys `object` and
+     *      `event`, representing the event name and the object it's
+     *      triggered upon.
+     *  (Function) callback: The function to call once all events have
+     *      been triggered.
+     */
+    var triggered = [];
+
+    function handler(result) {
+      triggered.push(result);
+
+      if (events.length === triggered.length) {
+        callback(triggered);
+        triggered = [];
+      }
+    }
+
+    _.each(events, function (map) {
+      return map.object.on(map.event, handler);
+    });
+  };
+
   u.safeSave = function (model, attributes) {
     if (u.isPersistableModel(model)) {
       model.save(attributes);
@@ -6365,7 +6594,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
   };
 
   u.isVisible = function (el) {
-    // XXX: Taken from jQuery's "visible" implementation
+    if (u.hasClass('hidden', el)) {
+      return false;
+    } // XXX: Taken from jQuery's "visible" implementation
+
+
     return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
   };
 
@@ -6845,7 +7078,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
 /*global Backbone, define, window, JSON */
 (function (root, factory) {
   define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory);
-})(this, function (sizzle, Promise, _, f, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {
+})(this, function (sizzle, Promise, _, f, polyfill, i18n, u, moment, Strophe, pluggable, Backbone) {
   /* Cannot use this due to Safari bug.
    * See https://github.com/jcbrand/converse.js/issues/196
    */
@@ -7017,7 +7250,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     /* Private function, used to add a new promise to the ones already
      * available via the `waitUntil` api method.
      */
-    _converse.promises[promise] = utils.getResolveablePromise();
+    _converse.promises[promise] = u.getResolveablePromise();
   }
 
   _converse.emit = function (name) {
@@ -7039,7 +7272,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     var _this = this;
 
     settings = !_.isUndefined(settings) ? settings : {};
-    var init_promise = utils.getResolveablePromise();
+    var init_promise = u.getResolveablePromise();
 
     _.each(PROMISES, addPromise);
 
@@ -7123,7 +7356,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
       jid: undefined,
       keepalive: true,
       locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
-      locales: ['af', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'uk', 'zh_CN', 'zh_TW'],
+      locales: ['af', 'bg', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'],
       message_carbons: true,
       message_storage: 'session',
       password: undefined,
@@ -7470,7 +7703,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
 
     this.initStatus = function () {
       return new Promise(function (resolve, reject) {
-        var promise = new utils.getResolveablePromise();
+        var promise = new u.getResolveablePromise();
         _this.xmppstatus = new _this.XMPPStatus();
         var id = b64_sha1("converse.xmppstatus-".concat(_converse.bare_jid));
         _this.xmppstatus.id = id; // Appears to be necessary for backbone.browserStorage
@@ -7515,7 +7748,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
         _converse.connection.disconnect();
       } else {
         _converse._tearDown();
-      }
+      } // Recreate all the promises
+
+
+      _.each(_.keys(_converse.promises), addPromise);
 
       _converse.emit('logout');
     };
@@ -7766,9 +8002,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
       initialize: function initialize(attributes) {
         var _this3 = this;
 
-        var jid = attributes.jid;
-        var bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
-        var resource = Strophe.getResourceFromJid(jid);
+        var jid = attributes.jid,
+            bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase(),
+            resource = Strophe.getResourceFromJid(jid);
         attributes.jid = bare_jid;
         this.set(_.assignIn({
           'fullname': bare_jid,
@@ -8041,7 +8277,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
         return true;
       },
       isSelf: function isSelf(jid) {
-        return utils.isSameBareJID(jid, _converse.connection.jid);
+        return u.isSameBareJID(jid, _converse.connection.jid);
       },
       addAndSubscribe: function addAndSubscribe(jid, name, groups, message, attributes) {
         /* Add a roster contact and then once we have confirmation from
@@ -8445,7 +8681,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
       constructPresence: function constructPresence(type, status_message) {
         var presence;
         type = _.isString(type) ? type : this.get('status') || _converse.default_state;
-        status_message = _.isString(status_message) ? status_message : undefined; // Most of these presence types are actually not explicitly sent,
+        status_message = _.isString(status_message) ? status_message : this.get('status_message'); // Most of these presence types are actually not explicitly sent,
         // but I add all of them here for reference and future proofing.
 
         if (type === 'unavailable' || type === 'probe' || type === 'error' || type === 'unsubscribe' || type === 'unsubscribed' || type === 'subscribe' || type === 'subscribed') {
@@ -8814,7 +9050,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     } else if (_.isUndefined(i18n)) {
       finishInitialization();
     } else {
-      i18n.fetchTranslations(_converse.locale, _converse.locales, _.template(_converse.locales_url)({
+      i18n.fetchTranslations(_converse.locale, _converse.locales, u.interpolate(_converse.locales_url, {
         'locale': _converse.locale
       })).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(finishInitialization).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
     }
@@ -8882,9 +9118,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     },
     'settings': {
       'update': function update(settings) {
-        utils.merge(_converse.default_settings, settings);
-        utils.merge(_converse, settings);
-        utils.applyUserSettings(_converse, settings, _converse.user_settings);
+        u.merge(_converse.default_settings, settings);
+        u.merge(_converse, settings);
+        u.applyUserSettings(_converse, settings, _converse.user_settings);
       },
       'get': function get(key) {
         if (_.includes(_.keys(_converse.default_settings), key)) {
@@ -9008,10 +9244,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
       'b64_sha1': b64_sha1,
       'moment': moment,
       'sizzle': sizzle,
-      'utils': utils
+      'utils': u
     }
   };
-  window.dispatchEvent(new Event('converse-loaded'));
+  window.dispatchEvent(new CustomEvent('converse-loaded'));
   return window.converse;
 });
 //# sourceMappingURL=converse-core.js.map;
@@ -9104,6 +9340,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
       _converse.ChatBox = Backbone.Model.extend({
         defaults: {
           'type': 'chatbox',
+          'show_avatar': true,
           'bookmarked': false,
           'chat_state': undefined,
           'num_unread': 0,
@@ -11957,9 +12194,9 @@ __e(o.avatar_height) +
 'px" width="' +
 __e(o.avatar_width) +
 'px"\n            src="data:' +
-__e(o.image_type) +
+__e(o.image_type || o._converse.DEFAULT_IMAGE_TYPE) +
 ';base64,' +
-__e(o.image) +
+__e(o.image || o._converse.DEFAULT_IMAGE) +
 '"/>\n    ';
  } ;
 __p += '\n    <div class="chat-title">\n        ';
@@ -12425,6 +12662,7 @@ return __p
         },
         render: function render() {
           this.el.innerHTML = tpl_chatbox_head(_.extend(this.model.toJSON(), {
+            '_converse': _converse,
             'avatar_width': _converse.chatview_avatar_width,
             'avatar_height': _converse.chatview_avatar_height,
             'info_close': __('Close this chat box')
@@ -15585,7 +15823,7 @@ return __p
             ev.preventDefault();
           }
 
-          var tab = ev.target,
+          var tab = u.hasClass('msgs-indicator', ev.target) ? ev.target.parentNode : ev.target,
               sibling_li = tab.parentNode.nextElementSibling || tab.parentNode.previousElementSibling,
               sibling = sibling_li.firstChild,
               sibling_panel = _converse.root.querySelector(sibling.getAttribute('href')),
@@ -16385,7 +16623,7 @@ __p += '\n<ul class="features-list">\n';
  if (o.passwordprotected) { ;
 __p += '\n<li class="feature" title="' +
 __e( o.tt_passwordprotected ) +
-'"><span class="icon-lock-2"></span>' +
+'"><span class="icon-lock"></span>' +
 __e( o.label_passwordprotected ) +
 '</li>\n';
  } ;
@@ -16904,7 +17142,7 @@ return __p
           this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
           this.features = new Backbone.Collection();
           this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.features-".concat(this.get('jid'))));
-          this.features.on('add', this.onFeatureAdded);
+          this.features.on('add', this.onFeatureAdded, this);
           this.identities = new Backbone.Collection();
           this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.identities-".concat(this.get('jid'))));
           this.fetchFeatures();
@@ -16961,6 +17199,8 @@ return __p
           });
         },
         onFeatureAdded: function onFeatureAdded(feature) {
+          feature.entity = this;
+
           _converse.emit('serviceDiscovered', feature);
         },
         fetchFeatures: function fetchFeatures() {
@@ -18256,8 +18496,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
  * specified in XEP-0045 Multi-user chat.
  */
 (function (root, factory) {
-  define('converse-muc',["form-utils", "converse-core", "lodash.fp", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_join_form", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!rooms_results", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
-})(this, function (u, converse, fp, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_join_form, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) {
+  define('converse-muc',["form-utils", "converse-core", "emojione", "lodash.fp", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_join_form", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!rooms_results", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
+})(this, function (u, converse, emojione, f, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_join_form, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) {
   "use strict";
 
   var ROOMS_PANEL_ID = 'chatrooms';
@@ -19184,6 +19424,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
            * Parameters:
            *  (String) text: The message text to be sent.
            */
+          text = emojione.shortnameToUnicode(text);
+
           var msgid = _converse.connection.getUniqueId();
 
           var msg = $msg({
@@ -20913,11 +21155,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
         renderTab: function renderTab() {
           var controlbox = _converse.chatboxes.get('controlbox');
 
-          var chatrooms = fp.filter(_.partial(u.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
+          var chatrooms = f.filter(_.partial(u.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
           this.tab_el.innerHTML = tpl_chatrooms_tab({
             'label_rooms': __('Rooms'),
             'is_current': controlbox.get('active-panel') === ROOMS_PANEL_ID,
-            'num_unread': fp.sum(fp.map(fp.curry(u.getAttribute)('num_unread'), chatrooms))
+            'num_unread': f.sum(f.map(f.curry(u.getAttribute)('num_unread'), chatrooms))
           });
         },
         insertIntoDOM: function insertIntoDOM() {
@@ -21149,7 +21391,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
          *  (XMLElement) message: The message stanza containing the
          *        invitation.
          */
-        var x_el = message.querySelector('x[xmlns="jabber:x:conference"]'),
+        var x_el = sizzle('x[xmlns="jabber:x:conference"]', message).pop(),
             from = Strophe.getBareJidFromJid(message.getAttribute('from')),
             room_jid = x_el.getAttribute('jid'),
             reason = x_el.getAttribute('reason');
@@ -21353,11 +21595,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
 
       function setMUCDomainFromDisco(controlboxview) {
         /* Check whether service discovery for the user's domain
-            * returned MUC information and use that to automatically
-            * set the MUC domain for the "Rooms" panel of the controlbox.
-            */
+         * returned MUC information and use that to automatically
+         * set the MUC domain for the "Rooms" panel of the controlbox.
+         */
         function featureAdded(feature) {
-          if (feature.get('var') === Strophe.NS.MUC) {
+          if (feature.get('var') === Strophe.NS.MUC && f.includes('conference', feature.entity.identities.pluck('category'))) {
             setMUCDomain(feature.get('from'), controlboxview);
           }
         }
@@ -21594,12 +21836,10 @@ return __p
           var _converse = this.__super__._converse;
 
           if (_converse.allow_bookmarks) {
-            _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid).then(function (identity) {
-              if (_.isNil(identity)) {
-                return;
+            _converse.checkBookmarksSupport().then(function (supported) {
+              if (supported) {
+                _this.renderBookmarkToggle();
               }
-
-              _this.renderBookmarkToggle();
             }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
           }
         },
@@ -22050,38 +22290,42 @@ return __p
         }
       });
 
+      _converse.checkBookmarksSupport = function () {
+        return new Promise(function (resolve, reject) {
+          Promise.all([_converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid)]).then(function (args) {
+            resolve(args[0] && (args[1].supported || _converse.allow_public_bookmarks));
+          }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+        }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+      };
+
       var initBookmarks = function initBookmarks() {
         if (!_converse.allow_bookmarks) {
           return;
         }
 
-        Promise.all([_converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid)]).then(function (args) {
-          var identity = args[0],
-              options_support = args[1];
-
-          if (_.isNil(identity) || !options_support.supported && !_converse.allow_public_bookmarks) {
-            _converse.emit('bookmarksInitialized');
-
-            return;
-          }
-
-          _converse.bookmarks = new _converse.Bookmarks();
-
-          _converse.bookmarks.fetchBookmarks().then(function () {
+        _converse.checkBookmarksSupport().then(function (supported) {
+          if (supported) {
+            _converse.bookmarks = new _converse.Bookmarks();
             _converse.bookmarksview = new _converse.BookmarksView({
               'model': _converse.bookmarks
             });
-          }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)).then(function () {
-            _converse.emit('bookmarksInitialized');
-          });
-        }).catch(function (e) {
-          _converse.log(e, Strophe.LogLevel.ERROR);
 
-          _converse.emit('bookmarksInitialized');
+            _converse.bookmarks.fetchBookmarks().catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(function () {
+              return _converse.emit('bookmarksInitialized');
+            });
+          } else {
+            _converse.emit('bookmarksInitialized');
+          }
         });
       };
 
-      Promise.all([_converse.api.waitUntil('chatBoxesFetched'), _converse.api.waitUntil('roomsPanelRendered')]).then(initBookmarks).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+      u.onMultipleEvents([{
+        'object': _converse,
+        'event': 'chatBoxesFetched'
+      }, {
+        'object': _converse,
+        'event': 'roomsPanelRendered'
+      }], initBookmarks);
 
       _converse.on('connected', function () {
         // Add a handler for bookmarks pushed from other connected clients
@@ -22300,7 +22544,11 @@ return __p
         },
         toHTML: function toHTML() {
           return tpl_rooms_list_item(_.extend(this.model.toJSON(), {
-            'allow_bookmarks': _converse.allow_bookmarks,
+            // XXX: By the time this renders, the _converse.bookmarks
+            // collection should already exist if bookmarks are
+            // supported by the XMPP server. So we can use it
+            // as a check for support (other ways of checking are async).
+            'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
             'info_leave_room': __('Leave this room'),
             'info_remove_bookmark': __('Unbookmark this room'),
             'info_add_bookmark': __('Bookmark this room'),
@@ -22421,13 +22669,26 @@ return __p
         });
       };
 
-      Promise.all([_converse.api.waitUntil('chatBoxesFetched'), _converse.api.waitUntil('roomsPanelRendered')]).then(function () {
-        if (_converse.allow_bookmarks) {
-          _converse.api.waitUntil('bookmarksInitialized').then(initRoomsListView);
-        } else {
-          initRoomsListView();
-        }
-      });
+      if (_converse.allow_bookmarks) {
+        u.onMultipleEvents([{
+          'object': _converse,
+          'event': 'chatBoxesFetched'
+        }, {
+          'object': _converse,
+          'event': 'roomsPanelRendered'
+        }, {
+          'object': _converse,
+          'event': 'bookmarksInitialized'
+        }], initRoomsListView);
+      } else {
+        u.onMultipleEvents([{
+          'object': _converse,
+          'event': 'chatBoxesFetched'
+        }, {
+          'object': _converse,
+          'event': 'roomsPanelRendered'
+        }], initRoomsListView);
+      }
 
       _converse.api.listen.on('reconnected', initRoomsListView);
     }
@@ -23039,7 +23300,9 @@ __p += '\n    <li class="toggle-toolbar-menu toggle-otr ' +
 __e(o.otr_status_class) +
 '" title="' +
 __e(o.otr_tooltip) +
-'">\n        ';
+'">\n        <span class="chat-toolbar-text">' +
+__e(o.otr_translated_status) +
+'</span>\n        ';
  if (o.otr_status == o.UNENCRYPTED) { ;
 __p += '\n            <span class="icon-unlocked"></span>\n        ';
  } ;
@@ -23554,7 +23817,7 @@ return __p
             otr_tooltip: this.getOTRTooltip(),
             otr_translated_status: OTR_TRANSLATED_MAPPING[data.otr_status]
           });
-          this.el.querySelector('.chat-toolbar').insertAdjacentHTML('beforeend', tpl_toolbar_otr(_.extend(this.model.toJSON(), options || {})));
+          this.el.querySelector('.chat-toolbar').insertAdjacentHTML('beforeend', tpl_toolbar_otr(_.extend(data, options || {})));
         },
         getToolbarOptions: function getToolbarOptions(options) {
           options = this.__super__.getToolbarOptions();
@@ -25451,12 +25714,6 @@ return __p
           _converse.chatboxviews.trimChats(chatbox);
         }
       });
-
-      var logOut = function logOut() {
-        _converse.minimized_chats.remove();
-      };
-
-      _converse.on('logout', logOut);
     }
   });
 });
@@ -26170,7 +26427,7 @@ return __p
       _ = _converse$env._;
   converse.plugins.add('converse-fullscreen', {
     enabled: function enabled(_converse) {
-      return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
+      return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
     },
     overrides: {
       // overrides mentioned here will be picked up by converse.js's

+ 333 - 76
dist/converse.js

@@ -2,7 +2,7 @@
  *
  *  An XMPP chat client that runs in the browser.
  *
- *  Version: 3.3.3
+ *  Version: 3.3.4
  */
 
 /* jshint ignore:start */
@@ -22063,6 +22063,17 @@ define('lodash.fp',['lodash', 'lodash.converter'], function (_, lodashConverter)
     return fp;
 });
 
+function CustomEvent ( event, params ) {
+    params = params || { bubbles: false, cancelable: false, detail: undefined };
+    var evt = document.createEvent( 'CustomEvent' );
+    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+    return evt;
+}
+if ( typeof window.CustomEvent !== "function" ) {
+    CustomEvent.prototype = window.Event.prototype;
+    window.CustomEvent = CustomEvent;
+}
+
 if (!String.prototype.includes) {
   String.prototype.includes = function(search, start) {
         'use strict';
@@ -27679,6 +27690,97 @@ return af;
 
 })));
 
+//! moment.js locale configuration
+//! locale : Bulgarian [bg]
+//! author : Krasen Borisov : https://github.com/kraz
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define('moment/locale/bg',['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var bg = moment.defineLocale('bg', {
+    months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+    monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+    weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+    weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+    weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+    longDateFormat : {
+        LT : 'H:mm',
+        LTS : 'H:mm:ss',
+        L : 'D.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY H:mm',
+        LLLL : 'dddd, D MMMM YYYY H:mm'
+    },
+    calendar : {
+        sameDay : '[Днес в] LT',
+        nextDay : '[Утре в] LT',
+        nextWeek : 'dddd [в] LT',
+        lastDay : '[Вчера в] LT',
+        lastWeek : function () {
+            switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
+            }
+        },
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : 'след %s',
+        past : 'преди %s',
+        s : 'няколко секунди',
+        m : 'минута',
+        mm : '%d минути',
+        h : 'час',
+        hh : '%d часа',
+        d : 'ден',
+        dd : '%d дни',
+        M : 'месец',
+        MM : '%d месеца',
+        y : 'година',
+        yy : '%d години'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+    ordinal : function (number) {
+        var lastDigit = number % 10,
+            last2Digits = number % 100;
+        if (number === 0) {
+            return number + '-ев';
+        } else if (last2Digits === 0) {
+            return number + '-ен';
+        } else if (last2Digits > 10 && last2Digits < 20) {
+            return number + '-ти';
+        } else if (lastDigit === 1) {
+            return number + '-ви';
+        } else if (lastDigit === 2) {
+            return number + '-ри';
+        } else if (lastDigit === 7 || lastDigit === 8) {
+            return number + '-ми';
+        } else {
+            return number + '-ти';
+        }
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
+
+return bg;
+
+})));
+
 //! moment.js locale configuration
 //! locale : Catalan [ca]
 //! author : Juan G. Hurtado : https://github.com/juanghurtado
@@ -28968,6 +29070,97 @@ return ru;
 
 })));
 
+//! moment.js locale configuration
+//! locale : Turkish [tr]
+//! authors : Erhan Gundogan : https://github.com/erhangundogan,
+//!           Burak Yiğit Kaya: https://github.com/BYK
+
+;(function (global, factory) {
+   typeof exports === 'object' && typeof module !== 'undefined'
+       && typeof require === 'function' ? factory(require('../moment')) :
+   typeof define === 'function' && define.amd ? define('moment/locale/tr',['../moment'], factory) :
+   factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+    1: '\'inci',
+    5: '\'inci',
+    8: '\'inci',
+    70: '\'inci',
+    80: '\'inci',
+    2: '\'nci',
+    7: '\'nci',
+    20: '\'nci',
+    50: '\'nci',
+    3: '\'üncü',
+    4: '\'üncü',
+    100: '\'üncü',
+    6: '\'ncı',
+    9: '\'uncu',
+    10: '\'uncu',
+    30: '\'uncu',
+    60: '\'ıncı',
+    90: '\'ıncı'
+};
+
+var tr = moment.defineLocale('tr', {
+    months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+    monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+    weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+    weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+    weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+    longDateFormat : {
+        LT : 'HH:mm',
+        LTS : 'HH:mm:ss',
+        L : 'DD.MM.YYYY',
+        LL : 'D MMMM YYYY',
+        LLL : 'D MMMM YYYY HH:mm',
+        LLLL : 'dddd, D MMMM YYYY HH:mm'
+    },
+    calendar : {
+        sameDay : '[bugün saat] LT',
+        nextDay : '[yarın saat] LT',
+        nextWeek : '[haftaya] dddd [saat] LT',
+        lastDay : '[dün] LT',
+        lastWeek : '[geçen hafta] dddd [saat] LT',
+        sameElse : 'L'
+    },
+    relativeTime : {
+        future : '%s sonra',
+        past : '%s önce',
+        s : 'birkaç saniye',
+        m : 'bir dakika',
+        mm : '%d dakika',
+        h : 'bir saat',
+        hh : '%d saat',
+        d : 'bir gün',
+        dd : '%d gün',
+        M : 'bir ay',
+        MM : '%d ay',
+        y : 'bir yıl',
+        yy : '%d yıl'
+    },
+    dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
+    ordinal : function (number) {
+        if (number === 0) {  // special case for zero
+            return number + '\'ıncı';
+        }
+        var a = number % 10,
+            b = number % 100 - a,
+            c = number >= 100 ? 100 : null;
+        return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+    },
+    week : {
+        dow : 1, // Monday is the first day of the week.
+        doy : 7  // The week that contains Jan 1st is the first week of the year.
+    }
+});
+
+return tr;
+
+})));
+
 //! moment.js locale configuration
 //! locale : Ukrainian [uk]
 //! author : zemlanin : https://github.com/zemlanin
@@ -29348,7 +29541,7 @@ return zhTw;
 
 /*global define */
 (function (root, factory) {
-  define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
+  define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/bg', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/tr', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
 })(this, function (Promise, Jed, _, moment) {
   'use strict';
 
@@ -36494,6 +36687,42 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
     return promise;
   };
 
+  u.interpolate = function (string, o) {
+    return string.replace(/{{{([^{}]*)}}}/g, function (a, b) {
+      var r = o[b];
+      return typeof r === 'string' || typeof r === 'number' ? r : a;
+    });
+  };
+
+  u.onMultipleEvents = function () {
+    var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
+    var callback = arguments.length > 1 ? arguments[1] : undefined;
+
+    /* Call the callback once all the events have been triggered
+     *
+     * Parameters:
+     *  (Array) events: An array of objects, with keys `object` and
+     *      `event`, representing the event name and the object it's
+     *      triggered upon.
+     *  (Function) callback: The function to call once all events have
+     *      been triggered.
+     */
+    var triggered = [];
+
+    function handler(result) {
+      triggered.push(result);
+
+      if (events.length === triggered.length) {
+        callback(triggered);
+        triggered = [];
+      }
+    }
+
+    _.each(events, function (map) {
+      return map.object.on(map.event, handler);
+    });
+  };
+
   u.safeSave = function (model, attributes) {
     if (u.isPersistableModel(model)) {
       model.save(attributes);
@@ -36503,7 +36732,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
   };
 
   u.isVisible = function (el) {
-    // XXX: Taken from jQuery's "visible" implementation
+    if (u.hasClass('hidden', el)) {
+      return false;
+    } // XXX: Taken from jQuery's "visible" implementation
+
+
     return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
   };
 
@@ -39196,7 +39429,7 @@ return Backbone.BrowserStorage;
 /*global Backbone, define, window, JSON */
 (function (root, factory) {
   define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory);
-})(this, function (sizzle, Promise, _, f, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {
+})(this, function (sizzle, Promise, _, f, polyfill, i18n, u, moment, Strophe, pluggable, Backbone) {
   /* Cannot use this due to Safari bug.
    * See https://github.com/jcbrand/converse.js/issues/196
    */
@@ -39368,7 +39601,7 @@ return Backbone.BrowserStorage;
     /* Private function, used to add a new promise to the ones already
      * available via the `waitUntil` api method.
      */
-    _converse.promises[promise] = utils.getResolveablePromise();
+    _converse.promises[promise] = u.getResolveablePromise();
   }
 
   _converse.emit = function (name) {
@@ -39390,7 +39623,7 @@ return Backbone.BrowserStorage;
     var _this = this;
 
     settings = !_.isUndefined(settings) ? settings : {};
-    var init_promise = utils.getResolveablePromise();
+    var init_promise = u.getResolveablePromise();
 
     _.each(PROMISES, addPromise);
 
@@ -39474,7 +39707,7 @@ return Backbone.BrowserStorage;
       jid: undefined,
       keepalive: true,
       locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
-      locales: ['af', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'uk', 'zh_CN', 'zh_TW'],
+      locales: ['af', 'bg', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'],
       message_carbons: true,
       message_storage: 'session',
       password: undefined,
@@ -39821,7 +40054,7 @@ return Backbone.BrowserStorage;
 
     this.initStatus = function () {
       return new Promise(function (resolve, reject) {
-        var promise = new utils.getResolveablePromise();
+        var promise = new u.getResolveablePromise();
         _this.xmppstatus = new _this.XMPPStatus();
         var id = b64_sha1("converse.xmppstatus-".concat(_converse.bare_jid));
         _this.xmppstatus.id = id; // Appears to be necessary for backbone.browserStorage
@@ -39866,7 +40099,10 @@ return Backbone.BrowserStorage;
         _converse.connection.disconnect();
       } else {
         _converse._tearDown();
-      }
+      } // Recreate all the promises
+
+
+      _.each(_.keys(_converse.promises), addPromise);
 
       _converse.emit('logout');
     };
@@ -40117,9 +40353,9 @@ return Backbone.BrowserStorage;
       initialize: function initialize(attributes) {
         var _this3 = this;
 
-        var jid = attributes.jid;
-        var bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
-        var resource = Strophe.getResourceFromJid(jid);
+        var jid = attributes.jid,
+            bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase(),
+            resource = Strophe.getResourceFromJid(jid);
         attributes.jid = bare_jid;
         this.set(_.assignIn({
           'fullname': bare_jid,
@@ -40392,7 +40628,7 @@ return Backbone.BrowserStorage;
         return true;
       },
       isSelf: function isSelf(jid) {
-        return utils.isSameBareJID(jid, _converse.connection.jid);
+        return u.isSameBareJID(jid, _converse.connection.jid);
       },
       addAndSubscribe: function addAndSubscribe(jid, name, groups, message, attributes) {
         /* Add a roster contact and then once we have confirmation from
@@ -40796,7 +41032,7 @@ return Backbone.BrowserStorage;
       constructPresence: function constructPresence(type, status_message) {
         var presence;
         type = _.isString(type) ? type : this.get('status') || _converse.default_state;
-        status_message = _.isString(status_message) ? status_message : undefined; // Most of these presence types are actually not explicitly sent,
+        status_message = _.isString(status_message) ? status_message : this.get('status_message'); // Most of these presence types are actually not explicitly sent,
         // but I add all of them here for reference and future proofing.
 
         if (type === 'unavailable' || type === 'probe' || type === 'error' || type === 'unsubscribe' || type === 'unsubscribed' || type === 'subscribe' || type === 'subscribed') {
@@ -41165,7 +41401,7 @@ return Backbone.BrowserStorage;
     } else if (_.isUndefined(i18n)) {
       finishInitialization();
     } else {
-      i18n.fetchTranslations(_converse.locale, _converse.locales, _.template(_converse.locales_url)({
+      i18n.fetchTranslations(_converse.locale, _converse.locales, u.interpolate(_converse.locales_url, {
         'locale': _converse.locale
       })).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(finishInitialization).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
     }
@@ -41233,9 +41469,9 @@ return Backbone.BrowserStorage;
     },
     'settings': {
       'update': function update(settings) {
-        utils.merge(_converse.default_settings, settings);
-        utils.merge(_converse, settings);
-        utils.applyUserSettings(_converse, settings, _converse.user_settings);
+        u.merge(_converse.default_settings, settings);
+        u.merge(_converse, settings);
+        u.applyUserSettings(_converse, settings, _converse.user_settings);
       },
       'get': function get(key) {
         if (_.includes(_.keys(_converse.default_settings), key)) {
@@ -41359,10 +41595,10 @@ return Backbone.BrowserStorage;
       'b64_sha1': b64_sha1,
       'moment': moment,
       'sizzle': sizzle,
-      'utils': utils
+      'utils': u
     }
   };
-  window.dispatchEvent(new Event('converse-loaded'));
+  window.dispatchEvent(new CustomEvent('converse-loaded'));
   return window.converse;
 });
 //# sourceMappingURL=converse-core.js.map;
@@ -41617,6 +41853,7 @@ return Backbone.BrowserStorage;
       _converse.ChatBox = Backbone.Model.extend({
         defaults: {
           'type': 'chatbox',
+          'show_avatar': true,
           'bookmarked': false,
           'chat_state': undefined,
           'num_unread': 0,
@@ -44470,9 +44707,9 @@ __e(o.avatar_height) +
 'px" width="' +
 __e(o.avatar_width) +
 'px"\n            src="data:' +
-__e(o.image_type) +
+__e(o.image_type || o._converse.DEFAULT_IMAGE_TYPE) +
 ';base64,' +
-__e(o.image) +
+__e(o.image || o._converse.DEFAULT_IMAGE) +
 '"/>\n    ';
  } ;
 __p += '\n    <div class="chat-title">\n        ';
@@ -44938,6 +45175,7 @@ return __p
         },
         render: function render() {
           this.el.innerHTML = tpl_chatbox_head(_.extend(this.model.toJSON(), {
+            '_converse': _converse,
             'avatar_width': _converse.chatview_avatar_width,
             'avatar_height': _converse.chatview_avatar_height,
             'info_close': __('Close this chat box')
@@ -48169,7 +48407,7 @@ return __p
             ev.preventDefault();
           }
 
-          var tab = ev.target,
+          var tab = u.hasClass('msgs-indicator', ev.target) ? ev.target.parentNode : ev.target,
               sibling_li = tab.parentNode.nextElementSibling || tab.parentNode.previousElementSibling,
               sibling = sibling_li.firstChild,
               sibling_panel = _converse.root.querySelector(sibling.getAttribute('href')),
@@ -48969,7 +49207,7 @@ __p += '\n<ul class="features-list">\n';
  if (o.passwordprotected) { ;
 __p += '\n<li class="feature" title="' +
 __e( o.tt_passwordprotected ) +
-'"><span class="icon-lock-2"></span>' +
+'"><span class="icon-lock"></span>' +
 __e( o.label_passwordprotected ) +
 '</li>\n';
  } ;
@@ -50268,7 +50506,7 @@ Strophe.addConnectionPlugin('disco',
           this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
           this.features = new Backbone.Collection();
           this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.features-".concat(this.get('jid'))));
-          this.features.on('add', this.onFeatureAdded);
+          this.features.on('add', this.onFeatureAdded, this);
           this.identities = new Backbone.Collection();
           this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.identities-".concat(this.get('jid'))));
           this.fetchFeatures();
@@ -50325,6 +50563,8 @@ Strophe.addConnectionPlugin('disco',
           });
         },
         onFeatureAdded: function onFeatureAdded(feature) {
+          feature.entity = this;
+
           _converse.emit('serviceDiscovered', feature);
         },
         fetchFeatures: function fetchFeatures() {
@@ -51620,8 +51860,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
  * specified in XEP-0045 Multi-user chat.
  */
 (function (root, factory) {
-  define('converse-muc',["form-utils", "converse-core", "lodash.fp", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_join_form", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!rooms_results", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
-})(this, function (u, converse, fp, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_join_form, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) {
+  define('converse-muc',["form-utils", "converse-core", "emojione", "lodash.fp", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_join_form", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!rooms_results", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
+})(this, function (u, converse, emojione, f, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_join_form, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) {
   "use strict";
 
   var ROOMS_PANEL_ID = 'chatrooms';
@@ -52548,6 +52788,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
            * Parameters:
            *  (String) text: The message text to be sent.
            */
+          text = emojione.shortnameToUnicode(text);
+
           var msgid = _converse.connection.getUniqueId();
 
           var msg = $msg({
@@ -54277,11 +54519,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
         renderTab: function renderTab() {
           var controlbox = _converse.chatboxes.get('controlbox');
 
-          var chatrooms = fp.filter(_.partial(u.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
+          var chatrooms = f.filter(_.partial(u.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
           this.tab_el.innerHTML = tpl_chatrooms_tab({
             'label_rooms': __('Rooms'),
             'is_current': controlbox.get('active-panel') === ROOMS_PANEL_ID,
-            'num_unread': fp.sum(fp.map(fp.curry(u.getAttribute)('num_unread'), chatrooms))
+            'num_unread': f.sum(f.map(f.curry(u.getAttribute)('num_unread'), chatrooms))
           });
         },
         insertIntoDOM: function insertIntoDOM() {
@@ -54513,7 +54755,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
          *  (XMLElement) message: The message stanza containing the
          *        invitation.
          */
-        var x_el = message.querySelector('x[xmlns="jabber:x:conference"]'),
+        var x_el = sizzle('x[xmlns="jabber:x:conference"]', message).pop(),
             from = Strophe.getBareJidFromJid(message.getAttribute('from')),
             room_jid = x_el.getAttribute('jid'),
             reason = x_el.getAttribute('reason');
@@ -54717,11 +54959,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
 
       function setMUCDomainFromDisco(controlboxview) {
         /* Check whether service discovery for the user's domain
-            * returned MUC information and use that to automatically
-            * set the MUC domain for the "Rooms" panel of the controlbox.
-            */
+         * returned MUC information and use that to automatically
+         * set the MUC domain for the "Rooms" panel of the controlbox.
+         */
         function featureAdded(feature) {
-          if (feature.get('var') === Strophe.NS.MUC) {
+          if (feature.get('var') === Strophe.NS.MUC && f.includes('conference', feature.entity.identities.pluck('category'))) {
             setMUCDomain(feature.get('from'), controlboxview);
           }
         }
@@ -54958,12 +55200,10 @@ return __p
           var _converse = this.__super__._converse;
 
           if (_converse.allow_bookmarks) {
-            _converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid).then(function (identity) {
-              if (_.isNil(identity)) {
-                return;
+            _converse.checkBookmarksSupport().then(function (supported) {
+              if (supported) {
+                _this.renderBookmarkToggle();
               }
-
-              _this.renderBookmarkToggle();
             }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
           }
         },
@@ -55414,38 +55654,42 @@ return __p
         }
       });
 
+      _converse.checkBookmarksSupport = function () {
+        return new Promise(function (resolve, reject) {
+          Promise.all([_converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid)]).then(function (args) {
+            resolve(args[0] && (args[1].supported || _converse.allow_public_bookmarks));
+          }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+        }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+      };
+
       var initBookmarks = function initBookmarks() {
         if (!_converse.allow_bookmarks) {
           return;
         }
 
-        Promise.all([_converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid)]).then(function (args) {
-          var identity = args[0],
-              options_support = args[1];
-
-          if (_.isNil(identity) || !options_support.supported && !_converse.allow_public_bookmarks) {
-            _converse.emit('bookmarksInitialized');
-
-            return;
-          }
-
-          _converse.bookmarks = new _converse.Bookmarks();
-
-          _converse.bookmarks.fetchBookmarks().then(function () {
+        _converse.checkBookmarksSupport().then(function (supported) {
+          if (supported) {
+            _converse.bookmarks = new _converse.Bookmarks();
             _converse.bookmarksview = new _converse.BookmarksView({
               'model': _converse.bookmarks
             });
-          }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)).then(function () {
-            _converse.emit('bookmarksInitialized');
-          });
-        }).catch(function (e) {
-          _converse.log(e, Strophe.LogLevel.ERROR);
 
-          _converse.emit('bookmarksInitialized');
+            _converse.bookmarks.fetchBookmarks().catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(function () {
+              return _converse.emit('bookmarksInitialized');
+            });
+          } else {
+            _converse.emit('bookmarksInitialized');
+          }
         });
       };
 
-      Promise.all([_converse.api.waitUntil('chatBoxesFetched'), _converse.api.waitUntil('roomsPanelRendered')]).then(initBookmarks).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+      u.onMultipleEvents([{
+        'object': _converse,
+        'event': 'chatBoxesFetched'
+      }, {
+        'object': _converse,
+        'event': 'roomsPanelRendered'
+      }], initBookmarks);
 
       _converse.on('connected', function () {
         // Add a handler for bookmarks pushed from other connected clients
@@ -55664,7 +55908,11 @@ return __p
         },
         toHTML: function toHTML() {
           return tpl_rooms_list_item(_.extend(this.model.toJSON(), {
-            'allow_bookmarks': _converse.allow_bookmarks,
+            // XXX: By the time this renders, the _converse.bookmarks
+            // collection should already exist if bookmarks are
+            // supported by the XMPP server. So we can use it
+            // as a check for support (other ways of checking are async).
+            'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
             'info_leave_room': __('Leave this room'),
             'info_remove_bookmark': __('Unbookmark this room'),
             'info_add_bookmark': __('Bookmark this room'),
@@ -55785,13 +56033,26 @@ return __p
         });
       };
 
-      Promise.all([_converse.api.waitUntil('chatBoxesFetched'), _converse.api.waitUntil('roomsPanelRendered')]).then(function () {
-        if (_converse.allow_bookmarks) {
-          _converse.api.waitUntil('bookmarksInitialized').then(initRoomsListView);
-        } else {
-          initRoomsListView();
-        }
-      });
+      if (_converse.allow_bookmarks) {
+        u.onMultipleEvents([{
+          'object': _converse,
+          'event': 'chatBoxesFetched'
+        }, {
+          'object': _converse,
+          'event': 'roomsPanelRendered'
+        }, {
+          'object': _converse,
+          'event': 'bookmarksInitialized'
+        }], initRoomsListView);
+      } else {
+        u.onMultipleEvents([{
+          'object': _converse,
+          'event': 'chatBoxesFetched'
+        }, {
+          'object': _converse,
+          'event': 'roomsPanelRendered'
+        }], initRoomsListView);
+      }
 
       _converse.api.listen.on('reconnected', initRoomsListView);
     }
@@ -56484,7 +56745,9 @@ __p += '\n    <li class="toggle-toolbar-menu toggle-otr ' +
 __e(o.otr_status_class) +
 '" title="' +
 __e(o.otr_tooltip) +
-'">\n        ';
+'">\n        <span class="chat-toolbar-text">' +
+__e(o.otr_translated_status) +
+'</span>\n        ';
  if (o.otr_status == o.UNENCRYPTED) { ;
 __p += '\n            <span class="icon-unlocked"></span>\n        ';
  } ;
@@ -64238,7 +64501,7 @@ CryptoJS.mode.CTR = (function () {
             otr_tooltip: this.getOTRTooltip(),
             otr_translated_status: OTR_TRANSLATED_MAPPING[data.otr_status]
           });
-          this.el.querySelector('.chat-toolbar').insertAdjacentHTML('beforeend', tpl_toolbar_otr(_.extend(this.model.toJSON(), options || {})));
+          this.el.querySelector('.chat-toolbar').insertAdjacentHTML('beforeend', tpl_toolbar_otr(_.extend(data, options || {})));
         },
         getToolbarOptions: function getToolbarOptions(options) {
           options = this.__super__.getToolbarOptions();
@@ -66227,12 +66490,6 @@ return __p
           _converse.chatboxviews.trimChats(chatbox);
         }
       });
-
-      var logOut = function logOut() {
-        _converse.minimized_chats.remove();
-      };
-
-      _converse.on('logout', logOut);
     }
   });
 });
@@ -66946,7 +67203,7 @@ return __p
       _ = _converse$env._;
   converse.plugins.add('converse-fullscreen', {
     enabled: function enabled(_converse) {
-      return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
+      return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
     },
     overrides: {
       // overrides mentioned here will be picked up by converse.js's

+ 2 - 2
docs/source/conf.py

@@ -48,9 +48,9 @@ copyright = u'2017, JC Brand'
 # built documents.
 #
 # The short X.Y version.
-version = '3.3.3'
+version = '3.3.4'
 # The full version, including alpha/beta/rc tags.
-release = '3.3.3'
+release = '3.3.4'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

+ 2 - 2
docs/source/quickstart.rst

@@ -22,8 +22,8 @@ The latest versions of these files are available at these URLs:
 
 To load a specific version of Converse.js you can put the version in the URL, like so:
 
-* https://cdn.conversejs.org/3.3.3/dist/converse.min.js
-* https://cdn.conversejs.org/3.3.3/css/converse.min.css
+* https://cdn.conversejs.org/3.3.4/dist/converse.min.js
+* https://cdn.conversejs.org/3.3.4/css/converse.min.css
 
 You can include these two URLs inside the *<head>* element of your website
 via the *script* and *link* tags:

+ 0 - 3
index.html

@@ -58,9 +58,6 @@
                     <li>
                         <a href="/docs/html/index.html">Documentation</a>
                     </li>
-                    <li>
-                        <a href="jslicenses.html" rel="jslicense">Licences</a>
-                    </li>
                     <li>
                         <a href="https://github.com/jcbrand/converse.js/releases" class="button" target="_blank" rel="noopener">Download</a>
                     </li>

+ 2 - 2
inverse.html

@@ -7,8 +7,8 @@
     <link rel="shortcut icon" type="image/ico" href="css/images/favicon.ico"/>
     <script type="text/javascript" src="inverse-analytics.js"></script>
     <noscript><p><img src="//stats.opkode.com/piwik.php?idsite=5" style="border:0;" alt="" /></p></noscript>
-    <link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/3.3.1/css/inverse.min.css" />
-    <script src="https://cdn.conversejs.org/3.3.1/dist/converse.min.js"></script>
+    <link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/css/inverse.min.css" />
+    <script src="/cdn.conversejs.org/dist/converse.min.js"></script>
 </head>
 <body>
     <div class="content">

File diff suppressed because it is too large
+ 217 - 217
locale/af/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 0 - 0
locale/bg/LC_MESSAGES/converse.json


+ 1343 - 0
locale/bg/LC_MESSAGES/converse.po

@@ -0,0 +1,1343 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Jan-Carel Brand
+# This file is distributed under the same license as the Converse.js package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Converse.js 3.3.3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-03-05 14:40+0100\n"
+"PO-Revision-Date: 2018-03-02 14:54+0000\n"
+"Last-Translator: Тони <toni@neshtoto.club>\n"
+"Language-Team: Bulgarian <https://hosted.weblate.org/projects/conversejs/"
+"translations/bg/>\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 2.20-dev\n"
+
+#: dist/converse-no-dependencies.js:7545
+msgid "The connection has dropped, attempting to reconnect."
+msgstr "Връзката е прекъснала, опитва се свързване отново."
+
+#: dist/converse-no-dependencies.js:7643
+msgid "An error occurred while connecting to the chat server."
+msgstr "Възникна грешка при свързване с чат сървъра."
+
+#: dist/converse-no-dependencies.js:7650
+msgid "Your Jabber ID and/or password is incorrect. Please try again."
+msgstr ""
+"Вашият джабер идентификатор и/или парола са грешни. Моля опитайте отново."
+
+#: dist/converse-no-dependencies.js:7662
+#, javascript-format
+msgid "Sorry, we could not connect to the XMPP host with domain: %1$s"
+msgstr "Извинете, не можахме да се свържем към XMPP хоста с домейна: %1$s"
+
+#: dist/converse-no-dependencies.js:7664
+msgid "The XMPP server did not offer a supported authentication mechanism"
+msgstr "XMPP сървърът не предложи поддържан удостоверителен механизъм"
+
+#: dist/converse-no-dependencies.js:8359
+#, javascript-format
+msgid "Sorry, there was an error while trying to add %1$s as a contact."
+msgstr "Извинете, възникна грешка при опит за добавяне на %1$s като контакт."
+
+#: dist/converse-no-dependencies.js:8543
+msgid "This client does not allow presence subscriptions"
+msgstr "Този клиент не допуска абонаменти за присъствие"
+
+#: dist/converse-no-dependencies.js:8624
+msgid "Click to hide these contacts"
+msgstr "Натиснете за скриване на тези контакти"
+
+#: dist/converse-no-dependencies.js:12668
+msgid "Close this chat box"
+msgstr "Затваряне на това чат прозорче"
+
+#: dist/converse-no-dependencies.js:12720
+#: dist/converse-no-dependencies.js:12757
+#: dist/converse-no-dependencies.js:18937
+msgid "You have unread messages"
+msgstr "Имате непрочетени съобщения"
+
+#: dist/converse-no-dependencies.js:12743
+msgid "Hidden message"
+msgstr "Скрито съобщение"
+
+#: dist/converse-no-dependencies.js:12745
+msgid "Personal message"
+msgstr "Лично съобщение"
+
+#: dist/converse-no-dependencies.js:12752
+#: dist/converse-no-dependencies.js:18934
+msgid "Send"
+msgstr "Изпращане"
+
+#: dist/converse-no-dependencies.js:12753
+msgid "Optional hint"
+msgstr "Незадължителен съвет"
+
+#: dist/converse-no-dependencies.js:12809
+msgid "Click to write as a normal (non-spoiler) message"
+msgstr "Натиснете за писане на нормално (неакордеонно) съобщение"
+
+#: dist/converse-no-dependencies.js:12811
+msgid "Click to write your message as a spoiler"
+msgstr "Натиснете, за да пишете съобщение, разгъващо се като акордеон"
+
+#: dist/converse-no-dependencies.js:12815
+msgid "Clear all messages"
+msgstr "Изчистване на всички съобщения"
+
+#: dist/converse-no-dependencies.js:12816
+msgid "Insert a smiley"
+msgstr "Вмъкване на усмивка"
+
+#: dist/converse-no-dependencies.js:12817
+msgid "Start a call"
+msgstr "Обаждане"
+
+#: dist/converse-no-dependencies.js:13012
+#: dist/converse-no-dependencies.js:13475
+msgid "Show hidden message"
+msgstr "Показване на скритото съобщение"
+
+#: dist/converse-no-dependencies.js:13064
+msgid "me"
+msgstr "аз"
+
+#: dist/converse-no-dependencies.js:13119
+msgid "Typing from another device"
+msgstr "Пише от друго устройство"
+
+#: dist/converse-no-dependencies.js:13121
+msgid "is typing"
+msgstr "пише"
+
+#: dist/converse-no-dependencies.js:13127
+msgid "Stopped typing on the other device"
+msgstr "Спря да пише на другото устройство"
+
+#: dist/converse-no-dependencies.js:13129
+msgid "has stopped typing"
+msgstr "спря да пише"
+
+#: dist/converse-no-dependencies.js:13134
+#: dist/converse-no-dependencies.js:13490
+#: dist/converse-no-dependencies.js:25001
+msgid "has gone away"
+msgstr "се е махнал(а)"
+
+#: dist/converse-no-dependencies.js:13262
+#: dist/converse-no-dependencies.js:19554
+msgid "Remove messages"
+msgstr "Премахване на съобщения"
+
+#: dist/converse-no-dependencies.js:13262
+msgid "Write in the third person"
+msgstr "Писане от трето лице"
+
+#: dist/converse-no-dependencies.js:13262
+#: dist/converse-no-dependencies.js:19554
+msgid "Show this menu"
+msgstr "Показване на това меню"
+
+#: dist/converse-no-dependencies.js:13393
+msgid "Are you sure you want to clear the messages from this chat box?"
+msgstr ""
+"Сигурни ли сте, че искате да изчистите съобщенията от това чат прозорче?"
+
+#: dist/converse-no-dependencies.js:13470
+msgid "Hide hidden message"
+msgstr "Скриване на скритото съобщение"
+
+#: dist/converse-no-dependencies.js:13488
+#: dist/converse-no-dependencies.js:24999
+msgid "has gone offline"
+msgstr "се е изключил(а)"
+
+#: dist/converse-no-dependencies.js:13492
+#: dist/converse-no-dependencies.js:25003
+msgid "is busy"
+msgstr "е зает(а)"
+
+#: dist/converse-no-dependencies.js:13788
+msgid "Login"
+msgstr "Вход"
+
+#: dist/converse-no-dependencies.js:13810
+msgid "Jabber ID:"
+msgstr "Джабер идентификатор:"
+
+#: dist/converse-no-dependencies.js:13816
+msgid "Password:"
+msgstr "Парола:"
+
+#: dist/converse-no-dependencies.js:13818
+msgid "password"
+msgstr "парола"
+
+#: dist/converse-no-dependencies.js:13822
+#: dist/converse-no-dependencies.js:20213
+msgid "Submit"
+msgstr "Изпращане"
+
+#: dist/converse-no-dependencies.js:13828
+msgid "Click here to log in anonymously"
+msgstr "Натиснете тук, за да велезете анонимно"
+
+#: dist/converse-no-dependencies.js:14117
+msgid "This contact is busy"
+msgstr "Този контакт е зает"
+
+#: dist/converse-no-dependencies.js:14118
+msgid "This contact is online"
+msgstr "Този контакт е включен"
+
+#: dist/converse-no-dependencies.js:14119
+msgid "This contact is offline"
+msgstr "Този контакт е изключен"
+
+#: dist/converse-no-dependencies.js:14120
+msgid "This contact is unavailable"
+msgstr "Този контакт е недостъпен"
+
+#: dist/converse-no-dependencies.js:14121
+msgid "This contact is away for an extended period"
+msgstr "Този контакт отсъства дълго време"
+
+#: dist/converse-no-dependencies.js:14122
+msgid "This contact is away"
+msgstr "Този контакт отсъства"
+
+#: dist/converse-no-dependencies.js:14125
+#: dist/converse-no-dependencies.js:15628
+#: dist/converse-no-dependencies.js:16155
+msgid "Contacts"
+msgstr "Контакти"
+
+#: dist/converse-no-dependencies.js:14127
+msgid "Groups"
+msgstr "Групи"
+
+#: dist/converse-no-dependencies.js:14129
+msgid "My contacts"
+msgstr "Моите контакти"
+
+#: dist/converse-no-dependencies.js:14131
+msgid "Pending contacts"
+msgstr "Изчакващи контакти"
+
+#: dist/converse-no-dependencies.js:14133
+msgid "Contact requests"
+msgstr "Заявки за свързване"
+
+#: dist/converse-no-dependencies.js:14135
+msgid "Ungrouped"
+msgstr "Негрупирани"
+
+#: dist/converse-no-dependencies.js:14194
+msgid "Filter"
+msgstr "Подбор"
+
+#: dist/converse-no-dependencies.js:14197
+msgid "State"
+msgstr "Състояние"
+
+#: dist/converse-no-dependencies.js:14198
+msgid "Any"
+msgstr "Произволно"
+
+#: dist/converse-no-dependencies.js:14199
+msgid "Unread"
+msgstr "Непрочетено"
+
+#: dist/converse-no-dependencies.js:14200
+#: dist/converse-no-dependencies.js:15980
+msgid "Online"
+msgstr "Включен(а)"
+
+#: dist/converse-no-dependencies.js:14201
+msgid "Chatty"
+msgstr "Приказлив(а)"
+
+#: dist/converse-no-dependencies.js:14202
+#: dist/converse-no-dependencies.js:15981
+msgid "Busy"
+msgstr "Зает(а)"
+
+#: dist/converse-no-dependencies.js:14203
+#: dist/converse-no-dependencies.js:15982
+msgid "Away"
+msgstr "Отсъстващ(а)"
+
+#: dist/converse-no-dependencies.js:14204
+msgid "Extended Away"
+msgstr "Отсъстващ(а) за дълго"
+
+#: dist/converse-no-dependencies.js:14205
+#: dist/converse-no-dependencies.js:15983
+msgid "Offline"
+msgstr "Изключен(а)"
+
+#: dist/converse-no-dependencies.js:14380
+#: dist/converse-no-dependencies.js:14403
+#, javascript-format
+msgid "Click to remove %1$s as a contact"
+msgstr "Натиснете за премахване на %1$s като контакт"
+
+#: dist/converse-no-dependencies.js:14386
+#, javascript-format
+msgid "Click to accept the contact request from %1$s"
+msgstr "Натиснете за приемане на заявката за свързване от %1$s"
+
+#: dist/converse-no-dependencies.js:14387
+#, javascript-format
+msgid "Click to decline the contact request from %1$s"
+msgstr "Натиснете, за да откажете заявката за свързване от %1$s"
+
+#: dist/converse-no-dependencies.js:14402
+#, javascript-format
+msgid "Click to chat with %1$s (JID: %2$s)"
+msgstr "Натиснете за разговор с %1$s (JID:%2$s)"
+
+#: dist/converse-no-dependencies.js:14447
+msgid "Are you sure you want to remove this contact?"
+msgstr "Сигурни ли сте, че искате да премахнете този контакт?"
+
+#: dist/converse-no-dependencies.js:14464
+#, javascript-format
+msgid "Sorry, there was an error while trying to remove %1$s as a contact."
+msgstr "Извинете, възникна грешка при опит за премахване на %1$s като контакт."
+
+#: dist/converse-no-dependencies.js:14486
+msgid "Are you sure you want to decline this contact request?"
+msgstr "Сигурни ли сте, че искате да откажете тази заявка за свързване?"
+
+#. For translators: the %1$s part gets replaced with the status
+#. Example, I am online
+#: dist/converse-no-dependencies.js:15329
+#: dist/converse-no-dependencies.js:15398
+#, javascript-format
+msgid "I am %1$s"
+msgstr "Аз съм %1$s"
+
+#: dist/converse-no-dependencies.js:15331
+#: dist/converse-no-dependencies.js:15405
+msgid "Click here to write a custom status message"
+msgstr "Натиснете тук, за да въведете свое съобщение за състояние"
+
+#: dist/converse-no-dependencies.js:15332
+#: dist/converse-no-dependencies.js:15406
+msgid "Click to change your chat status"
+msgstr "Натиснете, за да промените чат състоянието си"
+
+#: dist/converse-no-dependencies.js:15358
+msgid "Custom status"
+msgstr "Въвеждане на състояние"
+
+#: dist/converse-no-dependencies.js:15359
+#: dist/converse-no-dependencies.js:19842
+#: dist/converse-no-dependencies.js:21920
+msgid "Save"
+msgstr "Запис"
+
+#: dist/converse-no-dependencies.js:15381
+#: dist/converse-no-dependencies.js:15391
+msgid "online"
+msgstr "свързан"
+
+#: dist/converse-no-dependencies.js:15383
+msgid "busy"
+msgstr "зает"
+
+#: dist/converse-no-dependencies.js:15385
+msgid "away for long"
+msgstr "продължително отсъствие"
+
+#: dist/converse-no-dependencies.js:15387
+msgid "away"
+msgstr "отсъствие"
+
+#: dist/converse-no-dependencies.js:15389
+msgid "offline"
+msgstr "изключен"
+
+#: dist/converse-no-dependencies.js:15896
+msgid "Username"
+msgstr "Потребителско име"
+
+#: dist/converse-no-dependencies.js:15896
+msgid "user@domain"
+msgstr "потребител@домейн"
+
+#: dist/converse-no-dependencies.js:15904
+#: dist/converse-no-dependencies.js:16104
+msgid "Please enter a valid XMPP address"
+msgstr "Моля въведете валиден XMPP адрес"
+
+#: dist/converse-no-dependencies.js:15984
+msgid "Log out"
+msgstr "Изход"
+
+#: dist/converse-no-dependencies.js:15991
+msgid "Click to add new chat contacts"
+msgstr "Натиснете за въвеждане на нови чат контакти"
+
+#: dist/converse-no-dependencies.js:15992
+msgid "Add a contact"
+msgstr "Добавяне на контакт"
+
+#: dist/converse-no-dependencies.js:16031
+msgid "Contact name"
+msgstr "Име на контакта"
+
+#: dist/converse-no-dependencies.js:16032
+msgid "Search"
+msgstr "Търсене"
+
+#: dist/converse-no-dependencies.js:16037
+#: dist/converse-no-dependencies.js:16105
+msgid "e.g. user@example.org"
+msgstr "например user@example.org"
+
+#: dist/converse-no-dependencies.js:16038
+#: dist/converse-no-dependencies.js:16106
+msgid "Add"
+msgstr "Добавяне"
+
+#: dist/converse-no-dependencies.js:16070
+msgid "No users found"
+msgstr "Няма налични потребители"
+
+#: dist/converse-no-dependencies.js:16074
+msgid "Click to add as a chat contact"
+msgstr "Натиснете, за да се добави като чат контакт"
+
+#: dist/converse-no-dependencies.js:16155
+msgid "Toggle chat"
+msgstr "Показване на чата"
+
+#: dist/converse-no-dependencies.js:18695
+msgid "This room is not anonymous"
+msgstr "Тази стая не е анонимна"
+
+#: dist/converse-no-dependencies.js:18696
+msgid "This room now shows unavailable members"
+msgstr "Тази стая сега показва недостъпни членове"
+
+#: dist/converse-no-dependencies.js:18697
+msgid "This room does not show unavailable members"
+msgstr "Тази стая не показва недостъпни членове"
+
+#: dist/converse-no-dependencies.js:18698
+msgid "The room configuration has changed"
+msgstr "Настройките на стаята се промениха"
+
+#: dist/converse-no-dependencies.js:18699
+msgid "Room logging is now enabled"
+msgstr "Включено е записване в дневник за стаята"
+
+#: dist/converse-no-dependencies.js:18700
+msgid "Room logging is now disabled"
+msgstr "Записването в дневник за стаята е изключено"
+
+#: dist/converse-no-dependencies.js:18701
+msgid "This room is now no longer anonymous"
+msgstr "Тази стая вече не е анонимна"
+
+#: dist/converse-no-dependencies.js:18702
+msgid "This room is now semi-anonymous"
+msgstr "Тази стая вече е полуанонимна"
+
+#: dist/converse-no-dependencies.js:18703
+msgid "This room is now fully-anonymous"
+msgstr "Тази стая вече е напълно анонимна"
+
+#: dist/converse-no-dependencies.js:18704
+msgid "A new room has been created"
+msgstr "Създадена е нова стая"
+
+#: dist/converse-no-dependencies.js:18707
+msgid "You have been banned from this room"
+msgstr "Достъпът ви до тази стая беше спрян"
+
+#: dist/converse-no-dependencies.js:18708
+msgid "You have been kicked from this room"
+msgstr "Бяхте изведени от тази стая"
+
+#: dist/converse-no-dependencies.js:18709
+msgid "You have been removed from this room because of an affiliation change"
+msgstr "Бяхте премахнати от тази стая заради промяна на правата за достъп"
+
+#: dist/converse-no-dependencies.js:18710
+msgid ""
+"You have been removed from this room because the room has changed to members-"
+"only and you're not a member"
+msgstr ""
+"Бяхте премахнати от тази стая, защото стаята стана само за членове, а вие не "
+"сте член"
+
+#: dist/converse-no-dependencies.js:18711
+msgid ""
+"You have been removed from this room because the MUC (Multi-user chat) "
+"service is being shut down"
+msgstr ""
+"Бяхте премахнати от тази стая, защото услугата „Чат за множество "
+"потребители“ се изключва"
+
+#. XXX: Note the triple underscore function and not double
+#. * underscore.
+#. *
+#. * This is a hack. We can't pass the strings to __ because we
+#. * don't yet know what the variable to interpolate is.
+#. *
+#. * Triple underscore will just return the string again, but we
+#. * can then at least tell gettext to scan for it so that these
+#. * strings are picked up by the translation machinery.
+#.
+#: dist/converse-no-dependencies.js:18724
+#, javascript-format
+msgid "%1$s has been banned"
+msgstr "%1$s беше лишен от достъп"
+
+#: dist/converse-no-dependencies.js:18725
+#, javascript-format
+msgid "%1$s's nickname has changed"
+msgstr "Краткото име на %1$s се промени"
+
+#: dist/converse-no-dependencies.js:18726
+#, javascript-format
+msgid "%1$s has been kicked out"
+msgstr "%1$s беше изведен"
+
+#: dist/converse-no-dependencies.js:18727
+#, javascript-format
+msgid "%1$s has been removed because of an affiliation change"
+msgstr "%1$s беше премахнат заради промяна на членство"
+
+#: dist/converse-no-dependencies.js:18728
+#, javascript-format
+msgid "%1$s has been removed for not being a member"
+msgstr "%1$s беше премахнат, защото не е член"
+
+#: dist/converse-no-dependencies.js:18731
+#, javascript-format
+msgid "Your nickname has been automatically set to %1$s"
+msgstr "Вашето кратко име беше автоматично установено на %1$s"
+
+#: dist/converse-no-dependencies.js:18732
+#, javascript-format
+msgid "Your nickname has been changed to %1$s"
+msgstr "Краткото ви име беше променено на %1$s"
+
+#: dist/converse-no-dependencies.js:18933
+msgid "Message"
+msgstr "Съобщение"
+
+#: dist/converse-no-dependencies.js:18962
+#, javascript-format
+msgid "%1$s is no longer a moderator."
+msgstr "%1$s вече не е модератор."
+
+#: dist/converse-no-dependencies.js:18966
+#, javascript-format
+msgid "%1$s has been given a voice again."
+msgstr "%1$s получи глас отново."
+
+#: dist/converse-no-dependencies.js:18970
+#, javascript-format
+msgid "%1$s has been muted."
+msgstr "%1$s беше заглушен."
+
+#: dist/converse-no-dependencies.js:18974
+#, javascript-format
+msgid "%1$s is now a moderator."
+msgstr "%1$s сега е модератор."
+
+#: dist/converse-no-dependencies.js:18982
+msgid "Close and leave this room"
+msgstr "Затваряне и напускане на тази стая"
+
+#: dist/converse-no-dependencies.js:18983
+msgid "Configure this room"
+msgstr "Настройване на тази стая"
+
+#: dist/converse-no-dependencies.js:19040
+msgid "Hide the list of occupants"
+msgstr "Скриване на списъка с участници"
+
+#: dist/converse-no-dependencies.js:19479
+#, javascript-format
+msgid ""
+"Error: the \"%1$s\" command takes two arguments, the user's nickname and "
+"optionally a reason."
+msgstr ""
+"Грешка: командата “%1$s” приема два аргумента – краткото име на потребителя "
+"и, по желание, причина."
+
+#: dist/converse-no-dependencies.js:19492
+msgid "Are you sure you want to clear the messages from this room?"
+msgstr "Сигурни ли сте, че искате да изчистите съобщенията от тази стая?"
+
+#: dist/converse-no-dependencies.js:19501
+msgid "Error: could not execute the command"
+msgstr "Грешка: невъзможност за изпълнение на командата"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Change user's affiliation to admin"
+msgstr "Промяна на ролята на потребителя на администратор"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Ban user from room"
+msgstr "Спиране на достъпа на потребителя до стаята"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Change user role to participant"
+msgstr "Промяна на ролята на потребителя на участник"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Kick user from room"
+msgstr "Извеждане на потребителя от стаята"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Write in 3rd person"
+msgstr "Писане в трето лице"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Grant membership to a user"
+msgstr "Приемане на членство на потребител"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Remove user's ability to post messages"
+msgstr "Премахване на допуска на потребителя да публикува съобщения"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Change your nickname"
+msgstr "Промяна на краткото ви име"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Grant moderator role to user"
+msgstr "Даване на роля модератор на потребителя"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Grant ownership of this room"
+msgstr "Даване на собствеността на тази стая"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Revoke user's membership"
+msgstr "Спиране на членството на потребителя"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Set room subject"
+msgstr "Задаване на тема на стаята"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Set room subject (alias for /subject)"
+msgstr "Задаване на тема на стаята (псевдоним за /тема)"
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Allow muted user to post messages"
+msgstr "Позволяване заглушен потребител да публикува съобщения"
+
+#: dist/converse-no-dependencies.js:19843
+#: dist/converse-no-dependencies.js:21921
+#: dist/converse-no-dependencies.js:23960
+msgid "Cancel"
+msgstr "Отмяна"
+
+#: dist/converse-no-dependencies.js:20162
+msgid ""
+"The nickname you chose is reserved or currently in use, please choose a "
+"different one."
+msgstr ""
+"Краткото име, което избрахте, е запазено или понастоящем се ползва, моля "
+"изберете друго."
+
+#: dist/converse-no-dependencies.js:20188
+msgid "Please choose your nickname"
+msgstr "Моля изберете краткото си име"
+
+#: dist/converse-no-dependencies.js:20189
+#: dist/converse-no-dependencies.js:21101
+msgid "Nickname"
+msgstr "Кратко име"
+
+#: dist/converse-no-dependencies.js:20190
+msgid "Enter room"
+msgstr "Влизане в стаята"
+
+#: dist/converse-no-dependencies.js:20211
+msgid "This chatroom requires a password"
+msgstr "Тази чат стая изисква парола"
+
+#: dist/converse-no-dependencies.js:20212
+msgid "Password: "
+msgstr "Парола: "
+
+#: dist/converse-no-dependencies.js:20354
+#, javascript-format
+msgid "This action was done by %1$s."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20358
+#: dist/converse-no-dependencies.js:20374
+#, javascript-format
+msgid "The reason given is: \"%1$s\"."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20390
+#, javascript-format
+msgid "%1$s has left and re-entered the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20396
+#, javascript-format
+msgid "%1$s has entered the room. \"%2$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20398
+#, javascript-format
+msgid "%1$s has entered the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20427
+#, javascript-format
+msgid "%1$s has entered and left the room. \"%2$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20429
+#, javascript-format
+msgid "%1$s has entered and left the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20441
+#, javascript-format
+msgid "%1$s has left the room. \"%2$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20443
+#, javascript-format
+msgid "%1$s has left the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20512
+msgid "You are not on the member list of this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20514
+msgid "You have been banned from this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20518
+msgid "No nickname was specified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20522
+msgid "You are not allowed to create new rooms."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20524
+msgid "Your nickname doesn't conform to this room's policies."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20528
+msgid "This room does not (yet) exist."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20530
+msgid "This room has reached its maximum number of occupants."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20651
+#, javascript-format
+msgid "Topic set by %1$s to: %2$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20767
+#, javascript-format
+msgid "Click to mention %1$s in your message."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20768
+msgid "This user is a moderator."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20769
+msgid "This user can send messages in this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20770
+msgid "This user can NOT send messages in this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20829
+msgid "Occupants"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20846
+#: dist/converse-no-dependencies.js:21050
+msgid "Invite"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20865
+msgid "Features"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20866
+#: dist/converse-no-dependencies.js:21306
+msgid "Hidden"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20867
+msgid "Message archiving"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20868
+msgid "Members only"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20869
+#: dist/converse-no-dependencies.js:21308
+msgid "Moderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20870
+#: dist/converse-no-dependencies.js:21309
+msgid "Non-anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20871
+msgid "Open"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20872
+msgid "Password protected"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20873
+msgid "Persistent"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20874
+#: dist/converse-no-dependencies.js:21312
+msgid "Public"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20875
+#: dist/converse-no-dependencies.js:21313
+msgid "Semi-anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20876
+msgid "Temporary"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20877
+#: dist/converse-no-dependencies.js:21315
+msgid "Unmoderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20878
+msgid "No password"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20879
+msgid "This room is not publicly searchable"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20880
+msgid "Messages are archived on the server"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20881
+msgid "This room is restricted to members only"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20882
+msgid "This room is being moderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20883
+msgid "All other room occupants can see your XMPP username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20884
+msgid "Anyone can join this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20885
+msgid "This room requires a password before entry"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20886
+msgid "This room persists even if it's unoccupied"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20887
+msgid "This room is publicly searchable"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20888
+msgid "Only moderators can see your XMPP username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20889
+msgid "This room will disappear once the last person leaves"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20890
+msgid "This room is not being moderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20891
+msgid "This room does not require a password upon entry"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21027
+#, javascript-format
+msgid ""
+"You are about to invite %1$s to the chat room \"%2$s\". You may optionally "
+"include a message, explaining the reason for the invitation."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21049
+msgid "Please enter a valid XMPP username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21100
+msgid "Room name"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21102
+msgid "Server"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21103
+msgid "Join Room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21104
+msgid "Show rooms"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21165
+msgid "Rooms"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21196
+msgid "No rooms found"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21208
+#: dist/converse-no-dependencies.js:22191
+#: dist/converse-no-dependencies.js:22562
+msgid "Click to open this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21209
+#: dist/converse-no-dependencies.js:22188
+#: dist/converse-no-dependencies.js:22560
+msgid "Show more information on this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21224
+msgid "Rooms found"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21301
+msgid "Description:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21302
+msgid "Room Address (JID):"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21303
+msgid "Occupants:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21304
+msgid "Features:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21305
+msgid "Requires authentication"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21307
+msgid "Requires an invitation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21310
+msgid "Open room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21311
+msgid "Permanent room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21314
+msgid "Temporary room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21414
+#, javascript-format
+msgid "%1$s has invited you to join a chat room: %2$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21416
+#, javascript-format
+msgid ""
+"%1$s has invited you to join a chat room: %2$s, and left the following "
+"reason: \"%3$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21830
+#: dist/converse-no-dependencies.js:21915
+#: dist/converse-no-dependencies.js:22559
+msgid "Bookmark this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21916
+msgid "The name for this bookmark:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21917
+msgid "Would you like this room to be automatically joined upon startup?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21918
+msgid "What should your nickname for this room be?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21994
+#, javascript-format
+msgid "Are you sure you want to remove the bookmark \"%1$s\"?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22106
+msgid "Sorry, something went wrong while trying to save your bookmark."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22185
+#: dist/converse-no-dependencies.js:22557
+msgid "Leave this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22186
+msgid "Remove this bookmark"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22187
+#: dist/converse-no-dependencies.js:22558
+msgid "Unbookmark this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22226
+msgid "Click to toggle the bookmarks list"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22227
+msgid "Bookmarks"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22593
+msgid "Click to toggle the rooms list"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22594
+msgid "Open Rooms"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22627
+#, javascript-format
+msgid "Are you sure you want to leave the room \"%1$s\"?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23479
+msgid "Re-establishing encrypted session"
+msgstr ""
+
+#. We need to generate a new key and instance tag
+#: dist/converse-no-dependencies.js:23490
+msgid "Generating private key."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23490
+msgid "Your browser might become unresponsive."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23533
+#, javascript-format
+msgid ""
+"Authentication request from %1$s\n"
+"\n"
+"Your chat contact is attempting to verify your identity, by asking you the "
+"question below.\n"
+"\n"
+"%2$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23542
+msgid "Could not verify this user's identify."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23596
+msgid "Exchanging private key with contact."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23711
+msgid "Your messages are not encrypted anymore"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23713
+msgid ""
+"Your messages are now encrypted but your contact's identity has not been "
+"verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23715
+msgid "Your contact's identify has been verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23717
+msgid "Your contact has ended encryption on their end, you should do the same."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23727
+msgid "Your message could not be sent"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23729
+msgid "We received an unencrypted message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23731
+msgid "We received an unreadable encrypted message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23757
+#, javascript-format
+msgid ""
+"Here are the fingerprints, please confirm them with %1$s, outside of this "
+"chat.\n"
+"\n"
+"Fingerprint for you, %2$s: %3$s\n"
+"\n"
+"Fingerprint for %1$s: %4$s\n"
+"\n"
+"If you have confirmed that the fingerprints match, click OK, otherwise click "
+"Cancel."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23769
+msgid ""
+"You will be prompted to provide a security question and then an answer to "
+"that question.\n"
+"\n"
+"Your contact will then be prompted the same question and if they type the "
+"exact same answer (case sensitive), their identity will be verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23770
+msgid "What is your security question?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23773
+msgid "What is the answer to the security question?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23777
+msgid "Invalid authentication scheme provided"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23795
+msgid "Your messages are not encrypted. Click here to enable OTR encryption."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23797
+msgid "Your messages are encrypted, but your contact has not been verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23799
+msgid "Your messages are encrypted and your contact verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23801
+msgid ""
+"Your contact has closed their end of the private session, you should do the "
+"same"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23815
+msgid "End encrypted conversation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23816
+msgid "Refresh encrypted conversation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23817
+msgid "Start encrypted conversation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23818
+msgid "Verify with fingerprints"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23819
+msgid "Verify with SMP"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23820
+msgid "What's this?"
+msgstr ""
+
+#. Translation aware constants
+#. ---------------------------
+#. We can only call the __ translation method *after* converse.js
+#. has been initialized and with it the i18n machinery. That's why
+#. we do it here in the "initialize" method and not at the top of
+#. the module.
+#: dist/converse-no-dependencies.js:23863
+msgid "unencrypted"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23864
+msgid "unverified"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23865
+msgid "verified"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23866
+msgid "finished"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23882
+msgid "Don't have a chat account?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23884
+msgid "Create an account"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23896
+msgid "Create your account"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23898
+msgid "Please enter the XMPP provider to register with:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23920
+msgid "Already have a chat account?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23922
+msgid "Log in here"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23932
+msgid "Account Registration:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23940
+msgid "Register"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23944
+msgid "Choose a different provider"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23956
+msgid "Hold tight, we're fetching the registration form…"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24091
+msgid " e.g. conversejs.org"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24137
+msgid "Fetch registration form"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24138
+msgid "Tip: A list of public XMPP providers is available"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24139
+msgid "here"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24187
+msgid "Sorry, we're unable to connect to your chosen provider."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24203
+msgid ""
+"Sorry, the given provider does not support in band account registration. "
+"Please try with a different provider."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24227
+#, javascript-format
+msgid ""
+"Something went wrong while establishing a connection with \"%1$s\". Are you "
+"sure it exists?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24390
+msgid "Now logging you in"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24394
+msgid "Registered successfully"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24503
+msgid ""
+"The provider rejected your registration attempt. Please check the values you "
+"entered for correctness."
+msgstr ""
+
+#. workaround for Prosody which doesn't give type "headline"
+#: dist/converse-no-dependencies.js:24949
+#: dist/converse-no-dependencies.js:24955
+#, javascript-format
+msgid "Notification from %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24957
+#: dist/converse-no-dependencies.js:24968
+#: dist/converse-no-dependencies.js:24971
+#, javascript-format
+msgid "%1$s says"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25005
+msgid "has come online"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25022
+msgid "wants to be your contact"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25347
+#: dist/converse-no-dependencies.js:25703
+msgid "Minimize this chat box"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25493
+msgid "Click to restore this chat"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25680
+msgid "Minimized"
+msgstr ""

File diff suppressed because it is too large
+ 235 - 235
locale/ca/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 283 - 283
locale/converse.pot


File diff suppressed because it is too large
+ 0 - 0
locale/de/LC_MESSAGES/converse.json


File diff suppressed because it is too large
+ 247 - 249
locale/de/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 282 - 282
locale/es/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 0 - 0
locale/fr/LC_MESSAGES/converse.json


File diff suppressed because it is too large
+ 245 - 249
locale/fr/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 282 - 282
locale/he/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 282 - 282
locale/hu/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 282 - 282
locale/id/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 260 - 260
locale/it/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 235 - 235
locale/ja/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 0 - 0
locale/nb/LC_MESSAGES/converse.json


File diff suppressed because it is too large
+ 239 - 239
locale/nb/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 0 - 0
locale/nl/LC_MESSAGES/converse.json


File diff suppressed because it is too large
+ 244 - 248
locale/nl/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 235 - 235
locale/pl/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 235 - 235
locale/pt_BR/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 235 - 235
locale/ru/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 0 - 0
locale/tr/LC_MESSAGES/converse.json


+ 1333 - 0
locale/tr/LC_MESSAGES/converse.po

@@ -0,0 +1,1333 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Jan-Carel Brand
+# This file is distributed under the same license as the Converse.js package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Converse.js 3.3.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-03-05 14:40+0100\n"
+"PO-Revision-Date: 2018-02-15 18:40+0000\n"
+"Last-Translator: monolifed <monolifed@gmail.com>\n"
+"Language-Team: Turkish <https://hosted.weblate.org/projects/conversejs/"
+"translations/tr/>\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 2.19\n"
+
+#: dist/converse-no-dependencies.js:7545
+msgid "The connection has dropped, attempting to reconnect."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:7643
+msgid "An error occurred while connecting to the chat server."
+msgstr "Sohbet sunucusuna bağlanılırken bir hata oluştu."
+
+#: dist/converse-no-dependencies.js:7650
+msgid "Your Jabber ID and/or password is incorrect. Please try again."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:7662
+#, javascript-format
+msgid "Sorry, we could not connect to the XMPP host with domain: %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:7664
+msgid "The XMPP server did not offer a supported authentication mechanism"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:8359
+#, javascript-format
+msgid "Sorry, there was an error while trying to add %1$s as a contact."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:8543
+msgid "This client does not allow presence subscriptions"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:8624
+msgid "Click to hide these contacts"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12668
+msgid "Close this chat box"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12720
+#: dist/converse-no-dependencies.js:12757
+#: dist/converse-no-dependencies.js:18937
+msgid "You have unread messages"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12743
+msgid "Hidden message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12745
+msgid "Personal message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12752
+#: dist/converse-no-dependencies.js:18934
+msgid "Send"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12753
+msgid "Optional hint"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12809
+msgid "Click to write as a normal (non-spoiler) message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12811
+msgid "Click to write your message as a spoiler"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12815
+msgid "Clear all messages"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12816
+msgid "Insert a smiley"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:12817
+msgid "Start a call"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13012
+#: dist/converse-no-dependencies.js:13475
+msgid "Show hidden message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13064
+msgid "me"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13119
+msgid "Typing from another device"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13121
+msgid "is typing"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13127
+msgid "Stopped typing on the other device"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13129
+msgid "has stopped typing"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13134
+#: dist/converse-no-dependencies.js:13490
+#: dist/converse-no-dependencies.js:25001
+msgid "has gone away"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13262
+#: dist/converse-no-dependencies.js:19554
+msgid "Remove messages"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13262
+msgid "Write in the third person"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13262
+#: dist/converse-no-dependencies.js:19554
+msgid "Show this menu"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13393
+msgid "Are you sure you want to clear the messages from this chat box?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13470
+msgid "Hide hidden message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13488
+#: dist/converse-no-dependencies.js:24999
+msgid "has gone offline"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13492
+#: dist/converse-no-dependencies.js:25003
+msgid "is busy"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13788
+msgid "Login"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13810
+msgid "Jabber ID:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13816
+msgid "Password:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13818
+msgid "password"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13822
+#: dist/converse-no-dependencies.js:20213
+msgid "Submit"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:13828
+msgid "Click here to log in anonymously"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14117
+msgid "This contact is busy"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14118
+msgid "This contact is online"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14119
+msgid "This contact is offline"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14120
+msgid "This contact is unavailable"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14121
+msgid "This contact is away for an extended period"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14122
+msgid "This contact is away"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14125
+#: dist/converse-no-dependencies.js:15628
+#: dist/converse-no-dependencies.js:16155
+msgid "Contacts"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14127
+msgid "Groups"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14129
+msgid "My contacts"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14131
+msgid "Pending contacts"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14133
+msgid "Contact requests"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14135
+msgid "Ungrouped"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14194
+msgid "Filter"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14197
+msgid "State"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14198
+msgid "Any"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14199
+msgid "Unread"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14200
+#: dist/converse-no-dependencies.js:15980
+msgid "Online"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14201
+msgid "Chatty"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14202
+#: dist/converse-no-dependencies.js:15981
+msgid "Busy"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14203
+#: dist/converse-no-dependencies.js:15982
+msgid "Away"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14204
+msgid "Extended Away"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14205
+#: dist/converse-no-dependencies.js:15983
+msgid "Offline"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14380
+#: dist/converse-no-dependencies.js:14403
+#, javascript-format
+msgid "Click to remove %1$s as a contact"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14386
+#, javascript-format
+msgid "Click to accept the contact request from %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14387
+#, javascript-format
+msgid "Click to decline the contact request from %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14402
+#, javascript-format
+msgid "Click to chat with %1$s (JID: %2$s)"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14447
+msgid "Are you sure you want to remove this contact?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14464
+#, javascript-format
+msgid "Sorry, there was an error while trying to remove %1$s as a contact."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:14486
+msgid "Are you sure you want to decline this contact request?"
+msgstr ""
+
+#. For translators: the %1$s part gets replaced with the status
+#. Example, I am online
+#: dist/converse-no-dependencies.js:15329
+#: dist/converse-no-dependencies.js:15398
+#, javascript-format
+msgid "I am %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15331
+#: dist/converse-no-dependencies.js:15405
+msgid "Click here to write a custom status message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15332
+#: dist/converse-no-dependencies.js:15406
+msgid "Click to change your chat status"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15358
+msgid "Custom status"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15359
+#: dist/converse-no-dependencies.js:19842
+#: dist/converse-no-dependencies.js:21920
+msgid "Save"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15381
+#: dist/converse-no-dependencies.js:15391
+msgid "online"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15383
+msgid "busy"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15385
+msgid "away for long"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15387
+msgid "away"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15389
+msgid "offline"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15896
+msgid "Username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15896
+msgid "user@domain"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15904
+#: dist/converse-no-dependencies.js:16104
+msgid "Please enter a valid XMPP address"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15984
+msgid "Log out"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15991
+msgid "Click to add new chat contacts"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:15992
+msgid "Add a contact"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16031
+msgid "Contact name"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16032
+msgid "Search"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16037
+#: dist/converse-no-dependencies.js:16105
+msgid "e.g. user@example.org"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16038
+#: dist/converse-no-dependencies.js:16106
+msgid "Add"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16070
+msgid "No users found"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16074
+msgid "Click to add as a chat contact"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:16155
+msgid "Toggle chat"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18695
+msgid "This room is not anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18696
+msgid "This room now shows unavailable members"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18697
+msgid "This room does not show unavailable members"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18698
+msgid "The room configuration has changed"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18699
+msgid "Room logging is now enabled"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18700
+msgid "Room logging is now disabled"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18701
+msgid "This room is now no longer anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18702
+msgid "This room is now semi-anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18703
+msgid "This room is now fully-anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18704
+msgid "A new room has been created"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18707
+msgid "You have been banned from this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18708
+msgid "You have been kicked from this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18709
+msgid "You have been removed from this room because of an affiliation change"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18710
+msgid ""
+"You have been removed from this room because the room has changed to members-"
+"only and you're not a member"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18711
+msgid ""
+"You have been removed from this room because the MUC (Multi-user chat) "
+"service is being shut down"
+msgstr ""
+
+#. XXX: Note the triple underscore function and not double
+#. * underscore.
+#. *
+#. * This is a hack. We can't pass the strings to __ because we
+#. * don't yet know what the variable to interpolate is.
+#. *
+#. * Triple underscore will just return the string again, but we
+#. * can then at least tell gettext to scan for it so that these
+#. * strings are picked up by the translation machinery.
+#.
+#: dist/converse-no-dependencies.js:18724
+#, javascript-format
+msgid "%1$s has been banned"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18725
+#, javascript-format
+msgid "%1$s's nickname has changed"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18726
+#, javascript-format
+msgid "%1$s has been kicked out"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18727
+#, javascript-format
+msgid "%1$s has been removed because of an affiliation change"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18728
+#, javascript-format
+msgid "%1$s has been removed for not being a member"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18731
+#, javascript-format
+msgid "Your nickname has been automatically set to %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18732
+#, javascript-format
+msgid "Your nickname has been changed to %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18933
+msgid "Message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18962
+#, javascript-format
+msgid "%1$s is no longer a moderator."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18966
+#, javascript-format
+msgid "%1$s has been given a voice again."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18970
+#, javascript-format
+msgid "%1$s has been muted."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18974
+#, javascript-format
+msgid "%1$s is now a moderator."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18982
+msgid "Close and leave this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:18983
+msgid "Configure this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19040
+msgid "Hide the list of occupants"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19479
+#, javascript-format
+msgid ""
+"Error: the \"%1$s\" command takes two arguments, the user's nickname and "
+"optionally a reason."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19492
+msgid "Are you sure you want to clear the messages from this room?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19501
+msgid "Error: could not execute the command"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Change user's affiliation to admin"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Ban user from room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Change user role to participant"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Kick user from room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Write in 3rd person"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Grant membership to a user"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Remove user's ability to post messages"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Change your nickname"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Grant moderator role to user"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Grant ownership of this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Revoke user's membership"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Set room subject"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Set room subject (alias for /subject)"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19554
+msgid "Allow muted user to post messages"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:19843
+#: dist/converse-no-dependencies.js:21921
+#: dist/converse-no-dependencies.js:23960
+msgid "Cancel"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20162
+msgid ""
+"The nickname you chose is reserved or currently in use, please choose a "
+"different one."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20188
+msgid "Please choose your nickname"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20189
+#: dist/converse-no-dependencies.js:21101
+msgid "Nickname"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20190
+msgid "Enter room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20211
+msgid "This chatroom requires a password"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20212
+msgid "Password: "
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20354
+#, javascript-format
+msgid "This action was done by %1$s."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20358
+#: dist/converse-no-dependencies.js:20374
+#, javascript-format
+msgid "The reason given is: \"%1$s\"."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20390
+#, javascript-format
+msgid "%1$s has left and re-entered the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20396
+#, javascript-format
+msgid "%1$s has entered the room. \"%2$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20398
+#, javascript-format
+msgid "%1$s has entered the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20427
+#, javascript-format
+msgid "%1$s has entered and left the room. \"%2$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20429
+#, javascript-format
+msgid "%1$s has entered and left the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20441
+#, javascript-format
+msgid "%1$s has left the room. \"%2$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20443
+#, javascript-format
+msgid "%1$s has left the room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20512
+msgid "You are not on the member list of this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20514
+msgid "You have been banned from this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20518
+msgid "No nickname was specified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20522
+msgid "You are not allowed to create new rooms."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20524
+msgid "Your nickname doesn't conform to this room's policies."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20528
+msgid "This room does not (yet) exist."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20530
+msgid "This room has reached its maximum number of occupants."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20651
+#, javascript-format
+msgid "Topic set by %1$s to: %2$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20767
+#, javascript-format
+msgid "Click to mention %1$s in your message."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20768
+msgid "This user is a moderator."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20769
+msgid "This user can send messages in this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20770
+msgid "This user can NOT send messages in this room."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20829
+msgid "Occupants"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20846
+#: dist/converse-no-dependencies.js:21050
+msgid "Invite"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20865
+msgid "Features"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20866
+#: dist/converse-no-dependencies.js:21306
+msgid "Hidden"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20867
+msgid "Message archiving"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20868
+msgid "Members only"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20869
+#: dist/converse-no-dependencies.js:21308
+msgid "Moderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20870
+#: dist/converse-no-dependencies.js:21309
+msgid "Non-anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20871
+msgid "Open"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20872
+msgid "Password protected"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20873
+msgid "Persistent"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20874
+#: dist/converse-no-dependencies.js:21312
+msgid "Public"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20875
+#: dist/converse-no-dependencies.js:21313
+msgid "Semi-anonymous"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20876
+msgid "Temporary"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20877
+#: dist/converse-no-dependencies.js:21315
+msgid "Unmoderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20878
+msgid "No password"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20879
+msgid "This room is not publicly searchable"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20880
+msgid "Messages are archived on the server"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20881
+msgid "This room is restricted to members only"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20882
+msgid "This room is being moderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20883
+msgid "All other room occupants can see your XMPP username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20884
+msgid "Anyone can join this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20885
+msgid "This room requires a password before entry"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20886
+msgid "This room persists even if it's unoccupied"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20887
+msgid "This room is publicly searchable"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20888
+msgid "Only moderators can see your XMPP username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20889
+msgid "This room will disappear once the last person leaves"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20890
+msgid "This room is not being moderated"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:20891
+msgid "This room does not require a password upon entry"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21027
+#, javascript-format
+msgid ""
+"You are about to invite %1$s to the chat room \"%2$s\". You may optionally "
+"include a message, explaining the reason for the invitation."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21049
+msgid "Please enter a valid XMPP username"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21100
+msgid "Room name"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21102
+msgid "Server"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21103
+msgid "Join Room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21104
+msgid "Show rooms"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21165
+msgid "Rooms"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21196
+msgid "No rooms found"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21208
+#: dist/converse-no-dependencies.js:22191
+#: dist/converse-no-dependencies.js:22562
+msgid "Click to open this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21209
+#: dist/converse-no-dependencies.js:22188
+#: dist/converse-no-dependencies.js:22560
+msgid "Show more information on this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21224
+msgid "Rooms found"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21301
+msgid "Description:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21302
+msgid "Room Address (JID):"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21303
+msgid "Occupants:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21304
+msgid "Features:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21305
+msgid "Requires authentication"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21307
+msgid "Requires an invitation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21310
+msgid "Open room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21311
+msgid "Permanent room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21314
+msgid "Temporary room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21414
+#, javascript-format
+msgid "%1$s has invited you to join a chat room: %2$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21416
+#, javascript-format
+msgid ""
+"%1$s has invited you to join a chat room: %2$s, and left the following "
+"reason: \"%3$s\""
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21830
+#: dist/converse-no-dependencies.js:21915
+#: dist/converse-no-dependencies.js:22559
+msgid "Bookmark this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21916
+msgid "The name for this bookmark:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21917
+msgid "Would you like this room to be automatically joined upon startup?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21918
+msgid "What should your nickname for this room be?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:21994
+#, javascript-format
+msgid "Are you sure you want to remove the bookmark \"%1$s\"?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22106
+msgid "Sorry, something went wrong while trying to save your bookmark."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22185
+#: dist/converse-no-dependencies.js:22557
+msgid "Leave this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22186
+msgid "Remove this bookmark"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22187
+#: dist/converse-no-dependencies.js:22558
+msgid "Unbookmark this room"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22226
+msgid "Click to toggle the bookmarks list"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22227
+msgid "Bookmarks"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22593
+msgid "Click to toggle the rooms list"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22594
+msgid "Open Rooms"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:22627
+#, javascript-format
+msgid "Are you sure you want to leave the room \"%1$s\"?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23479
+msgid "Re-establishing encrypted session"
+msgstr ""
+
+#. We need to generate a new key and instance tag
+#: dist/converse-no-dependencies.js:23490
+msgid "Generating private key."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23490
+msgid "Your browser might become unresponsive."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23533
+#, javascript-format
+msgid ""
+"Authentication request from %1$s\n"
+"\n"
+"Your chat contact is attempting to verify your identity, by asking you the "
+"question below.\n"
+"\n"
+"%2$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23542
+msgid "Could not verify this user's identify."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23596
+msgid "Exchanging private key with contact."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23711
+msgid "Your messages are not encrypted anymore"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23713
+msgid ""
+"Your messages are now encrypted but your contact's identity has not been "
+"verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23715
+msgid "Your contact's identify has been verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23717
+msgid "Your contact has ended encryption on their end, you should do the same."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23727
+msgid "Your message could not be sent"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23729
+msgid "We received an unencrypted message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23731
+msgid "We received an unreadable encrypted message"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23757
+#, javascript-format
+msgid ""
+"Here are the fingerprints, please confirm them with %1$s, outside of this "
+"chat.\n"
+"\n"
+"Fingerprint for you, %2$s: %3$s\n"
+"\n"
+"Fingerprint for %1$s: %4$s\n"
+"\n"
+"If you have confirmed that the fingerprints match, click OK, otherwise click "
+"Cancel."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23769
+msgid ""
+"You will be prompted to provide a security question and then an answer to "
+"that question.\n"
+"\n"
+"Your contact will then be prompted the same question and if they type the "
+"exact same answer (case sensitive), their identity will be verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23770
+msgid "What is your security question?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23773
+msgid "What is the answer to the security question?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23777
+msgid "Invalid authentication scheme provided"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23795
+msgid "Your messages are not encrypted. Click here to enable OTR encryption."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23797
+msgid "Your messages are encrypted, but your contact has not been verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23799
+msgid "Your messages are encrypted and your contact verified."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23801
+msgid ""
+"Your contact has closed their end of the private session, you should do the "
+"same"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23815
+msgid "End encrypted conversation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23816
+msgid "Refresh encrypted conversation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23817
+msgid "Start encrypted conversation"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23818
+msgid "Verify with fingerprints"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23819
+msgid "Verify with SMP"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23820
+msgid "What's this?"
+msgstr ""
+
+#. Translation aware constants
+#. ---------------------------
+#. We can only call the __ translation method *after* converse.js
+#. has been initialized and with it the i18n machinery. That's why
+#. we do it here in the "initialize" method and not at the top of
+#. the module.
+#: dist/converse-no-dependencies.js:23863
+msgid "unencrypted"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23864
+msgid "unverified"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23865
+msgid "verified"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23866
+msgid "finished"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23882
+msgid "Don't have a chat account?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23884
+msgid "Create an account"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23896
+msgid "Create your account"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23898
+msgid "Please enter the XMPP provider to register with:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23920
+msgid "Already have a chat account?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23922
+msgid "Log in here"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23932
+msgid "Account Registration:"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23940
+msgid "Register"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23944
+msgid "Choose a different provider"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:23956
+msgid "Hold tight, we're fetching the registration form…"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24091
+msgid " e.g. conversejs.org"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24137
+msgid "Fetch registration form"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24138
+msgid "Tip: A list of public XMPP providers is available"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24139
+msgid "here"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24187
+msgid "Sorry, we're unable to connect to your chosen provider."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24203
+msgid ""
+"Sorry, the given provider does not support in band account registration. "
+"Please try with a different provider."
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24227
+#, javascript-format
+msgid ""
+"Something went wrong while establishing a connection with \"%1$s\". Are you "
+"sure it exists?"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24390
+msgid "Now logging you in"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24394
+msgid "Registered successfully"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24503
+msgid ""
+"The provider rejected your registration attempt. Please check the values you "
+"entered for correctness."
+msgstr ""
+
+#. workaround for Prosody which doesn't give type "headline"
+#: dist/converse-no-dependencies.js:24949
+#: dist/converse-no-dependencies.js:24955
+#, javascript-format
+msgid "Notification from %1$s"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:24957
+#: dist/converse-no-dependencies.js:24968
+#: dist/converse-no-dependencies.js:24971
+#, javascript-format
+msgid "%1$s says"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25005
+msgid "has come online"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25022
+msgid "wants to be your contact"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25347
+#: dist/converse-no-dependencies.js:25703
+msgid "Minimize this chat box"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25493
+msgid "Click to restore this chat"
+msgstr ""
+
+#: dist/converse-no-dependencies.js:25680
+msgid "Minimized"
+msgstr ""

File diff suppressed because it is too large
+ 235 - 235
locale/uk/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 0 - 0
locale/zh_CN/LC_MESSAGES/converse.json


File diff suppressed because it is too large
+ 292 - 292
locale/zh_CN/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 282 - 282
locale/zh_TW/LC_MESSAGES/converse.po


File diff suppressed because it is too large
+ 334 - 325
package-lock.json


+ 4 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "converse.js",
-  "version": "3.3.3",
+  "version": "3.3.4",
   "description": "Browser based XMPP instant messaging client",
   "main": "main.js",
   "directories": {
@@ -77,5 +77,7 @@
     "wait-until-promise": "^1.0.0",
     "xss": "^0.3.3"
   },
-  "dependencies": {}
+  "dependencies": {
+    "npm": "^5.7.1"
+  }
 }

+ 1 - 1
sass/_fonts.scss

@@ -68,7 +68,7 @@
     .icon-italic:before         { content: "\e04f"; }
     .icon-key:before            { content: "\e028"; }
     .icon-legal:before          { content: "\f0e3"; }
-    .icon-lock-2:before         { content: "\e027"; }
+    .icon-lock:before           { content: "\e027"; }
     .icon-minus:before          { content: "\e05a"; }
     .icon-music:before          { content: "\266b"; }
     .icon-newtab:before         { content: "\e053"; }

+ 26 - 12
spec/chatroom.js

@@ -1423,16 +1423,15 @@
                     var from_jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
                     var room_jid = 'lounge@localhost';
                     var reason = "Please join this chat room";
-                    var message = $(
-                        "<message from='"+from_jid+"' to='"+_converse.bare_jid+"'>" +
-                            "<x xmlns='jabber:x:conference'" +
-                                "jid='"+room_jid+"'" +
-                                "reason='"+reason+"'/>"+
-                        "</message>"
-                    )[0];
+
                     expect(_converse.chatboxes.models.length).toBe(1);
                     expect(_converse.chatboxes.models[0].id).toBe("controlbox");
-                    _converse.onDirectMUCInvitation(message);
+
+                    var stanza = Strophe.xmlHtmlNode(
+                        '<message xmlns="jabber:client" to="'+_converse.bare_jid+'" from="'+from_jid+'" id="9bceb415-f34b-4fa4-80d5-c0d076a24231">'+
+                            '<x xmlns="jabber:x:conference" jid="'+room_jid+'" reason="'+reason+'"/>'+
+                        '</message>').firstChild;
+                    _converse.onDirectMUCInvitation(stanza);
                     expect(window.confirm).toHaveBeenCalledWith(
                         name + ' has invited you to join a chat room: '+ room_jid +
                         ', and left the following reason: "'+reason+'"');
@@ -3142,26 +3141,41 @@
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
 
+                var sendIQ = _converse.connection.sendIQ;
+                var sent_stanza, IQ_id;
+                spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
+                    sent_stanza = iq;
+                    IQ_id = sendIQ.bind(this)(iq, callback, errback);
+                });
+
                 test_utils.openControlBox();
                 var panel = _converse.chatboxviews.get('controlbox').roomspanel;
                 $(panel.tabs).find('li').last().find('a')[0].click(); // Click the chatrooms tab
                 panel.model.set({'muc_domain': 'muc.localhost'}); // Make sure the domain is set
                 // See: http://xmpp.org/extensions/xep-0045.html#disco-rooms
-                expect($('#available-chatrooms').children('dt').length).toBe(0);
-                expect($('#available-chatrooms').children('dd').length).toBe(0);
+                expect(document.querySelectorAll('#available-chatrooms dt').length).toBe(0);
+                expect(document.querySelectorAll('#available-chatrooms dd').length).toBe(0);
+                document.querySelector('input#show-rooms').click();
+
+                expect(sent_stanza.toLocaleString()).toBe(
+                    "<iq to='muc.localhost' from='dummy@localhost/resource' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                        "<query xmlns='http://jabber.org/protocol/disco#items'/>"+
+                    "</iq>"
+                );
 
                 var iq = $iq({
                     from:'muc.localhost',
                     to:'dummy@localhost/pda',
+                    id: IQ_id,
                     type:'result'
                 }).c('query')
                   .c('item', { jid:'heath@chat.shakespeare.lit', name:'A Lonely Heath'}).up()
                   .c('item', { jid:'coven@chat.shakespeare.lit', name:'A Dark Cave'}).up()
                   .c('item', { jid:'forres@chat.shakespeare.lit', name:'The Palace'}).up()
                   .c('item', { jid:'inverness@chat.shakespeare.lit', name:'Macbeth&apos;s Castle'}).nodeTree;
+                _converse.connection._dataRecv(test_utils.createRequest(iq));
 
-                panel.onRoomsFound(iq);
-                expect($(panel.el.querySelector('#available-chatrooms')).children('dt').length).toBe(1);
+                expect(document.querySelectorAll('#available-chatrooms dt').length).toBe(1);
                 expect($(panel.el.querySelector('#available-chatrooms')).children('dt').first().text()).toBe("Rooms found");
                 expect($(panel.el.querySelector('#available-chatrooms')).children('dd').length).toBe(4);
                 done();

+ 27 - 0
spec/presence.js

@@ -45,6 +45,33 @@
                 "</presence>"
             );
         }));
+
+        it("includes the saved status message",
+            mock.initConverseWithPromises(
+                null, ['rosterGroupsFetched'], {},
+                function (done, _converse) {
+
+            test_utils.openControlBox();
+            var view = _converse.xmppstatusview;
+            spyOn(view.model, 'sendPresence').and.callThrough();
+            spyOn(_converse.connection, 'send').and.callThrough();
+
+            view.el.querySelector('a.change-xmpp-status-message').click();
+            var msg = 'My custom status';
+            view.el.querySelector('input.custom-xmpp-status').value = msg;
+            view.el.querySelector('[type="submit"]').click();
+            expect(view.model.sendPresence).toHaveBeenCalled();
+
+            expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString())
+                .toBe("<presence xmlns='jabber:client'><status>My custom status</status><priority>0</priority></presence>")
+
+            view.el.querySelector('a.choose-xmpp-status').click();
+            view.el.querySelectorAll('.dropdown dd ul li a')[1].click(); // Change status to "dnd"
+
+            expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString())
+                .toBe("<presence xmlns='jabber:client'><show>dnd</show><status>My custom status</status><priority>0</priority></presence>")
+            done();
+        }));
     });
 
     describe("A received presence stanza", function () {

+ 2 - 2
src/converse-bookmarks.js

@@ -539,8 +539,8 @@
                         _converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid)
                     ]).then((args) => {
                         resolve(args[0] && (args[1].supported || _converse.allow_public_bookmarks));
-                    });
-                });
+                    }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
             }
 
             const initBookmarks = function () {

+ 1 - 0
src/converse-chatview.js

@@ -249,6 +249,7 @@
                 render () {
                     this.el.innerHTML = tpl_chatbox_head(
                         _.extend(this.model.toJSON(), {
+                            '_converse': _converse,
                             'avatar_width': _converse.chatview_avatar_width,
                             'avatar_height': _converse.chatview_avatar_height,
                             'info_close': __('Close this chat box'),

+ 8 - 7
src/converse-core.js

@@ -310,9 +310,9 @@
             keepalive: true,
             locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
             locales: [
-                'af', 'ca', 'de', 'es', 'en', 'fr', 'he',
+                'af', 'bg', 'ca', 'de', 'es', 'en', 'fr', 'he',
                 'hu', 'id', 'it', 'ja', 'nb', 'nl',
-                'pl', 'pt_BR', 'ru', 'uk', 'zh_CN', 'zh_TW'
+                'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'
             ],
             message_carbons: true,
             message_storage: 'session',
@@ -870,9 +870,10 @@
             },
 
             initialize (attributes) {
-                const { jid } = attributes;
-                const bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
-                const resource = Strophe.getResourceFromJid(jid);
+                const { jid } = attributes,
+                      bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase(),
+                      resource = Strophe.getResourceFromJid(jid);
+
                 attributes.jid = bare_jid;
                 this.set(_.assignIn({
                     'fullname': bare_jid,
@@ -1503,7 +1504,7 @@
             constructPresence (type, status_message) {
                 let presence;
                 type = _.isString(type) ? type : (this.get('status') || _converse.default_state);
-                status_message = _.isString(status_message) ? status_message : undefined;
+                status_message = _.isString(status_message) ? status_message : this.get('status_message');
                 // Most of these presence types are actually not explicitly sent,
                 // but I add all of them here for reference and future proofing.
                 if ((type === 'unavailable') ||
@@ -2027,6 +2028,6 @@
             'utils': u
         }
     };
-    window.dispatchEvent(new Event('converse-loaded'));
+    window.dispatchEvent(new CustomEvent('converse-loaded'));
     return window.converse;
 }));

+ 2 - 1
src/converse-disco.js

@@ -55,7 +55,7 @@
                     this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](
                         b64_sha1(`converse.features-${this.get('jid')}`)
                     );
-                    this.features.on('add', this.onFeatureAdded);
+                    this.features.on('add', this.onFeatureAdded, this);
 
                     this.identities = new Backbone.Collection();
                     this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](
@@ -118,6 +118,7 @@
                 },
 
                 onFeatureAdded (feature) {
+                    feature.entity = this;
                     _converse.emit('serviceDiscovered', feature);
                 },
 

+ 1 - 1
src/converse-fullscreen.js

@@ -21,7 +21,7 @@
     converse.plugins.add('converse-fullscreen', {
 
         enabled (_converse) {
-            return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
+            return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
         },
 
         overrides: {

+ 1 - 1
src/converse-mam.js

@@ -119,7 +119,7 @@
 
     converse.plugins.add('converse-mam', {
 
-        dependencies: ['converse-chatview', 'converse-muc'],
+        dependencies: ['converse-chatview', 'converse-muc', 'converse-muc-views'],
 
         overrides: {
             // Overrides mentioned here will be picked up by converse.js's

+ 1 - 1
src/converse-minimize.js

@@ -39,7 +39,7 @@
          *
          * NB: These plugins need to have already been loaded via require.js.
          */
-        dependencies: ["converse-chatview", "converse-controlbox", "converse-muc", "converse-headline"],
+        dependencies: ["converse-chatview", "converse-controlbox", "converse-muc", "converse-muc-views", "converse-headline"],
 
         enabled (_converse) {
             return _converse.view_mode == 'overlayed';

+ 4 - 2
src/converse-muc-views.js

@@ -12,6 +12,7 @@
     define([
         "converse-core",
         "bootstrap",
+        "emojione",
         "tpl!add_chatroom_modal",
         "tpl!chatarea",
         "tpl!chatroom",
@@ -38,6 +39,7 @@
 }(this, function (
     converse,
     bootstrap,
+    emojione,
     tpl_add_chatroom_modal,
     tpl_chatarea,
     tpl_chatroom,
@@ -93,7 +95,7 @@
          * If the setting "strict_plugin_dependencies" is set to true,
          * an error will be raised if the plugin is not found.
          */
-        dependencies: ["converse-modal", "converse-controlbox"],
+        dependencies: ["converse-modal", "converse-controlbox", "converse-chatview"],
 
         overrides: {
 
@@ -109,7 +111,6 @@
                         }))()
                     });
                     this.roomspanel.model.fetch();
-
                     this.el.querySelector('.controlbox-pane').insertAdjacentElement(
                         'beforeEnd', this.roomspanel.render().el);
 
@@ -949,6 +950,7 @@
                      * Parameters:
                      *  (String) text: The message text to be sent.
                      */
+                    text = emojione.shortnameToUnicode(text)
                     const msgid = _converse.connection.getUniqueId();
                     const msg = $msg({
                         to: this.model.get('jid'),

+ 2 - 3
src/converse-muc.js

@@ -13,14 +13,13 @@
     define([
             "form-utils",
             "converse-core",
-            "lodash.fp",
             "converse-chatview",
             "converse-disco",
             "backbone.overview",
             "backbone.orderedlistview",
             "backbone.vdomview"
     ], factory);
-}(this, function (u, converse, fp) {
+}(this, function (u, converse) {
     "use strict";
 
     const MUC_ROLE_WEIGHTS = {
@@ -353,7 +352,7 @@
                  *  (XMLElement) message: The message stanza containing the
                  *        invitation.
                  */
-                const x_el = message.querySelector('x[xmlns="jabber:x:conference"]'),
+                const x_el = sizzle('x[xmlns="jabber:x:conference"]', message).pop(),
                     from = Strophe.getBareJidFromJid(message.getAttribute('from')),
                     room_jid = x_el.getAttribute('jid'),
                     reason = x_el.getAttribute('reason');

+ 1 - 3
src/converse-otr.js

@@ -452,9 +452,7 @@
                     });
                     this.el.querySelector('.chat-toolbar').insertAdjacentHTML(
                         'beforeend',
-                        tpl_toolbar_otr(
-                            _.extend(this.model.toJSON(), options || {})
-                        ));
+                        tpl_toolbar_otr(_.extend(data, options || {})));
                 },
 
                 getToolbarOptions (options) {

+ 1 - 1
src/converse-roomslist.js

@@ -141,7 +141,7 @@
                     'click .close-room': 'closeRoom',
                     'click .open-rooms-toggle': 'toggleRoomsList',
                     'click .remove-bookmark': 'removeBookmark',
-                    'click a.open-room': 'openRoom',
+                    'click .open-room': 'openRoom',
                 },
                 listSelector: '.rooms-list',
                 ItemView: _converse.RoomsListElementView,

+ 1 - 0
src/converse.js

@@ -15,6 +15,7 @@ if (typeof define !== 'undefined') {
         "converse-muc",         // XEP-0045 Multi-user chat
         "converse-muc-views",   // Views related to MUC
         "converse-muc-embedded",
+        "converse-muc-views",
         "converse-vcard",       // XEP-0054 VCard-temp
         "converse-otr",         // Off-the-record encryption for one-on-one messages
         "converse-register",    // XEP-0077 In-band registration

+ 2 - 0
src/i18n.js

@@ -15,6 +15,7 @@
         "lodash.noconflict",
         "moment",
         'moment/locale/af',
+        'moment/locale/bg',
         'moment/locale/ca',
         'moment/locale/de',
         'moment/locale/es',
@@ -29,6 +30,7 @@
         'moment/locale/pl',
         'moment/locale/pt-br',
         'moment/locale/ru',
+        'moment/locale/tr',
         'moment/locale/uk',
         'moment/locale/zh-cn',
         'moment/locale/zh-tw'

+ 11 - 0
src/polyfill.js

@@ -1,3 +1,14 @@
+function CustomEvent ( event, params ) {
+    params = params || { bubbles: false, cancelable: false, detail: undefined };
+    var evt = document.createEvent( 'CustomEvent' );
+    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+    return evt;
+}
+if ( typeof window.CustomEvent !== "function" ) {
+    CustomEvent.prototype = window.Event.prototype;
+    window.CustomEvent = CustomEvent;
+}
+
 if (!String.prototype.includes) {
   String.prototype.includes = function(search, start) {
         'use strict';

+ 1 - 1
src/start.frag

@@ -2,7 +2,7 @@
  *
  *  An XMPP chat client that runs in the browser.
  *
- *  Version: 3.3.3
+ *  Version: 3.3.4
  */
 
 /* jshint ignore:start */

+ 1 - 1
src/templates/chatroom_features.html

@@ -3,7 +3,7 @@
 {[ } ]}
 <ul class="features-list">
 {[ if (o.passwordprotected) { ]}
-<li class="feature" title="{{{ o.tt_passwordprotected }}}"><span class="icon-lock-2"></span>{{{ o.label_passwordprotected }}}</li>
+<li class="feature" title="{{{ o.tt_passwordprotected }}}"><span class="icon-lock"></span>{{{ o.label_passwordprotected }}}</li>
 {[ } ]}
 {[ if (o.unsecured) { ]}
 <li class="feature" title="{{{ o.tt_unsecured }}}"><span class="icon-unlocked"></span>{{{ o.label_unsecured }}}</li>

+ 1 - 0
src/templates/toolbar_otr.html

@@ -1,5 +1,6 @@
 {[ if (o.allow_otr)  { ]}
     <li class="toggle-toolbar-menu toggle-otr {{{o.otr_status_class}}}" title="{{{o.otr_tooltip}}}">
+        <span class="chat-toolbar-text">{{{o.otr_translated_status}}}</span>
         {[ if (o.otr_status == o.UNENCRYPTED) { ]}
             <span class="icon-unlocked"></span>
         {[ } ]}

+ 7 - 7
tests/transpiled.html

@@ -4,15 +4,15 @@
 <head>
     <title>Converse.js Tests</title>
     <meta name="description" content="Converse.js: A chat client for your website" />
-    <link rel="shortcut icon" type="image/png" href="node_modules/jasmine-core/images/jasmine_favicon.png">
+    <link rel="shortcut icon" type="image/png" href="../node_modules/jasmine-core/images/jasmine_favicon.png">
 
-    <link rel="stylesheet" type="text/css" media="screen" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
-    <link rel="stylesheet" type="text/css" media="screen" href="css/jasmine.css">
-    <link type="text/css" rel="stylesheet" media="screen" href="css/theme.css" />
-    <link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" />
+    <link rel="stylesheet" type="text/css" media="screen" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
+    <link rel="stylesheet" type="text/css" media="screen" href="../css/jasmine.css">
+    <link type="text/css" rel="stylesheet" media="screen" href="../css/theme.css" />
+    <link type="text/css" rel="stylesheet" media="screen" href="../css/converse.css" />
 
-    <script src="src/config.js"></script>
-    <script data-main="tests/runner-transpiled" src="node_modules/requirejs/require.js"></script>
+    <script src="../src/config.js"></script>
+    <script data-main="runner-transpiled" src="../node_modules/requirejs/require.js"></script>
 
     <style>
         .tests-brand-heading {

Some files were not shown because too many files changed in this diff