diff --git a/include/class.orm.php b/include/class.orm.php
index 50b0a3046448ce95b1d5a3842ee0a7ca40727c42..80c009cf031772f4098febcda4f8e9a8b6325cb7 100644
--- a/include/class.orm.php
+++ b/include/class.orm.php
@@ -698,7 +698,7 @@ class VerySimpleModel {
         return $pk;
     }
 
-    function __getDbFields() {
+    function getDbFields() {
         return $this->ht;
     }
 }
@@ -721,7 +721,7 @@ class AnnotatedModel {
         }
         if (!isset($classes[$class])) {
             $classes[$class] = eval(<<<END_CLASS
-class AnnotatedModel___{$class}_{$extra}
+class {$extra}AnnotatedModel___{$class}
 extends {$class} {
     var \$__overlay__;
     use {$extra}AnnotatedModelTrait;
@@ -731,7 +731,7 @@ extends {$class} {
         \$this->__overlay__ = \$annotations;
     }
 }
-return "AnnotatedModel___{$class}_{$extra}";
+return "{$extra}AnnotatedModel___{$class}";
 END_CLASS
             );
         }
@@ -758,8 +758,8 @@ trait AnnotatedModelTrait {
         return parent::__isset($what);
     }
 
-    function __getDbFields() {
-        return $this->__overlay__ + parent::__getDbFields();
+    function getDbFields() {
+        return $this->__overlay__ + parent::getDbFields();
     }
 }
 
@@ -791,12 +791,12 @@ trait WriteableAnnotatedModelTrait {
         return parent::__isset($what);
     }
 
-    function __getDbFields() {
-        return $this->__overlay__->__getDbFields() + parent::__getDbFields();
+    function getDbFields() {
+        return $this->__overlay__->getDbFields() + parent::getDbFields();
     }
 
-    function save() {
-        $this->__overlay__->save();
+    function save($refetch=false) {
+        $this->__overlay__->save($refetch);
         return parent::save();
     }
 
diff --git a/include/class.queue.php b/include/class.queue.php
index 12b7a6e3fc7c4ea78be704c54fbb6efa4db6cd71..0aea1330d1114afbcb36e54ae5becba1a450ae7e 100644
--- a/include/class.queue.php
+++ b/include/class.queue.php
@@ -153,6 +153,7 @@ class CustomQueue extends SavedSearch {
                 $col->set('sort', array_search($key, $order));
                 $col->set('heading', $info['heading']);
                 $col->set('width', $info['width']);
+                $col->setSortable($info['sortable']);
                 unset($new[$key]);
             }
             // Add new columns
@@ -164,6 +165,7 @@ class CustomQueue extends SavedSearch {
                     'width' => $info['width'] ?: 100
                 ));
                 $glue->queue = $this;
+                $glue->setSortable($info['sortable']);
                 $this->columns->add(
                     QueueColumn::lookup($info['column_id']), $glue);
             }
@@ -668,6 +670,8 @@ extends VerySimpleModel {
         'ordering' => array('name'),
     );
 
+    const FLAG_SORTABLE = 0x0001;
+
     var $_annotations;
     var $_conditions;
 
@@ -710,6 +714,24 @@ extends VerySimpleModel {
         return $this->getLocal('heading');
     }
 
+    protected function setFlag($flag, $value=true, $field='flags') {
+        return $value
+            ? $this->{$field} |= $flag
+            : $this->clearFlag($flag, $field);
+    }
+
+    protected function clearFlag($flag, $field='flags') {
+        return $this->{$field} &= ~$flag;
+    }
+
+    function isSortable() {
+        return $this->bits & self::FLAG_SORTABLE;
+    }
+
+    function setSortable($sortable) {
+        $this->setFlag(self::FLAG_SORTABLE, $sortable, 'bits');
+    }
+
     function render($row) {
         // Basic data
         $text = $this->renderBasicValue($row);
@@ -810,7 +832,7 @@ extends VerySimpleModel {
     }
 
     function getDataConfigForm($source=false) {
-        return new QueueColDataConfigForm($source ?: $this->__getDbFields(),
+        return new QueueColDataConfigForm($source ?: $this->getDbFields(),
             array('id' => $this->id));
     }
 
diff --git a/include/staff/queue.inc.php b/include/staff/queue.inc.php
index 36d90cf34036205442ba0baea38ab3680308c66a..1967c3cf106ca504d9f2b241b9e1b235cf46dd0c 100644
--- a/include/staff/queue.inc.php
+++ b/include/staff/queue.inc.php
@@ -130,7 +130,7 @@ else {
     <table class="table two-column">
       <tbody>
         <tr class="header">
-          <th colspan="2">
+          <th colspan="3">
             <?php echo __("Manage columns in this queue"); ?>
             <div><small><?php echo __(
             "Add, remove, and customize the content of the columns in this queue using the options below. Click a column header to manage or resize it"); ?>
@@ -138,40 +138,46 @@ else {
           </th>
         </tr>
         <tr class="header">
-          <td><small><b><?php echo __('Column Name'); ?></b></small></td>
-          <td><small><b><?php echo __('Heading and Width'); ?></b></small></td>
+          <td style="width:36%"><small><b><?php echo __('Heading and Width'); ?></b></small></td>
+          <td><small><b><?php echo __('Column Details'); ?></b></small></td>
+          <td><small><b><?php echo __('Sortable'); ?></b></small></td>
         </tr>
       </tbody>
       <tbody class="sortable-rows">
         <tr id="column-template" class="hidden">
           <td>
             <i class="faded-more icon-sort"></i>
-            <input type="hidden" data-name="queue_id"
-              value="<?php echo $queue->getId(); ?>"/>
-            <input type="hidden" data-name="column_id" />
-            <span></span>
-          </td>
-          <td>
             <input type="text" size="25" data-name="heading"
               data-translate-tag="" />
             <input type="text" size="5" data-name="width" />
-            <a class="action-button"
+          </td>
+          <td>
+            <input type="hidden" data-name="queue_id"
+              value="<?php echo $queue->getId(); ?>"/>
+            <input type="hidden" data-name="column_id" />
+            <div>
+            <a class="inline action-button"
                 href="#" onclick="javascript:
                 var colid = $(this).closest('tr').find('[data-name=column_id]').val();
                 $.dialog('ajax.php/tickets/search/column/edit/' + colid, 201);
                 return false;
-                "><i class="icon-edit"></i> <?php echo __('Edit'); ?></a>
+                "><i class="icon-cog"></i> <?php echo __('Config'); ?></a>
+            <span></span>
+          </td>
+          <td>
+            <input type="checkbox" data-name="sortable">
             <a href="#" class="pull-right drop-column" title="<?php echo __('Delete');
               ?>"><i class="icon-trash"></i></a>
+            </div>
           </td>
         </tr>
       </tbody>
       <tbody>
         <tr class="header">
-          <td colspan="2"></td>
+          <td colspan="3"></td>
         </tr>
         <tr>
-          <td colspan="2" id="append-column">
+          <td colspan="3" id="append-column">
             <i class="icon-plus-sign"></i>
             <select id="add-column" data-quick-add="queue-column">
               <option value="">— <?php echo __('Add a column'); ?> —</option>
@@ -231,8 +237,12 @@ var addColumn = function(colid, info) {
     var $this = $(this),
         name = $this.data('name');
 
-    if (info[name] !== undefined)
-      $this.val(info[name]);
+    if (info[name] !== undefined) {
+      if ($this.is(':checkbox'))
+        $this.prop('checked', info[name]);
+      else
+        $this.val(info[name]);
+    }
     $this.attr('name', name_prefix + '[' + name + ']');
   });
   copy.find('span').text(info['name']);
@@ -264,14 +274,16 @@ $('#append-column').find('button').on('click', function() {
       id = parseInt(selected.val());
   if (!id)
       return;
-  addColumn(id, {name: selected.text(), heading: selected.text(), width: 100});
+  addColumn(id, {name: selected.text(), heading: selected.text(), width: 100, sortable: 1});
   return false;
 });
 
 <?php foreach ($queue->columns as $C) {
-  echo sprintf('addColumn(%d, {name: %s, heading: %s, width: %d, trans: %s});',
+  echo sprintf('addColumn(%d, {name: %s, heading: %s, width: %d, trans: %s,
+  sortable: %s});',
     $C->column_id, JsonDataEncoder::encode($C->name),
     JsonDataEncoder::encode($C->heading), $C->width,
-    JsonDataEncoder::encode($C->getTranslateTag('heading')));
+    JsonDataEncoder::encode($C->getTranslateTag('heading')),
+    $C->isSortable() ? 1 : 0);
 } ?>
 </script>
diff --git a/include/staff/templates/queue-tickets.tmpl.php b/include/staff/templates/queue-tickets.tmpl.php
index 49a8125755f97eb5c8c9b461c30249c9b1926fa2..99238c950b1b9254eda60dfeff786b38fe91a9a4 100644
--- a/include/staff/templates/queue-tickets.tmpl.php
+++ b/include/staff/templates/queue-tickets.tmpl.php
@@ -120,9 +120,35 @@ if ($canManageTickets) { ?>
         <th style="width:12px"></th>
 <?php 
 }
+if (isset($_GET['sort'])) {
+    $sort = $_SESSION['sort'][$queue->getId()] = array(
+        'col' => (int) $_GET['sort'],
+        'dir' => (int) $_GET['dir'],
+    );
+}
+else {
+    $sort = $_SESSION['sort'][$queue->getId()];
+}
 foreach ($columns as $C) {
-    echo sprintf('<th width="%s">%s</th>', $C->getWidth(),
-        Format::htmlchars($C->getLocalHeading()));
+    $heading = Format::htmlchars($C->getLocalHeading());
+    if ($C->isSortable()) {
+        $args = $_GET;
+        $dir = $sort['col'] != $C->id ?: ($sort['dir'] ? 'desc' : 'asc');
+        $args['dir'] = $sort['col'] != $C->id ?: (int) !$sort['dir'];
+        $args['sort'] = $C->id;
+        $heading = sprintf('<a href="?%s" class="%s">%s</a>',
+            Http::build_query($args), $dir, $heading);
+    }
+    echo sprintf('<th width="%s" data-id="%d">%s</th>',
+        $C->getWidth(), $C->id, $heading);
+
+    // Sort by this column ?
+    if ($sort['col'] == $C->id) {
+        $col = SavedSearch::getOrmPath($C->primary, $query);
+        if ($sort['dir'])
+            $col = '-' . $col;
+        $tickets = $tickets->order_by($col);
+    }
 } ?>
     </tr>
   </thead>
diff --git a/include/upgrader/streams/core/98ad7d55-00000000.patch.sql b/include/upgrader/streams/core/98ad7d55-00000000.patch.sql
index 4993af2fdca44fe614f4efb5eccdaf7e135852f3..bc3ca35cd33896243eccb6f3d4bb3d7e58ef0f38 100644
--- a/include/upgrader/streams/core/98ad7d55-00000000.patch.sql
+++ b/include/upgrader/streams/core/98ad7d55-00000000.patch.sql
@@ -32,8 +32,14 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%queue_columns`;
 CREATE TABLE `%TABLE_PREFIX%queue_columns` (
   `queue_id` int(11) unsigned NOT NULL,
   `column_id` int(11) unsigned NOT NULL,
+  `bits` int(10) unsigned NOT NULL DEFAULT '0',
   `sort` int(10) unsigned NOT NULL DEFAULT '1',
   `heading` varchar(64) DEFAULT NULL,
   `width` int(10) unsigned NOT NULL DEFAULT '100',
   PRIMARY KEY (`queue_id`, `column_id`)
 ) DEFAULT CHARSET=utf8;
+
+-- Finished with patch
+UPDATE `%TABLE_PREFIX%config`
+    SET `value` = '00000000000000000000000000000000'
+    WHERE `key` = 'schema_signature' AND `namespace` = 'core';
diff --git a/scp/js/jquery.translatable.js b/scp/js/jquery.translatable.js
index 41b28a16972f0272a9053dcce82a529e76426671..a7784624c03f77a1ac690a13d0eb59712132b577 100644
--- a/scp/js/jquery.translatable.js
+++ b/scp/js/jquery.translatable.js
@@ -41,9 +41,8 @@
       this.$footer = $('<div class="add-translation"></div>');
       this.$select = $('<select name="locale"></select>');
       this.$menu = $(this.options.menu).appendTo('body');
-      this.$container = $('<div class="translatable"></div>')
-          .prependTo(this.$element.parent())
-          .append(this.$element);
+      this.$element.wrap('<div class="translatable"></div>');
+      this.$container = this.$element.parent();
       if (this.$element.width() > 100)
           this.$element.width(this.$element.width()-35);
       this.$container.wrap('<div style="display:inline-block;position:relative;width:auto;white-space:nowrap;"></div>');
diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql
index 1a39a4a34d778bb8627648fe9e5c5697667aeabc..28ed813984c86f132f73275f61182a7323ac7637 100644
--- a/setup/inc/streams/core/install-mysql.sql
+++ b/setup/inc/streams/core/install-mysql.sql
@@ -860,6 +860,7 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%queue_columns`;
 CREATE TABLE `%TABLE_PREFIX%queue_columns` (
   `queue_id` int(11) unsigned NOT NULL,
   `column_id` int(11) unsigned NOT NULL,
+  `bits` int(10) unsigned NOT NULL DEFAULT '0',
   `sort` int(10) unsigned NOT NULL DEFAULT '1',
   `heading` varchar(64) DEFAULT NULL,
   `width` int(10) unsigned NOT NULL DEFAULT '100',