diff --git a/include/class.plugin.php b/include/class.plugin.php
index 9d15bd3595a97adac8c6f0c67d45152ea8cb159b..d565b90594e34150278e698fdfc4b30595689f05 100644
--- a/include/class.plugin.php
+++ b/include/class.plugin.php
@@ -550,7 +550,10 @@ abstract class Plugin {
         $P = new Phar($phar);
         $sig = $P->getSignature();
         $info = array();
-        if ($r = dns_get_record($sig['hash'].'.'.self::$verify_domain, DNS_TXT)) {
+        $ignored = null;
+        if ($r = dns_get_record($sig['hash'].'.'.self::$verify_domain.'.',
+            DNS_TXT, $ignored, $ignored, true)
+        ) {
             foreach ($r as $rec) {
                 foreach (explode(';', $rec['txt']) as $kv) {
                     list($k, $v) = explode('=', trim($kv));
diff --git a/include/cli/modules/i18n.php b/include/cli/modules/i18n.php
index f4c06caec1e1c34e7cb615ccb78957256b1a97b5..2adb14a9051d758dfd678631f3fe3fa37dcaa330 100644
--- a/include/cli/modules/i18n.php
+++ b/include/cli/modules/i18n.php
@@ -40,6 +40,12 @@ class i18n_Compiler extends Module {
             'help' => 'Add a domain to the path/context of PO strings'),
         'dns' => array('-d', '--dns', 'default' => false, 'metavar' => 'zone-id',
             'help' => 'Write signature to DNS (via this AWS HostedZoneId)'),
+        'zlib' => array('-z', '--zlib', 'default' => false,
+            'action' => 'store_true', 'help' => 'Compress PHAR with zlib'),
+        'bzip2' => array('-j', '--bzip2', 'default' => false,
+            'action' => 'store_true', 'help' => 'Compress PHAR with bzip2'),
+        'branch' => array('-b', '--branch', 'help' => 'Use a Crowdin branch
+            (other than the root)'),
     );
 
     var $epilog = "Note: If updating DNS, you will need to set
@@ -100,7 +106,7 @@ class i18n_Compiler extends Module {
                 $this->fail('API key is required');
             if (!$options['lang'])
                 $this->fail('Language code is required. See `list`');
-            $this->_build($options['lang']);
+            $this->_build($options['lang'], $options);
             break;
         case 'similar':
             $this->find_similar($options);
@@ -146,7 +152,7 @@ class i18n_Compiler extends Module {
         }
     }
 
-    function _build($lang) {
+    function _build($lang, $options) {
         list($code, $zip) = $this->_request("download/$lang.zip");
 
         if ($code !== 200)
@@ -164,19 +170,34 @@ class i18n_Compiler extends Module {
         @unlink(I18N_DIR."$lang.phar");
         $phar = new Phar(I18N_DIR."$lang.phar");
         $phar->startBuffering();
+        if ($options['zlib'])
+            $phar->compress(Phar::GZ, 'phar');
+        if ($options['bzip2'])
+            $phar->compress(Phar::BZ2, 'phar');
 
         $po_file = false;
 
+        $branch = false;
+        if ($options['branch'])
+            $branch = trim($options['branch'], '/') . '/';
         for ($i=0; $i<$zip->numFiles; $i++) {
             $info = $zip->statIndex($i);
+            if ($branch && strpos($info['name'], $branch) !== 0) {
+                // Skip files not part of the named branch
+                continue;
+            }
             $contents = $zip->getFromIndex($i);
             if (!$contents)
                 continue;
-            if (strpos($info['name'], '/messages.po') !== false) {
+            if (fnmatch('*/messages*.po', $info['name']) !== false) {
                 $po_file = $contents;
                 // Don't add the PO file as-is to the PHAR file
                 continue;
             }
+            elseif (!$branch && !file_exists(I18N_DIR . 'en_US/' . $info['name'])) {
+                // Skip files in (other) branches
+                continue;
+            }
             $phar->addFromString($info['name'], $contents);
         }
 
@@ -190,9 +211,9 @@ class i18n_Compiler extends Module {
         }
         foreach ($langs as $l) {
             list($code, $js) = $this->_http_get(
-                'http://imperavi.com/webdownload/redactor/lang/?lang='
-                .strtolower($l));
-            if ($code == 200 && ($js != 'File not found')) {
+                sprintf('https://imperavi.com/download/redactor/langs/%s/',
+                    strtolower($l)));
+            if ($code == 200 && strlen($js) > 100) {
                 $phar->addFromString('js/redactor.js', $js);
                 break;
             }
@@ -277,7 +298,9 @@ class i18n_Compiler extends Module {
         $po_header = Mail_Parse::splitHeaders($mo['']);
         $info = array(
             'Build-Date' => date(DATE_RFC822),
+            'Phrases-Version' => $po_header['X-Osticket-Major-Version'],
             'Build-Version' => trim(`git describe`),
+            'Build-Major-Version' => MAJOR_VERSION,
             'Language' => $po_header['Language'],
             #'Phrases' =>
             #'Translated' =>
@@ -308,6 +331,8 @@ class i18n_Compiler extends Module {
 
         if (!function_exists('openssl_get_privatekey'))
             $this->fail('OpenSSL extension required for signing');
+        if (!$options['pkey'] || !file_exists($options['pkey']))
+            $this->fail('Signing private key (-P) required');
         $private = openssl_get_privatekey(
                 file_get_contents($options['pkey']));
         if (!$private)
diff --git a/include/staff/system.inc.php b/include/staff/system.inc.php
index ee70faefb3dc4fd878342e65edf65bf28865d34f..20198b8f88c040d7592a9d5c512bb25c3fc5029b 100644
--- a/include/staff/system.inc.php
+++ b/include/staff/system.inc.php
@@ -171,18 +171,24 @@ if (!$lv) { ?>
 <?php
     foreach (Internationalization::availableLanguages() as $info) {
         $p = $info['path'];
-        if ($info['phar']) $p = 'phar://' . $p;
-        if (file_exists($p . '/MANIFEST.php')) {
-            $manifest = (include $p . '/MANIFEST.php'); ?>
+        if ($info['phar'])
+            $p = 'phar://' . $p;
+?>
     <h3><strong><?php echo Internationalization::getLanguageDescription($info['code']); ?></strong>
         &mdash; <?php echo $manifest['Language']; ?>
-<?php       if ($info['phar'])
-                Plugin::showVerificationBadge($info['path']);
-            ?>
+<?php   if ($info['phar'])
+            Plugin::showVerificationBadge($info['path']); ?>
         </h3>
-        <div><?php echo __('Version'); ?>: <?php echo $manifest['Version']; ?>,
-            <?php echo __('Built'); ?>: <?php echo $manifest['Build-Date']; ?>
+        <div><?php echo sprintf('<code>%s</code> — %s', $info['code'],
+                str_replace(ROOT_DIR, '', $info['path'])); ?>
+<?php   if (file_exists($p . '/MANIFEST.php')) {
+            $manifest = (include $p . '/MANIFEST.php'); ?>
+            <br/> <?php echo __('Version'); ?>: <?php echo $manifest['Version'];
+                ?>, <?php echo sprintf(__('for version %s'),
+                    'v'.($manifest['Phrases-Version'] ?: '1.9')); ?>
+            <br/> <?php echo __('Built'); ?>: <?php echo $manifest['Build-Date']; ?>
+<?php   } ?>
         </div>
-<?php }
+<?php
     } ?>
 </div>
diff --git a/scp/css/scp.css b/scp/css/scp.css
index 2b12d668b35e890300911594ede78abbd0fc131c..86632ba2766ff353f499c2c13b1d4b8b60d68b16 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -2322,7 +2322,9 @@ tr.disabled th {
 }
 
 .label {
-    float: right;
+    display: inline-block;
+    position: relative;
+    bottom: 1px;
     margin-bottom: 4px;
     font-size: 11px;
     padding: 0px 7px;