diff --git a/include/class.page.php b/include/class.page.php
index c533617d6126b04668d5927bf43cacf875c34cb8..5eea8eacd32cb941d0b094f757bc2cf3e79e7ce3 100644
--- a/include/class.page.php
+++ b/include/class.page.php
@@ -70,8 +70,13 @@ class Page {
     function getBody() {
         return $this->ht['body'];
     }
+    function getLocalBody() {
+        $tag = $this->getTranslateTag('body');
+        $T = CustomDataTranslation::translateArticle($tag);
+        return $T != $tag ? $T : $this->getBody();
+    }
     function getBodyWithImages() {
-        return Format::viewableImages($this->getBody(), ROOT_PATH.'image.php');
+        return Format::viewableImages($this->getLocalBody(), ROOT_PATH.'image.php');
     }
 
     function getNotes() {
@@ -102,6 +107,15 @@ class Page {
         return $this->ht['topics'];
     }
 
+    function getTranslateTag($subtag) {
+        return _H(sprintf('page.%s.%s', $subtag, $this->id));
+    }
+    function getLocal($subtag) {
+        $tag = $this->getTranslateTag($subtag);
+        $T = CustomDataTranslation::translate($tag);
+        return $T != $tag ? $T : $this->ht[$subtag];
+    }
+
     function update($vars, &$errors) {
 
         if(!$vars['isactive'] && $this->isInUse()) {
@@ -261,8 +275,8 @@ class Page {
 
         if($id) {
             $sql='UPDATE '.PAGE_TABLE.' SET '.$sql.' WHERE id='.db_input($id);
-            if(db_query($sql))
-                return true;
+            if (db_query($sql))
+                return $this->saveTranslations($vars, $errors);
 
             $errors['err']=sprintf(__('Unable to update %s.'), __('this site page'));
 
@@ -284,5 +298,44 @@ class Page {
 
         return false;
     }
+
+    function saveTranslations($vars, &$errors) {
+        global $thisstaff;
+
+        $tag = $this->getTranslateTag('body');
+        $translations = CustomDataTranslation::allTranslations($tag,'article');
+        foreach ($translations as $t) {
+            foreach ($vars['trans'] as $lang=>$content) {
+                if (strcasecmp($lang, $t->lang) !== 0)
+                    continue;
+                $content = Format::sanitize($content);
+                unset($vars['trans'][$lang]);
+                if ($content == $t->text)
+                    continue;
+                $t->text = $content;
+                $t->agent_id = $thisstaff->getId();
+                if (!$t->save())
+                    return false;
+            }
+        }
+        // New translations (?)
+        foreach ($vars['trans'] as $lang=>$content) {
+            $content = Format::sanitize($content);
+            if (!$content)
+                continue;
+            $t = CustomDataTranslation::create(array(
+                'type'      => 'article',
+                'object_hash' => $tag,
+                'lang'      => $lang,
+                'text'      => $content,
+                'revision'  => 1,
+                'agent_id'  => $thisstaff->getId(),
+                'updated'   => new SqlFunction('NOW'),
+            ));
+            if (!$t->save())
+                return false;
+        }
+        return true;
+    }
 }
 ?>
diff --git a/include/class.translation.php b/include/class.translation.php
index 4900bae82dc1d98c8721024785a0d3fe3884e58f..c4e606fdb0250039eacb3b89a15ea75b2416ce8b 100644
--- a/include/class.translation.php
+++ b/include/class.translation.php
@@ -902,7 +902,7 @@ class CustomDataTranslation extends VerySimpleModel {
         return $_cache[$locale] = $mo;
     }
 
-    static function translate($msgid, $locale=false, $cache=true) {
+    static function translate($msgid, $locale=false, $cache=true, $type='phrase') {
         global $thisstaff, $thisclient;
 
         if (!$locale
@@ -914,6 +914,12 @@ class CustomDataTranslation extends VerySimpleModel {
         elseif (is_object($locale) && method_exists($locale, 'getLanguage'))
             $locale = $locale->getLanguage();
 
+        else
+            $locale = Internationalization::getDefaultLanguage();
+
+        // Perhaps a slight optimization would be to check if the selected
+        // locale is also the system primary. If so, short-circuit
+
         if ($locale) {
             if ($cache) {
                 $mo = static::getTranslation($locale);
@@ -921,7 +927,7 @@ class CustomDataTranslation extends VerySimpleModel {
                     $msgid = $mo[$msgid]->text;
             }
             elseif ($p = static::lookup(array(
-                    'type' => 'phrase',
+                    'type' => $type,
                     'lang' => $locale,
                     'object_hash' => $msgid
             ))) {
@@ -931,9 +937,13 @@ class CustomDataTranslation extends VerySimpleModel {
         return $msgid;
     }
 
-    static function allTranslations($msgid) {
+    static function translateArticle($msgid, $locale=false) {
+        return static::translate($msgid, $locale, false, 'article');
+    }
+
+    static function allTranslations($msgid, $type='phrase') {
         return static::objects()->filter(array(
-            'type' => 'phrase',
+            'type' => $type,
             'object_hash' => $msgid
         ))->all();
     }
@@ -1025,9 +1035,6 @@ function _dcnpgettext($domain, $context, $singular, $plural, $category, $n) {
 function _H($tag) {
     return substr(md5($tag), -16);
 }
-function _C(Translatable $object) {
-    return $objet->getLocalName();
-}
 
 interface Translatable {
     function getTranslationTag();
diff --git a/include/staff/page.inc.php b/include/staff/page.inc.php
index 49f2cbea471ad5fa51e3cd9fa18092b076581070..714f8ce724d16da403b6f0fdc5679eea9843b554 100644
--- a/include/staff/page.inc.php
+++ b/include/staff/page.inc.php
@@ -15,8 +15,19 @@ if($page && $_REQUEST['a']!='add'){
     $info=$page->getHashtable();
     $info['body'] = Format::viewableImages($page->getBody());
     $info['notes'] = Format::viewableImages($info['notes']);
+    $trans['name'] = $page->getTranslateTag('name');
     $slug = Format::slugify($info['name']);
     $qstr.='&id='.$page->getId();
+    $translations = CustomDataTranslation::allTranslations(
+        $page->getTranslateTag('body'), 'article');
+    foreach ($cfg->getSecondaryLanguages() as $tag) {
+        foreach ($translations as $t) {
+            if (strcasecmp($t->lang, $tag) === 0) {
+                $info['trans'][$tag] = Format::viewableImages($t->text);
+                break;
+            }
+        }
+    }
 }else {
     $title=__('Add New Page');
     $action='add';
@@ -50,7 +61,8 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
               <?php echo __('Name'); ?>:
             </td>
             <td>
-                <input type="text" size="40" name="name" value="<?php echo $info['name']; ?>">
+                <input type="text" size="40" name="name" value="<?php echo $info['name']; ?>"
+                data-translate-tag="<?php echo $trans['name']; ?>"/>
                 &nbsp;<span class="error">*&nbsp;<?php echo $errors['name']; ?></span>
             </td>
         </tr>
@@ -96,30 +108,66 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
             </td>
         </tr>
         <tr>
-            <th colspan="2">
-                <em><?php echo __(
-                '<b>Page body</b>: Ticket variables are only supported in thank-you pages.'
-                ); ?><font class="error">*&nbsp;<?php echo $errors['body']; ?></font></em>
-            </th>
-        </tr>
-         <tr>
-            <td colspan=2 style="padding-left:3px;">
-                <textarea name="body" cols="21" rows="12" style="width:98%;" class="richtext draft"
+            <td colspan="2">
+                <ul class="tabs">
+                    <li><a class="active" href="#content"><?php echo __('Page Content'); ?></a></li>
+                    <li><a href="#notes"><?php echo __('Internal Notes'); ?></a></li>
+                </ul>
+    <div class="tab_content active" id="content">
+<?php if ($page && ($langs = $cfg->getSecondaryLanguages())) { ?>
+        <div class="banner">&nbsp;
+        <span class="pull-left">
+            <i class="icon-globe icon-large"></i>
+            <?php echo __('This content is translatable'); ?>
+        </span>
+        <span class="pull-right">
+        <?php echo __('View'); ?>:
+        <select onchange="javascript:
+$('option', this).each(function(){$($(this).val()).hide()});
+$($('option:selected', this).val()).show(); ">
+            <option value="#reference-text"><?php echo
+            Internationalization::getLanguageDescription($cfg->getPrimaryLanguage());
+            ?> — <?php echo __('Primary'); ?></option>
+<?php   foreach ($langs as $tag) { ?>
+            <option value="#translation-<?php echo $tag; ?>"><?php echo
+            Internationalization::getLanguageDescription($tag);
+            ?></option>
+<?php   } ?>
+        </select>
+        </span>
+        </div>
+        <div class="clear"></div>
+<?php } ?>
+        <div id="reference-text"
+            lang="<?php echo $cfg->getPrimaryLanguage(); ?>">
+        <textarea name="body" cols="21" rows="12" style="width:98%;" class="richtext draft"
 <?php
     list($draft, $attrs) = Draft::getDraftAndDataAttrs('page', $info['id'], $info['body']);
     echo $attrs; ?>><?php echo $draft ?: $info['body']; ?></textarea>
-            </td>
-        </tr>
-        <tr>
-            <th colspan="2">
-                <em><strong><?php echo __('Internal Notes'); ?></strong>:
-                <?php echo __("be liberal, they're internal"); ?></em>
-            </th>
-        </tr>
-        <tr>
-            <td colspan=2>
-                <textarea class="richtext no-bar" name="notes" cols="21"
-                    rows="8" style="width: 80%;"><?php echo $info['notes']; ?></textarea>
+        </div>
+
+<?php if ($langs && $page) {
+    foreach ($langs as $tag) { ?>
+        <div id="translation-<?php echo $tag; ?>" style="display:none" lang="<?php echo $tag; ?>">
+        <textarea name="trans[<?php echo $tag; ?>]" cols="21" rows="12"
+            style="width:98%;" class="richtext"
+            ><?php echo $info['trans'][$tag]; ?></textarea>
+        </div>
+<?php }
+} ?>
+
+        <div class="error" style="margin: 5px 0"><?php echo $errors['body']; ?></div>
+        <div id="msg_info"><em><i class="icon-info-sign"></i> <?php
+            echo __(
+                'Ticket variables are only supported in thank-you pages.'
+        ); ?></em></div>
+    </div>
+    <div class="tab_content" style="display:none" id="notes">
+        <em><strong><?php echo __('Internal Notes'); ?></strong>:
+        <?php echo __("be liberal, they're internal"); ?></em>
+        <textarea class="richtext no-bar" name="notes" cols="21"
+            rows="8" style="width: 80%;"><?php echo $info['notes']; ?></textarea>
+    </div>
             </td>
         </tr>
     </tbody>
diff --git a/scp/css/scp.css b/scp/css/scp.css
index 2fe63818d17da1f6514482d6b93a69b27c96791b..dab7b3a6774a12e81708d1f8184bb44c15fbe699 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -67,6 +67,8 @@ div#header a {
     color: #555;
 }
 
+.banner { margin: 0; padding: 5px 5px 11px; margin-bottom: 10px; color: #444; border: 1px solid #444;  background-color: #ddd; border-radius: 4px; }
+
 #msg_info,
 .info-banner { margin: 0; padding: 5px; margin-bottom: 10px; color: #3a87ad; border: 1px solid #bce8f1;  background-color: #d9edf7; }