diff --git a/include/ajax.config.php b/include/ajax.config.php
index c263bd4a253993240b27e4557060b1fadc689ae1..a4e11bf22ab1ea5bebbab361604edbf71e569065 100644
--- a/include/ajax.config.php
+++ b/include/ajax.config.php
@@ -46,7 +46,7 @@ class ConfigAjaxAPI extends AjaxController {
               'has_rtl'         => $rtl,
               'lang_flag'       => strtolower($info['flag'] ?: $locale ?: $sl),
               'primary_lang_flag' => strtolower($primary_info['flag'] ?: $primary_locale ?: $primary_sl),
-              'primary_language' => $primary,
+              'primary_language' => Internationalization::rfc1766($primary),
               'secondary_languages' => $cfg->getSecondaryLanguages(),
               'page_size'       => $thisstaff->getPageLimit(),
         );
@@ -70,7 +70,7 @@ class ConfigAjaxAPI extends AjaxController {
             'lang'            => $lang,
             'short_lang'      => $sl,
             'has_rtl'         => $rtl,
-            'primary_language' => $cfg->getPrimaryLanguage(),
+            'primary_language' => Internationalization::rfc1766($cfg->getPrimaryLanguage()),
             'secondary_languages' => $cfg->getSecondaryLanguages(),
         );
 
diff --git a/include/class.i18n.php b/include/class.i18n.php
index 94f6b679c41587f2c3c43272f6aa5b80137d2586..27486ba9b3db761ba91752cac6436f589094a690 100644
--- a/include/class.i18n.php
+++ b/include/class.i18n.php
@@ -408,6 +408,15 @@ class Internationalization {
         return $locale;
     }
 
+    static function rfc1766($what) {
+        if (is_array($what))
+            return array_map(array(get_called_class(), 'rfc1766'), $what);
+
+        $lr = explode('_', $what);
+        if (isset($lr[1]))
+            $lr[1] = strtoupper($lr[1]);
+        return implode('-', $lr);
+    }
 
     static function getTtfFonts() {
         if (!class_exists('Phar'))
diff --git a/include/client/header.inc.php b/include/client/header.inc.php
index db6e4006c2b72d9d8a06036189b3f35b65c6634f..c49e896395633f3b8a63e8eae3b62797a417592c 100644
--- a/include/client/header.inc.php
+++ b/include/client/header.inc.php
@@ -8,11 +8,17 @@ $signout_url = ROOT_PATH . "logout.php?auth=".$ost->getLinkToken();
 header("Content-Type: text/html; charset=UTF-8");
 ?>
 <!DOCTYPE html>
-<html <?php
+<html<?php
 if (($lang = Internationalization::getCurrentLanguage())
         && ($info = Internationalization::getLanguageInfo($lang))
         && (@$info['direction'] == 'rtl'))
-    echo 'dir="rtl" class="rtl"';
+    echo ' dir="rtl" class="rtl"';
+if ($lang) {
+    $langs = array_unique(array($lang, $cfg->getPrimaryLanguage()));
+    $langs = Internationalization::rfc1766($langs);
+    echo ' lang="' . $lang . '"';
+    header("Content-Language: ".implode(', ', $langs));
+}
 ?>>
 <head>
     <meta charset="utf-8">
@@ -48,6 +54,25 @@ if (($lang = Internationalization::getCurrentLanguage())
     if($ost && ($headers=$ost->getExtraHeaders())) {
         echo "\n\t".implode("\n\t", $headers)."\n";
     }
+
+    // Offer alternate links for search engines
+    // @see https://support.google.com/webmasters/answer/189077?hl=en
+    if (($all_langs = Internationalization::getConfiguredSystemLanguages())
+        && (count($all_langs) > 1)
+    ) {
+        $langs = Internationalization::rfc1766(array_keys($all_langs));
+        $qs = array();
+        parse_str($_SERVER['QUERY_STRING'], $qs);
+        foreach ($langs as $L) {
+            $qs['lang'] = $L; ?>
+        <link rel="alternate" href="//<?php echo $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; ?>?<?php
+            echo http_build_query($qs); ?>" hreflang="<?php echo $L; ?>" />
+<?php
+        } ?>
+        <link rel="alternate" href="//<?php echo $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; ?>"
+            hreflang="x-default";
+<?php
+    }
     ?>
 </head>
 <body>
diff --git a/include/staff/header.inc.php b/include/staff/header.inc.php
index 0945a916441d42a0b97f7034ced1bca34036983f..0e7bf469cb0f435d257b5bf40fd48f3068482073 100644
--- a/include/staff/header.inc.php
+++ b/include/staff/header.inc.php
@@ -2,11 +2,14 @@
 header("Content-Type: text/html; charset=UTF-8");
 if (!isset($_SERVER['HTTP_X_PJAX'])) { ?>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html <?php
+<html<?php
 if (($lang = Internationalization::getCurrentLanguage())
         && ($info = Internationalization::getLanguageInfo($lang))
         && (@$info['direction'] == 'rtl'))
-    echo 'dir="rtl" class="rtl"';
+    echo ' dir="rtl" class="rtl"';
+if ($lang) {
+    echo ' lang="' . Internationalization::rfc1766($lang) . '"';
+}
 ?>>
 <head>
     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
diff --git a/include/staff/templates/content-manage.tmpl.php b/include/staff/templates/content-manage.tmpl.php
index 3fa4e8fcbd8c1554649c576d84f3ba74e74e4eca..e90b8ff874719aad5e688dc446e9ebd2df506319 100644
--- a/include/staff/templates/content-manage.tmpl.php
+++ b/include/staff/templates/content-manage.tmpl.php
@@ -27,7 +27,8 @@ if (count($langs) > 1) { ?>
         class="tab_content left-tabs" style="padding:0" lang="<?php echo $cfg->getPrimaryLanguage(); ?>">
     <div class="error"><?php echo $errors['name']; ?></div>
     <input type="text" style="width: 100%; font-size: 14pt" name="name" value="<?php
-        echo Format::htmlchars($info['title']); ?>" />
+    echo Format::htmlchars($info['title']); ?>" spellcheck="true"
+        lang="<?php echo $cfg->getPrimaryLanguage(); ?>" />
     <div style="margin-top: 5px">
     <div class="error"><?php echo $errors['body']; ?></div>
     <textarea class="richtext no-bar" name="body"
@@ -46,7 +47,8 @@ if (count($langs) > 1) { ?>
     <input type="text" style="width: 100%; font-size: 14pt"
         name="trans[<?php echo $tag; ?>][title]" value="<?php
         echo Format::htmlchars($trans['title']); ?>"
-        placeholder="<?php echo __('Title'); ?>" />
+        placeholder="<?php echo __('Title'); ?>"  spellcheck="true"
+        lang="<?php echo $tag; ?>" />
     <div style="margin-top: 5px">
     <textarea class="richtext no-bar" data-direction=<?php echo $nfo['direction']; ?>
         data-root-context="<?php echo $content->getType(); ?>"
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 35fb34acacdc3334b36e1ffd7381ad9d82b72bd3..1bd831a38ee245e6b82adca315094aaf2c874b8f 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -433,7 +433,7 @@ $tcount = $ticket->getThreadEntries($types)->count();
     </ul>
     <?php
     if ($role->hasPerm(TicketModel::PERM_REPLY)) { ?>
-    <form id="reply" class="tab_content" action="tickets.php?id=<?php
+    <form id="reply" class="tab_content spellcheck" action="tickets.php?id=<?php
         echo $ticket->getId(); ?>" name="reply" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
@@ -622,7 +622,7 @@ $tcount = $ticket->getThreadEntries($types)->count();
     </form>
     <?php
     } ?>
-    <form id="note" class="hidden tab_content" action="tickets.php?id=<?php
+    <form id="note" class="hidden tab_content spellcheck" action="tickets.php?id=<?php
         echo $ticket->getId(); ?>#note" name="note" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
@@ -705,7 +705,7 @@ $tcount = $ticket->getThreadEntries($types)->count();
    </form>
     <?php
     if ($role->hasPerm(TicketModel::PERM_TRANSFER)) { ?>
-    <form id="transfer" class="hidden tab_content" action="tickets.php?id=<?php
+    <form id="transfer" class="hidden tab_content spellcheck" action="tickets.php?id=<?php
         echo $ticket->getId(); ?>#transfer" name="transfer" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="ticket_id" value="<?php echo $ticket->getId(); ?>">
@@ -766,7 +766,7 @@ $tcount = $ticket->getThreadEntries($types)->count();
     } ?>
     <?php
     if ($role->hasPerm(TicketModel::PERM_ASSIGN)) { ?>
-    <form id="assign" class="hidden tab_content" action="tickets.php?id=<?php
+    <form id="assign" class="hidden tab_content spellcheck" action="tickets.php?id=<?php
          echo $ticket->getId(); ?>#assign" name="assign" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
diff --git a/js/redactor-osticket.js b/js/redactor-osticket.js
index 23b1ee76a4aaed7305df84ed4f974294dbe53139..19ff52a6acb6906f9fca184f7f16fa40e2fc33e5 100644
--- a/js/redactor-osticket.js
+++ b/js/redactor-osticket.js
@@ -268,6 +268,12 @@ $(function() {
                 'tabFocus': false,
                 'toolbarFixedBox': true,
                 'focusCallback': function() { this.$box.addClass('no-pjax'); },
+                'initCallback': function() {
+                    this.$editor.attr('spellcheck', 'true');
+                    var lang = this.$editor.closest('[lang]').attr('lang');
+                    if (lang)
+                        this.$editor.attr('lang', lang);
+                },
                 'linkSize': 100000,
                 'definedLinks': 'ajax.php/config/links'
             }, options||{});
diff --git a/scp/js/jquery.translatable.js b/scp/js/jquery.translatable.js
index 08a28ae3c7e030fdf20c79a6882a6dfd55974019..08f754a1a5e85c0d50f9759edb458b1a2e7e8a7e 100644
--- a/scp/js/jquery.translatable.js
+++ b/scp/js/jquery.translatable.js
@@ -60,6 +60,7 @@
         .focus($.proxy(function() { this.addClass('focus'); }, this.$container))
         .blur($.proxy(function() { this.removeClass('focus'); }, this.$container));
       getConfig().then($.proxy(function(c) {
+        this.attr({'spellcheck': 'true', 'lang': c.primary_language})
         $('<span class="flag"></span>')
           .addClass('flag-' + c.primary_lang_flag)
           .insertAfter(this);
@@ -113,6 +114,8 @@
           .text(info.name)
           .prepend($('<span>').addClass('flag flag-'+info.flag))
           .append($('<input type="text" data-lang="'+lang+'">')
+            .attr('lang', lang)
+            .attr('spellcheck', 'true')
             .attr('dir', info.direction || 'ltr')
             .on('change keydown', $.proxy(this.showCommit, this))
             .val(text)
diff --git a/scp/js/scp.js b/scp/js/scp.js
index 24be12c76210a71a943c9c975995ad4802673c0d..502b7f06171a02f90eb2207df7c73867653d5b01 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -563,6 +563,16 @@ $(document).keydown(function(e) {
     }
 });
 
+
+$(document).on('focus', 'form.spellcheck textarea, form.spellcheck input[type=text]', function() {
+  var $this = $(this);
+  if ($this.attr('lang') !== undefined)
+    return;
+  var lang = $(this).closest('[lang]').attr('lang');
+  if (lang)
+    $(this).attr({'spellcheck':'true', 'lang': lang});
+});
+
 $.toggleOverlay = function (show) {
   if (typeof(show) === 'undefined') {
     return $.toggleOverlay(!$('#overlay').is(':visible'));