浏览代码

HUE-760 [beeswax] Backend i18n

Enrico Berti 13 年之前
父节点
当前提交
28a0eaf

+ 18 - 18
apps/beeswax/src/beeswax/conf.py

@@ -17,88 +17,88 @@
 """Configuration options for the Hive UI (Beeswax)."""
 from desktop.lib.conf import Config, coerce_bool
 import os.path
+from django.utils.translation import ugettext_lazy as _
 
 BEESWAX_SERVER_HOST = Config(
   key="beeswax_server_host",
-  help="Host where beeswax server thrift daemon is running",
+  help=_("Host where beeswax server thrift daemon is running"),
   private=True,
   default="localhost")
 
 BEESWAX_SERVER_PORT = Config(
   key="beeswax_server_port",
-  help="Configure the port the beeswax thrift server runs on",
+  help=_("Configure the port the beeswax thrift server runs on"),
   default=8002,
   type=int)
 
 BEESWAX_META_SERVER_HOST = Config(
   key="beeswax_meta_server_host",
-  help="Host where beeswax internal metastore thrift daemon is running",
+  help=_("Host where beeswax internal metastore thrift daemon is running"),
   private=True,
   default="localhost")
 
 BEESWAX_META_SERVER_PORT = Config(
   key="beeswax_meta_server_port",
-  help="Configure the port the internal metastore daemon runs on. Used only if "
-       "hive.metastore.local is true.",
+  help=_("Configure the port the internal metastore daemon runs on. Used only if "
+       "hive.metastore.local is true."),
   default=8003,
   type=int)
 
 BEESWAX_SERVER_BIN = Config(
   key="beeswax_server_bin",
-  help="Path to beeswax_server.sh",
+  help=_("Path to beeswax_server.sh"),
   private=True,
   default=os.path.join(os.path.dirname(__file__), "..", "..", "beeswax_server.sh"))
 
 BEESWAX_SERVER_HEAPSIZE = Config(
   key="beeswax_server_heapsize",
-  help="Maximum Java heapsize (in megabytes) used by Beeswax Server.  " + \
+  help=_("Maximum Java heapsize (in megabytes) used by Beeswax Server.  " + \
     "Note that the setting of HADOOP_HEAPSIZE in $HADOOP_CONF_DIR/hadoop-env.sh " + \
-    "may override this setting.",
+    "may override this setting."),
   default="1000")
 
 BEESWAX_HIVE_HOME_DIR = Config(
   key="hive_home_dir",
   default=os.environ.get("HIVE_HOME", "/usr/lib/hive"),
-  help=("Path to the root of the Hive installation; " +
-        "defaults to environment variable when not set.")
-)
+  help=_("Path to the root of the Hive installation; " +
+        "defaults to environment variable when not set."))
 
 BEESWAX_HIVE_CONF_DIR = Config(
   key='hive_conf_dir',
-  help='Hive configuration directory, where hive-site.xml is located',
+  help=_('Hive configuration directory, where hive-site.xml is located'),
   default=os.environ.get("HIVE_CONF_DIR", '/etc/hive/conf'))
 
 LOCAL_EXAMPLES_DATA_DIR = Config(
   key='local_examples_data_dir',
   default=os.path.join(os.path.dirname(__file__), "..", "..", "data"),
-  help='The local filesystem path containing the beeswax examples')
+  help=_('The local filesystem path containing the beeswax examples'))
 
 BEESWAX_SERVER_CONN_TIMEOUT = Config(
   key='beeswax_server_conn_timeout',
   default=120,
   type=int,
-  help='Timeout in seconds for thrift calls to beeswax service')
+  help=_('Timeout in seconds for thrift calls to beeswax service'))
 
 METASTORE_CONN_TIMEOUT= Config(
   key='metastore_conn_timeout',
   default=10,
   type=int,
-  help='Timeouts in seconds for thrift calls to the hive metastore. This timeout should take into account that the metastore could talk to an external DB')
+  help=_('Timeouts in seconds for thrift calls to the hive metastore. This timeout should take into account that the metastore could talk to an external DB'))
 
 BEESWAX_RUNNING_QUERY_LIFETIME = Config(
   key='beeswax_running_query_lifetime',
   default=604800000L, # 7*24*60*60*1000 (1 week)
   type=long,
-  help='Time in seconds for beeswax to persist queries in its cache.')
+  help=_('Time in seconds for beeswax to persist queries in its cache.'))
 
 BROWSE_PARTITIONED_TABLE_LIMIT = Config(
   key='browse_partitioned_table_limit',
   default=250,
   type=int,
-  help='Set a LIMIT clause when browsing a partitioned table. A positive value will be set as the LIMIT. If 0 or negative, do not set any limit.')
+  help=_('Set a LIMIT clause when browsing a partitioned table. A positive value will be set as the LIMIT. If 0 or negative, do not set any limit.'))
 
 SHARE_SAVED_QUERIES = Config(
   key='share_saved_queries',
   default=True,
   type=coerce_bool,
-  help='Share saved queries with all users. If set to false, saved queries are visible only to the owner and administrators.')
+  help=_('Share saved queries with all users. If set to false, saved queries are visible only to the owner and administrators.'))

+ 6 - 4
apps/beeswax/src/beeswax/create_table.py

@@ -35,6 +35,8 @@ from beeswax.views import describe_table, confirm_query, execute_directly
 from beeswax.views import make_beeswax_query
 from beeswax import db_utils
 
+from django.utils.translation import ugettext as _
+
 LOG = logging.getLogger(__name__)
 
 def index(request):
@@ -286,7 +288,7 @@ def _delim_preview(fs, file_form, encoding, file_types, delimiters):
                                                           file_type=file_type,
                                                           n_cols=n_cols))
   if not delim_form.is_valid():
-    assert False, 'Internal error when constructing the delimiter form'
+    assert False, _('Internal error when constructing the delimiter form')
   return fields_list, n_cols, delim_form
 
 
@@ -313,7 +315,7 @@ def _parse_fields(path, file_obj, encoding, filetypes, delimiters):
       return delim, reader.TYPE, fields_list
   else:
     # Even TextFileReader doesn't work
-    msg = "Failed to decode file '%s' into printable characters under %s" % (path, encoding,)
+    msg = _("Failed to decode file '%(path)s' into printable characters under %(encoding)s") % {'path': path, 'encoding': encoding}
     LOG.error(msg)
     raise PopupException(msg)
 
@@ -375,7 +377,7 @@ def _peek_file(fs, file_form):
     file_obj.close()
     return (path, file_head)
   except IOError, ex:
-    msg = "Failed to open file '%s': %s" % (path, ex)
+    msg = _("Failed to open file '%(path)s': %(error)s") % {'path': path, 'error': ex}
     LOG.exception(msg)
     raise PopupException(msg)
 
@@ -426,7 +428,7 @@ def load_after_create(request):
   tablename = request.REQUEST.get('table')
   path = request.REQUEST.get('path')
   if not tablename or not path:
-    msg = 'Internal error: Missing needed parameter to load data into table'
+    msg = _('Internal error: Missing needed parameter to load data into table')
     LOG.error(msg)
     raise PopupException(msg)
 

+ 5 - 4
apps/beeswax/src/beeswax/data_export.py

@@ -28,6 +28,7 @@ from beeswaxd.ttypes import QueryHandle
 
 from desktop.lib.export_csvxls import CSVformatter, XLSformatter, TooBigToDownloadException
 
+from django.utils.translation import ugettext as _
 
 LOG = logging.getLogger(__name__)
 
@@ -84,11 +85,11 @@ def data_generator(query_model, formatter):
     # Someone is reading the results concurrently. Abort.
     # But unfortunately, this current generator will produce incomplete data.
     if next_row != results.start_row:
-      msg = 'Error: Potentially incomplete results as an error occur during data retrieval.'
+      msg = _('Error: Potentially incomplete results as an error occur during data retrieval.')
       yield formatter.format_row([msg])
-      err = ('Detected another client retrieving results for %s. '
-             'Expect next row being %s and got %s. Aborting' %
-             (query_model.server_id, next_row, results.start_row))
+      err = (_('Detected another client retrieving results for %(server_id)s. '
+             'Expect next row being %(row)s and got %(start_row)s. Aborting') %
+             {'server_id': query_model.server_id, 'row': next_row, 'start_row': results.start_row})
       LOG.error(err)
       raise RuntimeError(err)
 

+ 4 - 2
apps/beeswax/src/beeswax/db_utils.py

@@ -37,6 +37,8 @@ from desktop.lib import thrift_util
 from hive_metastore import ThriftHiveMetastore
 from beeswaxd.ttypes import BeeswaxException, QueryHandle, QueryNotFoundException
 
+from django.utils.translation import ugettext_lazy as _
+
 LOG = logging.getLogger(__name__)
 
 def execute_directly(user, query_msg, design=None, notify=False):
@@ -64,8 +66,8 @@ def execute_directly(user, query_msg, design=None, notify=False):
     handle = db_client().query(query_msg)
     if not handle or not handle.id or not handle.log_context:
       # It really shouldn't happen
-      msg = "BeeswaxServer returning invalid handle for query id %d [%s]..." % \
-            (query_history.id, query_msg.query[:40])
+      msg = _("BeeswaxServer returning invalid handle for query id %(id)d [%(query)s]...") % \
+            {'id': query_history.id, 'query': query_msg.query[:40]}
       raise Exception(msg)
   except BeeswaxException, bex:
     # Kind of expected (hql compile/syntax error, etc.)

+ 45 - 43
apps/beeswax/src/beeswax/forms.py

@@ -26,6 +26,8 @@ from beeswax import models
 
 import filebrowser.forms
 
+from django.utils.translation import ugettext as _t
+
 def query_form():
   """Generates a multi form object for queries."""
   return MultiForm(
@@ -41,17 +43,17 @@ class SaveForm(forms.Form):
   name = forms.CharField(required=False,
                         max_length=64,
                         initial=models.SavedQuery.DEFAULT_NEW_DESIGN_NAME,
-                        help_text='Change the name to save as a new design')
-  desc = forms.CharField(required=False, max_length=1024, label="Description")
+                        help_text=_t('Change the name to save as a new design'))
+  desc = forms.CharField(required=False, max_length=1024, label=_t("Description"))
   save = forms.BooleanField(widget=SubmitButton, required=False)
   saveas = forms.BooleanField(widget=SubmitButton, required=False)
 
   def __init__(self, *args, **kwargs):
     forms.Form.__init__(self, *args, **kwargs)
-    self.fields['save'].label = 'Save'
-    self.fields['save'].widget.label = 'Save'
-    self.fields['saveas'].label = 'Save As'
-    self.fields['saveas'].widget.label = 'Save As'
+    self.fields['save'].label = _t('Save')
+    self.fields['save'].widget.label = _t('Save')
+    self.fields['saveas'].label = _t('Save As')
+    self.fields['saveas'].widget.label = _t('Save As')
 
   def clean_name(self):
     name = self.cleaned_data.get('name', '').strip()
@@ -64,7 +66,7 @@ class SaveForm(forms.Form):
     name = self.cleaned_data.get('name')
     if save and len(name) == 0:
       # Bother with name iff we're saving
-      raise forms.ValidationError('Please enter a name')
+      raise forms.ValidationError(_t('Please enter a name'))
     return self.cleaned_data
 
   def set_data(self, name, desc=''):
@@ -78,18 +80,18 @@ class SaveForm(forms.Form):
 class SaveResultsForm(DependencyAwareForm):
   """Used for saving the query result data"""
 
-  SAVE_TYPES = (SAVE_TYPE_TBL, SAVE_TYPE_DIR) = ('to a new table', 'to HDFS directory')
+  SAVE_TYPES = (SAVE_TYPE_TBL, SAVE_TYPE_DIR) = (_t('to a new table'), _t('to HDFS directory'))
   save_target = forms.ChoiceField(required=True,
                                   choices=common.to_choices(SAVE_TYPES),
                                   widget=forms.RadioSelect)
   target_table = common.HiveIdentifierField(
-                                  label="Table Name",
+                                  label=_t("Table Name"),
                                   required=False,
-                                  help_text="Name of the new table")
+                                  help_text=_t("Name of the new table"))
   target_dir = filebrowser.forms.PathField(
-                                  label="Results Location",
+                                  label=_t("Results Location"),
                                   required=False,
-                                  help_text="Empty directory in HDFS to put the results")
+                                  help_text=_t("Empty directory in HDFS to put the results"))
   dependencies = [
     ('save_target', SAVE_TYPE_TBL, 'target_table'),
     ('save_target', SAVE_TYPE_DIR, 'target_dir'),
@@ -100,14 +102,14 @@ class SaveResultsForm(DependencyAwareForm):
     if tbl:
       try:
         db_utils.meta_client().get_table("default", tbl)
-        raise forms.ValidationError('Table already exists')
+        raise forms.ValidationError(_t('Table already exists'))
       except hive_metastore.ttypes.NoSuchObjectException:
         pass
     return tbl
 
 
 class HQLForm(forms.Form):
-  query = forms.CharField(label="Query Editor",
+  query = forms.CharField(label=_t("Query Editor"),
                           required=True,
                           widget=forms.Textarea(attrs={'class':'beeswax_query'}))
   is_parameterized = forms.BooleanField(required=False, initial=True)
@@ -127,13 +129,13 @@ class FileResourceForm(forms.Form):
       ("JAR", "jar"),
       ("ARCHIVE", "archive"),
       ("FILE", "file"),
-    ], help_text="Resources to upload with your Hive job." +
+    ], help_text=_t("Resources to upload with your Hive job." +
        "  Use 'jar' for UDFs.  Use file and archive for "
-       "side files and MAP/TRANSFORM using.  Paths are on HDFS."
+       "side files and MAP/TRANSFORM using.  Paths are on HDFS.")
   )
   # TODO(philip): Could upload files here, too.  Or merely link
   # to upload utility?
-  path = forms.CharField(required=True, help_text="Path to file on HDFS.")
+  path = forms.CharField(required=True, help_text=_t("Path to file on HDFS."))
 
 FileResourceFormSet = simple_formset_factory(FileResourceForm)
 
@@ -156,8 +158,8 @@ class CreateTableForm(DependencyAwareForm):
   dependencies = []
 
   # Basic Data
-  name = common.HiveIdentifierField(label="Table Name", required=True)
-  comment = forms.CharField(label="Description", required=False)
+  name = common.HiveIdentifierField(label=_t("Table Name"), required=True)
+  comment = forms.CharField(label=_t("Description"), required=False)
 
   # Row Formatting
   row_format = forms.ChoiceField(required=True,
@@ -179,10 +181,10 @@ class CreateTableForm(DependencyAwareForm):
   ]
 
   # Serde Row
-  serde_name = forms.CharField(required=False, label="SerDe Name")
+  serde_name = forms.CharField(required=False, label=_t("SerDe Name"))
   serde_properties = forms.CharField(
                         required=False,
-                        help_text="Comma-separated list of key-value pairs, eg., 'p1=v1, p2=v2'")
+                        help_text=_t("Comma-separated list of key-value pairs, eg., 'p1=v1, p2=v2'"))
 
   dependencies += [
     ("row_format", "SerDe", "serde_name"),
@@ -193,8 +195,8 @@ class CreateTableForm(DependencyAwareForm):
   file_format = forms.ChoiceField(required=False, initial="TextFile",
                         choices=common.to_choices(["TextFile", "SequenceFile", "InputFormat"]),
                         widget=forms.RadioSelect)
-  input_format_class = forms.CharField(required=False, label="InputFormat Class")
-  output_format_class = forms.CharField(required=False, label="OutputFormat Class")
+  input_format_class = forms.CharField(required=False, label=_t("InputFormat Class"))
+  output_format_class = forms.CharField(required=False, label=_t("OutputFormat Class"))
 
   dependencies += [
     ("file_format", "InputFormat", "input_format_class"),
@@ -203,8 +205,8 @@ class CreateTableForm(DependencyAwareForm):
 
   # External?
   use_default_location = forms.BooleanField(required=False, initial=True,
-    label="Use default location")
-  external_location = forms.CharField(required=False, help_text="Path to HDFS directory or file of table data.")
+    label=_t("Use default location"))
+  external_location = forms.CharField(required=False, help_text=_t("Path to HDFS directory or file of table data."))
 
   dependencies += [
     ("use_default_location", False, "external_location")
@@ -226,28 +228,28 @@ class CreateTableForm(DependencyAwareForm):
 def _clean_tablename(name):
   try:
     db_utils.meta_client().get_table("default", name)
-    raise forms.ValidationError('Table "%s" already exists' % (name,))
+    raise forms.ValidationError(_t('Table "%(name)s" already exists') % {'name': name})
   except hive_metastore.ttypes.NoSuchObjectException:
     return name
 
 
 def _clean_terminator(val):
   if val is not None and len(val.decode('string_escape')) != 1:
-      raise forms.ValidationError('Terminator must be exactly one character')
+      raise forms.ValidationError(_t('Terminator must be exactly one character'))
   return val
 
 
 class CreateByImportFileForm(forms.Form):
   """Form for step 1 (specifying file) of the import wizard"""
   # Basic Data
-  name = common.HiveIdentifierField(label="Table Name", required=True)
-  comment = forms.CharField(label="Description", required=False)
+  name = common.HiveIdentifierField(label=_t("Table Name"), required=True)
+  comment = forms.CharField(label=_t("Description"), required=False)
 
   # File info
-  path = filebrowser.forms.PathField(label="Input File")
+  path = filebrowser.forms.PathField(label=_t("Input File"))
   do_import = forms.BooleanField(required=False, initial=True,
-                          label="Import data from file",
-                          help_text="Automatically load this file into the table after creation")
+                          label=_t("Import data from file"),
+                          help_text=_t("Automatically load this file into the table after creation"))
 
   def clean_name(self):
     return _clean_tablename(self.cleaned_data['name'])
@@ -263,7 +265,7 @@ class CreateByImportDelimForm(forms.Form):
     # ChoiceOrOtherField doesn't work with required=True
     delimiter = self.cleaned_data.get('delimiter')
     if not delimiter:
-      raise forms.ValidationError('Delimiter value is required')
+      raise forms.ValidationError(_t('Delimiter value is required'))
     _clean_terminator(delimiter)
     return self.cleaned_data
 
@@ -273,10 +275,10 @@ class CreateByImportDelimForm(forms.Form):
         chr(int(delimiter))
         return int(delimiter)
       except ValueError:
-        raise forms.ValidationError('Delimiter value must be smaller than 256')
+        raise forms.ValidationError(_t('Delimiter value must be smaller than 256'))
     val = delimiter.decode('string_escape')
     if len(val) != 1:
-      raise forms.ValidationError('Delimiter must be exactly one character')
+      raise forms.ValidationError(_t('Delimiter must be exactly one character'))
     return ord(val)
 
 
@@ -304,24 +306,24 @@ class ColumnTypeForm(DependencyAwareForm):
   column_type = forms.ChoiceField(required=True,
     choices=common.to_choices(HIVE_TYPES))
   array_type = forms.ChoiceField(required=False,
-    choices=common.to_choices(HIVE_PRIMITIVE_TYPES), label="Array Value Type")
+    choices=common.to_choices(HIVE_PRIMITIVE_TYPES), label=_t("Array Value Type"))
   map_key_type = forms.ChoiceField(required=False,
                                    choices=common.to_choices(HIVE_PRIMITIVE_TYPES),
-                                   help_text="Specify if column_type is map.")
+                                   help_text=_t("Specify if column_type is map."))
   map_value_type = forms.ChoiceField(required=False,
                                      choices=common.to_choices(HIVE_PRIMITIVE_TYPES),
-                                     help_text="Specify if column_type is map.")
+                                     help_text=_t("Specify if column_type is map."))
 
-ColumnTypeFormSet = simple_formset_factory(ColumnTypeForm, initial=[{}], add_label="add a column")
+ColumnTypeFormSet = simple_formset_factory(ColumnTypeForm, initial=[{}], add_label=_t("add a column"))
 # Default to no partitions
-PartitionTypeFormSet = simple_formset_factory(PartitionTypeForm, add_label="add a partition")
+PartitionTypeFormSet = simple_formset_factory(PartitionTypeForm, add_label=_t("add a partition"))
 
 
 class LoadDataForm(forms.Form):
   """Form used for loading data into an existing table."""
-  path = filebrowser.forms.PathField(label="Path")
+  path = filebrowser.forms.PathField(label=_t("Path"))
   overwrite = forms.BooleanField(required=False, initial=False,
-    label="Overwrite?")
+    label=_t("Overwrite?"))
 
   def __init__(self, table_obj, *args, **kwargs):
     """
@@ -334,6 +336,6 @@ class LoadDataForm(forms.Form):
       # We give these numeric names because column names
       # may be unpleasantly arbitrary.
       name = "partition_%d" % i
-      char_field = forms.CharField(required=True, label="%s (partition key with type %s)" % (column.name, column.type))
+      char_field = forms.CharField(required=True, label=_t("%(column_name)s (partition key with type %(column_type)s)") % {'column_name': column.name, 'column_type': column.type})
       self.fields[name] = char_field
       self.partition_columns[name] = column.name

+ 675 - 31
apps/beeswax/src/beeswax/locale/django.pot

@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PROJECT VERSION\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2012-07-03 01:12+0200\n"
+"POT-Creation-Date: 2012-07-21 11:58+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,6 +17,680 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 0.9.6\n"
 
+#: src/beeswax/conf.py:24
+msgid "Host where beeswax server thrift daemon is running"
+msgstr ""
+
+#: src/beeswax/conf.py:30
+msgid "Configure the port the beeswax thrift server runs on"
+msgstr ""
+
+#: src/beeswax/conf.py:36
+msgid "Host where beeswax internal metastore thrift daemon is running"
+msgstr ""
+
+#: src/beeswax/conf.py:42
+msgid ""
+"Configure the port the internal metastore daemon runs on. Used only if "
+"hive.metastore.local is true."
+msgstr ""
+
+#: src/beeswax/conf.py:49
+msgid "Path to beeswax_server.sh"
+msgstr ""
+
+#: src/beeswax/conf.py:55
+msgid ""
+"Maximum Java heapsize (in megabytes) used by Beeswax Server.  Note that "
+"the setting of HADOOP_HEAPSIZE in $HADOOP_CONF_DIR/hadoop-env.sh may "
+"override this setting."
+msgstr ""
+
+#: src/beeswax/conf.py:63
+msgid ""
+"Path to the root of the Hive installation; defaults to environment "
+"variable when not set."
+msgstr ""
+
+#: src/beeswax/conf.py:68
+msgid "Hive configuration directory, where hive-site.xml is located"
+msgstr ""
+
+#: src/beeswax/conf.py:74
+msgid "The local filesystem path containing the beeswax examples"
+msgstr ""
+
+#: src/beeswax/conf.py:80
+msgid "Timeout in seconds for thrift calls to beeswax service"
+msgstr ""
+
+#: src/beeswax/conf.py:86
+msgid ""
+"Timeouts in seconds for thrift calls to the hive metastore. This timeout "
+"should take into account that the metastore could talk to an external DB"
+msgstr ""
+
+#: src/beeswax/conf.py:92
+msgid "Time in seconds for beeswax to persist queries in its cache."
+msgstr ""
+
+#: src/beeswax/conf.py:98
+msgid ""
+"Set a LIMIT clause when browsing a partitioned table. A positive value "
+"will be set as the LIMIT. If 0 or negative, do not set any limit."
+msgstr ""
+
+#: src/beeswax/conf.py:104
+msgid ""
+"Share saved queries with all users. If set to false, saved queries are "
+"visible only to the owner and administrators."
+msgstr ""
+
+#: src/beeswax/create_table.py:291
+msgid "Internal error when constructing the delimiter form"
+msgstr ""
+
+#: src/beeswax/create_table.py:318
+#, python-format
+msgid ""
+"Failed to decode file '%(path)s' into printable characters under "
+"%(encoding)s"
+msgstr ""
+
+#: src/beeswax/create_table.py:380
+#, python-format
+msgid "Failed to open file '%(path)s': %(error)s"
+msgstr ""
+
+#: src/beeswax/create_table.py:431
+msgid "Internal error: Missing needed parameter to load data into table"
+msgstr ""
+
+#: src/beeswax/data_export.py:88
+msgid ""
+"Error: Potentially incomplete results as an error occur during data "
+"retrieval."
+msgstr ""
+
+#: src/beeswax/data_export.py:90
+#, python-format
+msgid ""
+"Detected another client retrieving results for %(server_id)s. Expect next"
+" row being %(row)s and got %(start_row)s. Aborting"
+msgstr ""
+
+#: src/beeswax/db_utils.py:69
+#, python-format
+msgid "BeeswaxServer returning invalid handle for query id %(id)d [%(query)s]..."
+msgstr ""
+
+#: src/beeswax/forms.py:46
+msgid "Change the name to save as a new design"
+msgstr ""
+
+#: src/beeswax/forms.py:47 src/beeswax/forms.py:162 src/beeswax/forms.py:246
+#: src/beeswax/templates/configuration.mako:37
+#: src/beeswax/templates/list_designs.mako:32
+msgid "Description"
+msgstr ""
+
+#: src/beeswax/forms.py:53 src/beeswax/forms.py:54
+#: src/beeswax/templates/execute.mako:54 src/beeswax/templates/execute.mako:289
+#: src/beeswax/templates/save_results.mako:43
+#: src/beeswax/templates/watch_results.mako:38
+#: src/beeswax/templates/watch_results.mako:156
+msgid "Save"
+msgstr ""
+
+#: src/beeswax/forms.py:55 src/beeswax/forms.py:56
+msgid "Save As"
+msgstr ""
+
+#: src/beeswax/forms.py:69
+msgid "Please enter a name"
+msgstr ""
+
+#: src/beeswax/forms.py:83
+msgid "to a new table"
+msgstr ""
+
+#: src/beeswax/forms.py:83
+msgid "to HDFS directory"
+msgstr ""
+
+#: src/beeswax/forms.py:88 src/beeswax/forms.py:161 src/beeswax/forms.py:245
+#: src/beeswax/templates/show_tables.mako:43
+#: src/beeswax/templates/watch_results.mako:139
+msgid "Table Name"
+msgstr ""
+
+#: src/beeswax/forms.py:90
+msgid "Name of the new table"
+msgstr ""
+
+#: src/beeswax/forms.py:92
+msgid "Results Location"
+msgstr ""
+
+#: src/beeswax/forms.py:94
+msgid "Empty directory in HDFS to put the results"
+msgstr ""
+
+#: src/beeswax/forms.py:105
+msgid "Table already exists"
+msgstr ""
+
+#: src/beeswax/forms.py:112 src/beeswax/templates/layout.mako:34
+msgid "Query Editor"
+msgstr ""
+
+#: src/beeswax/forms.py:132
+msgid ""
+"Resources to upload with your Hive job.  Use 'jar' for UDFs.  Use file "
+"and archive for side files and MAP/TRANSFORM using.  Paths are on HDFS."
+msgstr ""
+
+#: src/beeswax/forms.py:138
+msgid "Path to file on HDFS."
+msgstr ""
+
+#: src/beeswax/forms.py:184
+msgid "SerDe Name"
+msgstr ""
+
+#: src/beeswax/forms.py:187
+msgid "Comma-separated list of key-value pairs, eg., 'p1=v1, p2=v2'"
+msgstr ""
+
+#: src/beeswax/forms.py:198
+msgid "InputFormat Class"
+msgstr ""
+
+#: src/beeswax/forms.py:199
+msgid "OutputFormat Class"
+msgstr ""
+
+#: src/beeswax/forms.py:208
+#: src/beeswax/templates/create_table_manually.mako:236
+msgid "Use default location"
+msgstr ""
+
+#: src/beeswax/forms.py:209
+msgid "Path to HDFS directory or file of table data."
+msgstr ""
+
+#: src/beeswax/forms.py:231
+#, python-format
+msgid "Table \"%(name)s\" already exists"
+msgstr ""
+
+#: src/beeswax/forms.py:238
+msgid "Terminator must be exactly one character"
+msgstr ""
+
+#: src/beeswax/forms.py:249
+msgid "Input File"
+msgstr ""
+
+#: src/beeswax/forms.py:251
+msgid "Import data from file"
+msgstr ""
+
+#: src/beeswax/forms.py:252
+msgid "Automatically load this file into the table after creation"
+msgstr ""
+
+#: src/beeswax/forms.py:268
+msgid "Delimiter value is required"
+msgstr ""
+
+#: src/beeswax/forms.py:278
+msgid "Delimiter value must be smaller than 256"
+msgstr ""
+
+#: src/beeswax/forms.py:281
+msgid "Delimiter must be exactly one character"
+msgstr ""
+
+#: src/beeswax/forms.py:309
+msgid "Array Value Type"
+msgstr ""
+
+#: src/beeswax/forms.py:312 src/beeswax/forms.py:315
+msgid "Specify if column_type is map."
+msgstr ""
+
+#: src/beeswax/forms.py:317
+msgid "add a column"
+msgstr ""
+
+#: src/beeswax/forms.py:319
+msgid "add a partition"
+msgstr ""
+
+#: src/beeswax/forms.py:324
+msgid "Path"
+msgstr ""
+
+#: src/beeswax/forms.py:326
+msgid "Overwrite?"
+msgstr ""
+
+#: src/beeswax/forms.py:339
+#, python-format
+msgid "%(column_name)s (partition key with type %(column_type)s)"
+msgstr ""
+
+#: src/beeswax/models.py:124
+msgid "My saved query"
+msgstr ""
+
+#: src/beeswax/models.py:125
+msgid " (new)"
+msgstr ""
+
+#: src/beeswax/models.py:163
+#, python-format
+msgid "Cannot retrieve Beeswax design id %(id)s"
+msgstr ""
+
+#: src/beeswax/models.py:167
+#, python-format
+msgid "Design id %(id)s does not belong to user %(user)s"
+msgstr ""
+
+#: src/beeswax/models.py:172
+#, python-format
+msgid ""
+"Type mismatch for design id %(id)s (owner %(owner)s) - Expects "
+"%(expected_type)s got %(real_type)s"
+msgstr ""
+
+#: src/beeswax/views.py:68
+#, python-format
+msgid "Design %(id)s does not exist."
+msgstr ""
+
+#: src/beeswax/views.py:74
+#, python-format
+msgid "Cannot access design %(id)s"
+msgstr ""
+
+#: src/beeswax/views.py:85
+#, python-format
+msgid "QueryHistory %(id)s does not exist."
+msgstr ""
+
+#: src/beeswax/views.py:91
+#, python-format
+msgid "Cannot access QueryHistory %(id)s"
+msgstr ""
+
+#: src/beeswax/views.py:147
+#, python-format
+msgid "Do you really want to drop the view '%(table)s'?"
+msgstr ""
+
+#: src/beeswax/views.py:149
+#, python-format
+msgid ""
+"This may delete the underlying data as well as the metadata.  Drop table "
+"'%(table)s'?"
+msgstr ""
+
+#: src/beeswax/views.py:164
+#, python-format
+msgid "Failed to remove %(table)s.  Error: %(error)s"
+msgstr ""
+
+#: src/beeswax/views.py:165 src/beeswax/views.py:179
+msgid "Beeswax Error"
+msgstr ""
+
+#: src/beeswax/views.py:178
+#, python-format
+msgid "Failed to read table. Error: %(error)s"
+msgstr ""
+
+#: src/beeswax/views.py:232
+msgid "Design does not exist"
+msgstr ""
+
+#: src/beeswax/views.py:454
+msgid "Query is not parameterizable."
+msgstr ""
+
+#: src/beeswax/views.py:482
+msgid "Could not retrieve log."
+msgstr ""
+
+#: src/beeswax/views.py:484
+msgid "Unknown exception."
+msgstr ""
+
+#: src/beeswax/views.py:517
+#, python-format
+msgid "Invalid design type %(type)s"
+msgstr ""
+
+#: src/beeswax/views.py:545
+#, python-format
+msgid "Saved design \"%(name)s\""
+msgstr ""
+
+#: src/beeswax/views.py:679
+#, python-format
+msgid "Copied design: %(name)s"
+msgstr ""
+
+#: src/beeswax/views.py:731
+msgid "Beeswax query completed"
+msgstr ""
+
+#: src/beeswax/views.py:738
+#, python-format
+msgid ""
+"%(subject)s. You may see the results here: %(link)s\n"
+"\n"
+"Query:\n"
+"%(query)s"
+msgstr ""
+
+#: src/beeswax/views.py:784
+msgid "The result of this query has expired."
+msgstr ""
+
+#: src/beeswax/views.py:830
+msgid "Query is still being submitted to the Beeswax Server"
+msgstr ""
+
+#: src/beeswax/views.py:831
+msgid "Failed to retrieve query state from the Beeswax Server"
+msgstr ""
+
+#: src/beeswax/views.py:835
+msgid "Failed to contact Beeswax Server to check query status"
+msgstr ""
+
+#: src/beeswax/views.py:901
+#, python-format
+msgid "Trying to display result that is not yet ready. Query id %(id)s"
+msgstr ""
+
+#: src/beeswax/views.py:958
+msgid "This action is only available to the user who submitted the query."
+msgstr ""
+
+#: src/beeswax/views.py:968
+#, python-format
+msgid "This query has %(state)s. Results unavailable."
+msgstr ""
+
+#: src/beeswax/views.py:970
+msgid "The result of this query is not available yet."
+msgstr ""
+
+#: src/beeswax/views.py:987
+msgid "Cannot find query."
+msgstr ""
+
+#: src/beeswax/views.py:993
+msgid ""
+"Saving results from a partitioned table is not supported. You may copy "
+"from the HDFS location manually."
+msgstr ""
+
+#: src/beeswax/views.py:1000
+msgid ""
+"Saving results from a table to a directory is not supported. You may copy"
+" from the HDFS location manually."
+msgstr ""
+
+#: src/beeswax/views.py:1017
+msgid "The table could not be saved."
+msgstr ""
+
+#: src/beeswax/views.py:1025
+#, python-format
+msgid "Failed to save results from query: %(error)s"
+msgstr ""
+
+#: src/beeswax/views.py:1082
+#, python-format
+msgid "Saved query results as new table %(table)s"
+msgstr ""
+
+#: src/beeswax/views.py:1134
+msgid "Install sample tables and Beeswax examples?"
+msgstr ""
+
+#: src/beeswax/views.py:1153
+#, python-format
+msgid "Table '%(table)s' is not partitioned."
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:80
+msgid "Beeswax examples already installed"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:172
+#, python-format
+msgid "Cannot find table data in \"%(file)s\""
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:189
+#, python-format
+msgid "Table \"%(table)s\" already exists"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:197
+#, python-format
+msgid "Error creating table %(table)s: Operation timeout"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:201
+#, python-format
+msgid "Error creating table %(table)s: %(error)s"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:221
+#, python-format
+msgid "Error loading table %(table)s: Operation timeout"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:225
+#, python-format
+msgid "Error loading table %(table)s: %(error)s"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:246
+#, python-format
+msgid "Sample design %(name)s already exists"
+msgstr ""
+
+#: src/beeswax/report/report_gen.py:98
+#, python-format
+msgid "%(aggregation)s is not a valid aggregation"
+msgstr ""
+
+#: src/beeswax/report/report_gen.py:191
+#, python-format
+msgid "%(relation)s is not a valid operator"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:89
+msgid "Missing ManagementForm for conditions"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:186
+msgid "UnionMultiForm is not valid"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:217
+#, python-format
+msgid "%(field)s value not applicable with %(source)s source"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:221
+#, python-format
+msgid "%(field)s value missing"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:234
+msgid "Display"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:237
+#: src/beeswax/report/report_gen_views.py:393
+#: src/beeswax/report/report_gen_views.py:400
+msgid "Source"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:240
+msgid "Aggregate"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:243
+msgid "Distinct"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:246
+msgid "Constant value"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:249
+msgid "Table alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:251
+#: src/beeswax/report/report_gen_views.py:319
+msgid "From column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:253
+msgid "Column alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:255
+msgid "Sort"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:258
+msgid "Sort order"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:260
+msgid "Group order"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:265
+#: src/beeswax/report/report_gen_views.py:316
+msgid "From table"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:272
+msgid "Source must be \"table\" when not displaying column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:275
+msgid "Column alias not applicable when not displaying column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:278
+msgid "Source value missing"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:313
+#: src/beeswax/report/report_gen_views.py:397
+#: src/beeswax/report/report_gen_views.py:404
+msgid "Constant"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:322
+msgid "Sort order missing"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:329
+msgid "Alias not applicable for selecting \"*\""
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:331
+#, python-format
+msgid "Invalid column name \"%(column)s\""
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:369
+#, python-format
+msgid "Ambiguous table \"%(table)s\" without alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:379
+msgid "Not selecting from any table column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:381
+msgid "Not displaying any selection"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:395
+#: src/beeswax/report/report_gen_views.py:402
+msgid "Table name/alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:396
+#: src/beeswax/report/report_gen_views.py:403
+#: src/beeswax/templates/create_table_manually.mako:312
+#: src/beeswax/templates/define_columns.mako:67
+msgid "Column name"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:398
+msgid "Condition"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:416
+#, python-format
+msgid "Operator %(operator)s does not take the right operand"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:420
+#, python-format
+msgid "Operator %(operator)s takes both operands"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:425
+msgid "Constant (Left)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:427
+msgid "Table (Left)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:429
+msgid "Column (Left)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:435
+msgid "Constant (Right)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:437
+msgid "Table (Right)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:439
+msgid "Column (Right)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:470
+#, python-format
+msgid "Unknown table \"%(table)s\" in condition"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:487
+msgid "Remove"
+msgstr ""
+
 #: src/beeswax/templates/beeswax_components.mako:198
 msgid "Beginning of List"
 msgstr ""
@@ -210,11 +884,6 @@ msgstr ""
 msgid "Value"
 msgstr ""
 
-#: src/beeswax/templates/configuration.mako:37
-#: src/beeswax/templates/list_designs.mako:32
-msgid "Description"
-msgstr ""
-
 #: src/beeswax/templates/create_table_index.mako:21
 msgid "Beeswax: Create Table"
 msgstr ""
@@ -379,10 +1048,6 @@ msgstr ""
 msgid "Location"
 msgstr ""
 
-#: src/beeswax/templates/create_table_manually.mako:236
-msgid "Use default location"
-msgstr ""
-
 #: src/beeswax/templates/create_table_manually.mako:239
 msgid ""
 "Store your table in the default location (controlled by Hive, and "
@@ -445,11 +1110,6 @@ msgstr ""
 msgid "Delete this column"
 msgstr ""
 
-#: src/beeswax/templates/create_table_manually.mako:312
-#: src/beeswax/templates/define_columns.mako:67
-msgid "Column name"
-msgstr ""
-
 #: src/beeswax/templates/create_table_manually.mako:314
 msgid "Column Name"
 msgstr ""
@@ -675,13 +1335,6 @@ msgstr ""
 msgid "Execute"
 msgstr ""
 
-#: src/beeswax/templates/execute.mako:54 src/beeswax/templates/execute.mako:289
-#: src/beeswax/templates/save_results.mako:43
-#: src/beeswax/templates/watch_results.mako:38
-#: src/beeswax/templates/watch_results.mako:156
-msgid "Save"
-msgstr ""
-
 #: src/beeswax/templates/execute.mako:56
 msgid "Save as..."
 msgstr ""
@@ -854,10 +1507,6 @@ msgstr ""
 msgid "There was an error processing your request:"
 msgstr ""
 
-#: src/beeswax/templates/layout.mako:34
-msgid "Query Editor"
-msgstr ""
-
 #: src/beeswax/templates/layout.mako:35
 msgid "My Queries"
 msgstr ""
@@ -1125,11 +1774,6 @@ msgstr ""
 msgid "Beeswax: Table List"
 msgstr ""
 
-#: src/beeswax/templates/show_tables.mako:43
-#: src/beeswax/templates/watch_results.mako:139
-msgid "Table Name"
-msgstr ""
-
 #: src/beeswax/templates/util.mako:66
 msgid "Unsaved Query"
 msgstr ""

+ 675 - 31
apps/beeswax/src/beeswax/locale/en_US/LC_MESSAGES/django.po

@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PROJECT VERSION\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2012-07-03 01:12+0200\n"
+"POT-Creation-Date: 2012-07-21 11:58+0200\n"
 "PO-Revision-Date: 2012-07-03 01:11+0200\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: en_US <LL@li.org>\n"
@@ -17,6 +17,680 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 0.9.6\n"
 
+#: src/beeswax/conf.py:24
+msgid "Host where beeswax server thrift daemon is running"
+msgstr ""
+
+#: src/beeswax/conf.py:30
+msgid "Configure the port the beeswax thrift server runs on"
+msgstr ""
+
+#: src/beeswax/conf.py:36
+msgid "Host where beeswax internal metastore thrift daemon is running"
+msgstr ""
+
+#: src/beeswax/conf.py:42
+msgid ""
+"Configure the port the internal metastore daemon runs on. Used only if "
+"hive.metastore.local is true."
+msgstr ""
+
+#: src/beeswax/conf.py:49
+msgid "Path to beeswax_server.sh"
+msgstr ""
+
+#: src/beeswax/conf.py:55
+msgid ""
+"Maximum Java heapsize (in megabytes) used by Beeswax Server.  Note that "
+"the setting of HADOOP_HEAPSIZE in $HADOOP_CONF_DIR/hadoop-env.sh may "
+"override this setting."
+msgstr ""
+
+#: src/beeswax/conf.py:63
+msgid ""
+"Path to the root of the Hive installation; defaults to environment "
+"variable when not set."
+msgstr ""
+
+#: src/beeswax/conf.py:68
+msgid "Hive configuration directory, where hive-site.xml is located"
+msgstr ""
+
+#: src/beeswax/conf.py:74
+msgid "The local filesystem path containing the beeswax examples"
+msgstr ""
+
+#: src/beeswax/conf.py:80
+msgid "Timeout in seconds for thrift calls to beeswax service"
+msgstr ""
+
+#: src/beeswax/conf.py:86
+msgid ""
+"Timeouts in seconds for thrift calls to the hive metastore. This timeout "
+"should take into account that the metastore could talk to an external DB"
+msgstr ""
+
+#: src/beeswax/conf.py:92
+msgid "Time in seconds for beeswax to persist queries in its cache."
+msgstr ""
+
+#: src/beeswax/conf.py:98
+msgid ""
+"Set a LIMIT clause when browsing a partitioned table. A positive value "
+"will be set as the LIMIT. If 0 or negative, do not set any limit."
+msgstr ""
+
+#: src/beeswax/conf.py:104
+msgid ""
+"Share saved queries with all users. If set to false, saved queries are "
+"visible only to the owner and administrators."
+msgstr ""
+
+#: src/beeswax/create_table.py:291
+msgid "Internal error when constructing the delimiter form"
+msgstr ""
+
+#: src/beeswax/create_table.py:318
+#, python-format
+msgid ""
+"Failed to decode file '%(path)s' into printable characters under "
+"%(encoding)s"
+msgstr ""
+
+#: src/beeswax/create_table.py:380
+#, python-format
+msgid "Failed to open file '%(path)s': %(error)s"
+msgstr ""
+
+#: src/beeswax/create_table.py:431
+msgid "Internal error: Missing needed parameter to load data into table"
+msgstr ""
+
+#: src/beeswax/data_export.py:88
+msgid ""
+"Error: Potentially incomplete results as an error occur during data "
+"retrieval."
+msgstr ""
+
+#: src/beeswax/data_export.py:90
+#, python-format
+msgid ""
+"Detected another client retrieving results for %(server_id)s. Expect next"
+" row being %(row)s and got %(start_row)s. Aborting"
+msgstr ""
+
+#: src/beeswax/db_utils.py:69
+#, python-format
+msgid "BeeswaxServer returning invalid handle for query id %(id)d [%(query)s]..."
+msgstr ""
+
+#: src/beeswax/forms.py:46
+msgid "Change the name to save as a new design"
+msgstr ""
+
+#: src/beeswax/forms.py:47 src/beeswax/forms.py:162 src/beeswax/forms.py:246
+#: src/beeswax/templates/configuration.mako:37
+#: src/beeswax/templates/list_designs.mako:32
+msgid "Description"
+msgstr ""
+
+#: src/beeswax/forms.py:53 src/beeswax/forms.py:54
+#: src/beeswax/templates/execute.mako:54 src/beeswax/templates/execute.mako:289
+#: src/beeswax/templates/save_results.mako:43
+#: src/beeswax/templates/watch_results.mako:38
+#: src/beeswax/templates/watch_results.mako:156
+msgid "Save"
+msgstr ""
+
+#: src/beeswax/forms.py:55 src/beeswax/forms.py:56
+msgid "Save As"
+msgstr ""
+
+#: src/beeswax/forms.py:69
+msgid "Please enter a name"
+msgstr ""
+
+#: src/beeswax/forms.py:83
+msgid "to a new table"
+msgstr ""
+
+#: src/beeswax/forms.py:83
+msgid "to HDFS directory"
+msgstr ""
+
+#: src/beeswax/forms.py:88 src/beeswax/forms.py:161 src/beeswax/forms.py:245
+#: src/beeswax/templates/show_tables.mako:43
+#: src/beeswax/templates/watch_results.mako:139
+msgid "Table Name"
+msgstr ""
+
+#: src/beeswax/forms.py:90
+msgid "Name of the new table"
+msgstr ""
+
+#: src/beeswax/forms.py:92
+msgid "Results Location"
+msgstr ""
+
+#: src/beeswax/forms.py:94
+msgid "Empty directory in HDFS to put the results"
+msgstr ""
+
+#: src/beeswax/forms.py:105
+msgid "Table already exists"
+msgstr ""
+
+#: src/beeswax/forms.py:112 src/beeswax/templates/layout.mako:34
+msgid "Query Editor"
+msgstr ""
+
+#: src/beeswax/forms.py:132
+msgid ""
+"Resources to upload with your Hive job.  Use 'jar' for UDFs.  Use file "
+"and archive for side files and MAP/TRANSFORM using.  Paths are on HDFS."
+msgstr ""
+
+#: src/beeswax/forms.py:138
+msgid "Path to file on HDFS."
+msgstr ""
+
+#: src/beeswax/forms.py:184
+msgid "SerDe Name"
+msgstr ""
+
+#: src/beeswax/forms.py:187
+msgid "Comma-separated list of key-value pairs, eg., 'p1=v1, p2=v2'"
+msgstr ""
+
+#: src/beeswax/forms.py:198
+msgid "InputFormat Class"
+msgstr ""
+
+#: src/beeswax/forms.py:199
+msgid "OutputFormat Class"
+msgstr ""
+
+#: src/beeswax/forms.py:208
+#: src/beeswax/templates/create_table_manually.mako:236
+msgid "Use default location"
+msgstr ""
+
+#: src/beeswax/forms.py:209
+msgid "Path to HDFS directory or file of table data."
+msgstr ""
+
+#: src/beeswax/forms.py:231
+#, python-format
+msgid "Table \"%(name)s\" already exists"
+msgstr ""
+
+#: src/beeswax/forms.py:238
+msgid "Terminator must be exactly one character"
+msgstr ""
+
+#: src/beeswax/forms.py:249
+msgid "Input File"
+msgstr ""
+
+#: src/beeswax/forms.py:251
+msgid "Import data from file"
+msgstr ""
+
+#: src/beeswax/forms.py:252
+msgid "Automatically load this file into the table after creation"
+msgstr ""
+
+#: src/beeswax/forms.py:268
+msgid "Delimiter value is required"
+msgstr ""
+
+#: src/beeswax/forms.py:278
+msgid "Delimiter value must be smaller than 256"
+msgstr ""
+
+#: src/beeswax/forms.py:281
+msgid "Delimiter must be exactly one character"
+msgstr ""
+
+#: src/beeswax/forms.py:309
+msgid "Array Value Type"
+msgstr ""
+
+#: src/beeswax/forms.py:312 src/beeswax/forms.py:315
+msgid "Specify if column_type is map."
+msgstr ""
+
+#: src/beeswax/forms.py:317
+msgid "add a column"
+msgstr ""
+
+#: src/beeswax/forms.py:319
+msgid "add a partition"
+msgstr ""
+
+#: src/beeswax/forms.py:324
+msgid "Path"
+msgstr ""
+
+#: src/beeswax/forms.py:326
+msgid "Overwrite?"
+msgstr ""
+
+#: src/beeswax/forms.py:339
+#, python-format
+msgid "%(column_name)s (partition key with type %(column_type)s)"
+msgstr ""
+
+#: src/beeswax/models.py:124
+msgid "My saved query"
+msgstr ""
+
+#: src/beeswax/models.py:125
+msgid " (new)"
+msgstr ""
+
+#: src/beeswax/models.py:163
+#, python-format
+msgid "Cannot retrieve Beeswax design id %(id)s"
+msgstr ""
+
+#: src/beeswax/models.py:167
+#, python-format
+msgid "Design id %(id)s does not belong to user %(user)s"
+msgstr ""
+
+#: src/beeswax/models.py:172
+#, python-format
+msgid ""
+"Type mismatch for design id %(id)s (owner %(owner)s) - Expects "
+"%(expected_type)s got %(real_type)s"
+msgstr ""
+
+#: src/beeswax/views.py:68
+#, python-format
+msgid "Design %(id)s does not exist."
+msgstr ""
+
+#: src/beeswax/views.py:74
+#, python-format
+msgid "Cannot access design %(id)s"
+msgstr ""
+
+#: src/beeswax/views.py:85
+#, python-format
+msgid "QueryHistory %(id)s does not exist."
+msgstr ""
+
+#: src/beeswax/views.py:91
+#, python-format
+msgid "Cannot access QueryHistory %(id)s"
+msgstr ""
+
+#: src/beeswax/views.py:147
+#, python-format
+msgid "Do you really want to drop the view '%(table)s'?"
+msgstr ""
+
+#: src/beeswax/views.py:149
+#, python-format
+msgid ""
+"This may delete the underlying data as well as the metadata.  Drop table "
+"'%(table)s'?"
+msgstr ""
+
+#: src/beeswax/views.py:164
+#, python-format
+msgid "Failed to remove %(table)s.  Error: %(error)s"
+msgstr ""
+
+#: src/beeswax/views.py:165 src/beeswax/views.py:179
+msgid "Beeswax Error"
+msgstr ""
+
+#: src/beeswax/views.py:178
+#, python-format
+msgid "Failed to read table. Error: %(error)s"
+msgstr ""
+
+#: src/beeswax/views.py:232
+msgid "Design does not exist"
+msgstr ""
+
+#: src/beeswax/views.py:454
+msgid "Query is not parameterizable."
+msgstr ""
+
+#: src/beeswax/views.py:482
+msgid "Could not retrieve log."
+msgstr ""
+
+#: src/beeswax/views.py:484
+msgid "Unknown exception."
+msgstr ""
+
+#: src/beeswax/views.py:517
+#, python-format
+msgid "Invalid design type %(type)s"
+msgstr ""
+
+#: src/beeswax/views.py:545
+#, python-format
+msgid "Saved design \"%(name)s\""
+msgstr ""
+
+#: src/beeswax/views.py:679
+#, python-format
+msgid "Copied design: %(name)s"
+msgstr ""
+
+#: src/beeswax/views.py:731
+msgid "Beeswax query completed"
+msgstr ""
+
+#: src/beeswax/views.py:738
+#, python-format
+msgid ""
+"%(subject)s. You may see the results here: %(link)s\n"
+"\n"
+"Query:\n"
+"%(query)s"
+msgstr ""
+
+#: src/beeswax/views.py:784
+msgid "The result of this query has expired."
+msgstr ""
+
+#: src/beeswax/views.py:830
+msgid "Query is still being submitted to the Beeswax Server"
+msgstr ""
+
+#: src/beeswax/views.py:831
+msgid "Failed to retrieve query state from the Beeswax Server"
+msgstr ""
+
+#: src/beeswax/views.py:835
+msgid "Failed to contact Beeswax Server to check query status"
+msgstr ""
+
+#: src/beeswax/views.py:901
+#, python-format
+msgid "Trying to display result that is not yet ready. Query id %(id)s"
+msgstr ""
+
+#: src/beeswax/views.py:958
+msgid "This action is only available to the user who submitted the query."
+msgstr ""
+
+#: src/beeswax/views.py:968
+#, python-format
+msgid "This query has %(state)s. Results unavailable."
+msgstr ""
+
+#: src/beeswax/views.py:970
+msgid "The result of this query is not available yet."
+msgstr ""
+
+#: src/beeswax/views.py:987
+msgid "Cannot find query."
+msgstr ""
+
+#: src/beeswax/views.py:993
+msgid ""
+"Saving results from a partitioned table is not supported. You may copy "
+"from the HDFS location manually."
+msgstr ""
+
+#: src/beeswax/views.py:1000
+msgid ""
+"Saving results from a table to a directory is not supported. You may copy"
+" from the HDFS location manually."
+msgstr ""
+
+#: src/beeswax/views.py:1017
+msgid "The table could not be saved."
+msgstr ""
+
+#: src/beeswax/views.py:1025
+#, python-format
+msgid "Failed to save results from query: %(error)s"
+msgstr ""
+
+#: src/beeswax/views.py:1082
+#, python-format
+msgid "Saved query results as new table %(table)s"
+msgstr ""
+
+#: src/beeswax/views.py:1134
+msgid "Install sample tables and Beeswax examples?"
+msgstr ""
+
+#: src/beeswax/views.py:1153
+#, python-format
+msgid "Table '%(table)s' is not partitioned."
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:80
+msgid "Beeswax examples already installed"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:172
+#, python-format
+msgid "Cannot find table data in \"%(file)s\""
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:189
+#, python-format
+msgid "Table \"%(table)s\" already exists"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:197
+#, python-format
+msgid "Error creating table %(table)s: Operation timeout"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:201
+#, python-format
+msgid "Error creating table %(table)s: %(error)s"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:221
+#, python-format
+msgid "Error loading table %(table)s: Operation timeout"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:225
+#, python-format
+msgid "Error loading table %(table)s: %(error)s"
+msgstr ""
+
+#: src/beeswax/management/commands/beeswax_install_examples.py:246
+#, python-format
+msgid "Sample design %(name)s already exists"
+msgstr ""
+
+#: src/beeswax/report/report_gen.py:98
+#, python-format
+msgid "%(aggregation)s is not a valid aggregation"
+msgstr ""
+
+#: src/beeswax/report/report_gen.py:191
+#, python-format
+msgid "%(relation)s is not a valid operator"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:89
+msgid "Missing ManagementForm for conditions"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:186
+msgid "UnionMultiForm is not valid"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:217
+#, python-format
+msgid "%(field)s value not applicable with %(source)s source"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:221
+#, python-format
+msgid "%(field)s value missing"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:234
+msgid "Display"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:237
+#: src/beeswax/report/report_gen_views.py:393
+#: src/beeswax/report/report_gen_views.py:400
+msgid "Source"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:240
+msgid "Aggregate"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:243
+msgid "Distinct"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:246
+msgid "Constant value"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:249
+msgid "Table alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:251
+#: src/beeswax/report/report_gen_views.py:319
+msgid "From column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:253
+msgid "Column alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:255
+msgid "Sort"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:258
+msgid "Sort order"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:260
+msgid "Group order"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:265
+#: src/beeswax/report/report_gen_views.py:316
+msgid "From table"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:272
+msgid "Source must be \"table\" when not displaying column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:275
+msgid "Column alias not applicable when not displaying column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:278
+msgid "Source value missing"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:313
+#: src/beeswax/report/report_gen_views.py:397
+#: src/beeswax/report/report_gen_views.py:404
+msgid "Constant"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:322
+msgid "Sort order missing"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:329
+msgid "Alias not applicable for selecting \"*\""
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:331
+#, python-format
+msgid "Invalid column name \"%(column)s\""
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:369
+#, python-format
+msgid "Ambiguous table \"%(table)s\" without alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:379
+msgid "Not selecting from any table column"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:381
+msgid "Not displaying any selection"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:395
+#: src/beeswax/report/report_gen_views.py:402
+msgid "Table name/alias"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:396
+#: src/beeswax/report/report_gen_views.py:403
+#: src/beeswax/templates/create_table_manually.mako:312
+#: src/beeswax/templates/define_columns.mako:67
+msgid "Column name"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:398
+msgid "Condition"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:416
+#, python-format
+msgid "Operator %(operator)s does not take the right operand"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:420
+#, python-format
+msgid "Operator %(operator)s takes both operands"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:425
+msgid "Constant (Left)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:427
+msgid "Table (Left)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:429
+msgid "Column (Left)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:435
+msgid "Constant (Right)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:437
+msgid "Table (Right)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:439
+msgid "Column (Right)"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:470
+#, python-format
+msgid "Unknown table \"%(table)s\" in condition"
+msgstr ""
+
+#: src/beeswax/report/report_gen_views.py:487
+msgid "Remove"
+msgstr ""
+
 #: src/beeswax/templates/beeswax_components.mako:198
 msgid "Beginning of List"
 msgstr ""
@@ -210,11 +884,6 @@ msgstr ""
 msgid "Value"
 msgstr ""
 
-#: src/beeswax/templates/configuration.mako:37
-#: src/beeswax/templates/list_designs.mako:32
-msgid "Description"
-msgstr ""
-
 #: src/beeswax/templates/create_table_index.mako:21
 msgid "Beeswax: Create Table"
 msgstr ""
@@ -379,10 +1048,6 @@ msgstr ""
 msgid "Location"
 msgstr ""
 
-#: src/beeswax/templates/create_table_manually.mako:236
-msgid "Use default location"
-msgstr ""
-
 #: src/beeswax/templates/create_table_manually.mako:239
 msgid ""
 "Store your table in the default location (controlled by Hive, and "
@@ -445,11 +1110,6 @@ msgstr ""
 msgid "Delete this column"
 msgstr ""
 
-#: src/beeswax/templates/create_table_manually.mako:312
-#: src/beeswax/templates/define_columns.mako:67
-msgid "Column name"
-msgstr ""
-
 #: src/beeswax/templates/create_table_manually.mako:314
 msgid "Column Name"
 msgstr ""
@@ -675,13 +1335,6 @@ msgstr ""
 msgid "Execute"
 msgstr ""
 
-#: src/beeswax/templates/execute.mako:54 src/beeswax/templates/execute.mako:289
-#: src/beeswax/templates/save_results.mako:43
-#: src/beeswax/templates/watch_results.mako:38
-#: src/beeswax/templates/watch_results.mako:156
-msgid "Save"
-msgstr ""
-
 #: src/beeswax/templates/execute.mako:56
 msgid "Save as..."
 msgstr ""
@@ -854,10 +1507,6 @@ msgstr ""
 msgid "There was an error processing your request:"
 msgstr ""
 
-#: src/beeswax/templates/layout.mako:34
-msgid "Query Editor"
-msgstr ""
-
 #: src/beeswax/templates/layout.mako:35
 msgid "My Queries"
 msgstr ""
@@ -1125,11 +1774,6 @@ msgstr ""
 msgid "Beeswax: Table List"
 msgstr ""
 
-#: src/beeswax/templates/show_tables.mako:43
-#: src/beeswax/templates/watch_results.mako:139
-msgid "Table Name"
-msgstr ""
-
 #: src/beeswax/templates/util.mako:66
 msgid "Unsaved Query"
 msgstr ""

+ 10 - 8
apps/beeswax/src/beeswax/management/commands/beeswax_install_examples.py

@@ -48,6 +48,8 @@ from beeswaxd.ttypes import BeeswaxException
 
 import hive_metastore.ttypes
 
+from django.utils.translation import ugettext as _
+
 LOG = logging.getLogger(__name__)
 DEFAULT_INSTALL_USER = 'hue'
 
@@ -75,7 +77,7 @@ class Command(NoArgsCommand):
   def handle_noargs(self, **options):
     """Main entry point to install examples. May raise InstallException"""
     if self._check_installed():
-      msg = 'Beeswax examples already installed'
+      msg = _('Beeswax examples already installed')
       LOG.error(msg)
       raise InstallException(msg)
 
@@ -167,7 +169,7 @@ class SampleTable(object):
     self._data_dir = beeswax.conf.LOCAL_EXAMPLES_DATA_DIR.get()
     self._contents_file = os.path.join(self._data_dir, self.filename)
     if not os.path.isfile(self._contents_file):
-      msg = 'Cannot find table data in "%s"' % (self._contents_file,)
+      msg = _('Cannot find table data in "%(file)s"') % {'file': self._contents_file}
       LOG.error(msg)
       raise ValueError(msg)
 
@@ -184,7 +186,7 @@ class SampleTable(object):
     try:
       # Already exists?
       tables = db_utils.meta_client().get_table("default", self.name)
-      msg = 'Table "%s" already exists' % (self.name,)
+      msg = _('Table "%(table)s" already exists') % {'table': self.name}
       LOG.error(msg)
       raise InstallException(msg)
     except hive_metastore.ttypes.NoSuchObjectException:
@@ -192,11 +194,11 @@ class SampleTable(object):
       try:
         results = db_utils.execute_and_wait(django_user, query_msg)
         if not results:
-          msg = 'Error creating table %s: Operation timeout' % (self.name,)
+          msg = _('Error creating table %(table)s: Operation timeout') % {'table': self.name}
           LOG.error(msg)
           raise InstallException(msg)
       except BeeswaxException, ex:
-        msg = 'Error creating table %s: %s' % (self.name, ex)
+        msg = _('Error creating table %(table)s: %(error)s') % {'table': self.name, 'error': ex}
         LOG.error(msg)
         raise InstallException(msg)
 
@@ -216,11 +218,11 @@ class SampleTable(object):
     try:
       results = db_utils.execute_and_wait(django_user, query_msg)
       if not results:
-        msg = 'Error loading table %s: Operation timeout' % (self.name,)
+        msg = _('Error loading table %(table)s: Operation timeout') % {'table': self.name}
         LOG.error(msg)
         raise InstallException(msg)
     except BeeswaxException, ex:
-      msg = 'Error loading table %s: %s' % (self.name, ex)
+      msg = _('Error loading table %(table)s: %(error)s') % {'table': self.name, 'error': ex}
       LOG.error(msg)
       raise InstallException(msg)
 
@@ -241,7 +243,7 @@ class SampleDesign(object):
     try:
       # Don't overwrite
       model = models.SavedQuery.objects.get(owner=django_user, name=self.name)
-      msg = 'Sample design %s already exists' % (self.name,)
+      msg = _('Sample design %(name)s already exists') % {'name': self.name}
       LOG.error(msg)
       raise InstallException(msg)
     except models.SavedQuery.DoesNotExist:

+ 8 - 6
apps/beeswax/src/beeswax/models.py

@@ -27,6 +27,8 @@ from django.contrib.auth.models import User
 from desktop.lib.django_util import PopupException
 from beeswaxd.ttypes import QueryState
 
+from django.utils.translation import ugettext as _
+
 LOG = logging.getLogger(__name__)
 
 QUERY_SUBMISSION_TIMEOUT = datetime.timedelta(0, 60 * 60)               # 1 hr
@@ -119,8 +121,8 @@ class SavedQuery(models.Model):
   Note that this used to be called QueryDesign. Any references to 'design'
   probably mean a SavedQuery.
   """
-  DEFAULT_NEW_DESIGN_NAME = 'My saved query'
-  AUTO_DESIGN_SUFFIX = ' (new)'
+  DEFAULT_NEW_DESIGN_NAME = _('My saved query')
+  AUTO_DESIGN_SUFFIX = _(' (new)')
   TYPES = (HQL, REPORT) = range(2)
 
   type = models.IntegerField(null=False)
@@ -158,17 +160,17 @@ class SavedQuery(models.Model):
     try:
       design = SavedQuery.objects.get(id=id)
     except SavedQuery.DoesNotExist, err:
-      msg = 'Cannot retrieve Beeswax design id %s' % (id,)
+      msg = _('Cannot retrieve Beeswax design id %(id)s') % {'id': id}
       raise err
 
     if owner is not None and design.owner != owner:
-      msg = 'Design id %s does not belong to user %s' % (id, owner)
+      msg = _('Design id %(id)s does not belong to user %(user)s') % {'id': id, 'user': owner}
       LOG.error(msg)
       raise PopupException(msg)
 
     if type is not None and design.type != type:
-      msg = 'Type mismatch for design id %s (owner %s) - Expects %s got %s' % \
-            (id, owner, design.type, type)
+      msg = _('Type mismatch for design id %(id)s (owner %(owner)s) - Expects %(expected_type)s got %(real_type)s') % \
+            {'id': id, 'owner': owner, 'expected_type': design.type, 'real_type': type}
       LOG.error(msg)
       raise PopupException(msg)
 

+ 4 - 2
apps/beeswax/src/beeswax/report/report_gen.py

@@ -44,6 +44,8 @@ import logging
 from beeswax import common
 from beeswax import db_utils
 
+from django.utils.translation import ugettext as _
+
 LOG = logging.getLogger(__name__)
 
 #
@@ -93,7 +95,7 @@ class _Selection(object):
 
   def set_aggregation(self, agg):
     if agg not in common.AGGREGATIONS:
-      raise KeyError("%s is not a valid aggregation" % (agg,))
+      raise KeyError(_("%(aggregation)s is not a valid aggregation") % {'aggregation': agg})
     self._agg = agg
 
   @property
@@ -186,7 +188,7 @@ class BooleanCondition(object):
     assert isinstance(lhs_selection, _Selection)
     assert rhs_selection is None or isinstance(rhs_selection, _Selection)
     if relation not in common.RELATION_OPS:
-      raise ValueError("%s is not a valid operator" % (relation,))
+      raise ValueError(_("%(relation)s is not a valid operator") % {'relation': relation})
     self._lhs = lhs_selection
     self._rhs = rhs_selection
     self._relation = relation

+ 50 - 48
apps/beeswax/src/beeswax/report/report_gen_views.py

@@ -57,6 +57,8 @@ from beeswax.report import report_gen
 from desktop.lib.django_forms import BaseSimpleFormSet, ManagementForm, MultiForm
 from desktop.lib.django_forms import simple_formset_factory, SubmitButton
 
+from django.utils.translation import ugettext as _t
+
 LOG = logging.getLogger(__name__)
 
 SUB_UNION_PREFIX = 'sub'
@@ -84,7 +86,7 @@ def fixup_union(parent_mform, subform_name, data, is_root=False):
   union_mform = getattr(parent_mform, subform_name)
   mgmt_form = union_mform.mgmt
   if not mgmt_form.is_valid():
-    raise forms.ValidationError('Missing ManagementForm for conditions')
+    raise forms.ValidationError(_t('Missing ManagementForm for conditions'))
   n_children = mgmt_form.form_counts()
 
   # This removes our current subform (union_mform) and any children.
@@ -181,7 +183,7 @@ def _extract_condition(union_mform, table_alias_dict):
   """
   global SUB_UNION_PREFIX
   if not union_mform.is_valid():
-    assert False, 'UnionMultiForm is not valid'
+    assert False, _t('UnionMultiForm is not valid')
     return None
 
   op = union_mform.bool.cleaned_data['bool']
@@ -212,11 +214,11 @@ def _field_source_check(true_source, field_name, field_value, is_from_table):
   """
   if bool(true_source == 'table') ^ bool(is_from_table):
     if field_value:
-      raise forms.ValidationError('%s value not applicable with %s source' %
-                                  (field_name, true_source))
+      raise forms.ValidationError(_t('%(field)s value not applicable with %(source)s source') %
+                                  {'field': field_name, 'source': true_source})
     return False
   elif not field_value:
-    raise forms.ValidationError('%s value missing' % (field_name,))
+    raise forms.ValidationError(_t('%(field)s value missing') % {'field': field_name})
   return True
 
 
@@ -229,51 +231,51 @@ class ReportColumnForm(forms.Form):
   A form representing a column in the report.
   """
   # If not 'display', then source must be 'table'
-  display = forms.BooleanField(label='Display', required=False, initial=True)
+  display = forms.BooleanField(label=_t('Display'), required=False, initial=True)
 
   # Shown iff 'display'. 'source' is not required, but will be set during clean
-  source = forms.ChoiceField(label='Source', required=False, initial='table',
+  source = forms.ChoiceField(label=_t('Source'), required=False, initial='table',
                                 choices=common.to_choices(common.SELECTION_SOURCE))
   # Shown iff 'display'
-  agg = forms.ChoiceField(label='Aggregate', required=False,
+  agg = forms.ChoiceField(label=_t('Aggregate'), required=False,
                                 choices=common.to_choices(common.AGGREGATIONS))
   # Shown iff 'display'
-  distinct = forms.BooleanField(label="Distinct", required=False)
+  distinct = forms.BooleanField(label=_t("Distinct"), required=False)
 
   # Shown iff 'source' is 'constant'
-  constant = forms.CharField(label='Constant value', required=False)
+  constant = forms.CharField(label=_t('Constant value'), required=False)
 
   # Shown iff 'source' is 'table'
-  table_alias = common.HiveIdentifierField(label='Table alias', required=False)
+  table_alias = common.HiveIdentifierField(label=_t('Table alias'), required=False)
   # Shown iff 'source' is 'table'
-  col = forms.CharField(label='From column', required=False)
+  col = forms.CharField(label=_t('From column'), required=False)
   # Shown iff 'display', and 'source' is 'table'
-  col_alias = common.HiveIdentifierField(label='Column alias', required=False)
+  col_alias = common.HiveIdentifierField(label=_t('Column alias'), required=False)
   # Shown iff 'display', and 'source' is 'table'
-  sort = forms.ChoiceField(label='Sort', required=False,
+  sort = forms.ChoiceField(label=_t('Sort'), required=False,
                                 choices=common.to_choices(common.SORT_OPTIONS))
   # Shown iff 'sort'
-  sort_order = forms.IntegerField(label='Sort order', required=False, min_value=1)
+  sort_order = forms.IntegerField(label=_t('Sort order'), required=False, min_value=1)
   # Shown iff 'display', and 'source' is 'table'
-  group_order = forms.IntegerField(label='Group order', required=False, min_value=1)
+  group_order = forms.IntegerField(label=_t('Group order'), required=False, min_value=1)
 
   def __init__(self, *args, **kwargs):
     forms.Form.__init__(self, *args, **kwargs)
     # Shown iff 'source' is 'table'
-    self.fields['table'] = common.HiveTableChoiceField(label='From table', required=False)
+    self.fields['table'] = common.HiveTableChoiceField(label=_t('From table'), required=False)
 
   def _display_check(self):
     """Reconcile 'display' with 'source'"""
     src = self.cleaned_data.get('source')
     if not self.cleaned_data.get('display'):
       if src and src != 'table':
-        raise forms.ValidationError('Source must be "table" when not displaying column')
+        raise forms.ValidationError(_t('Source must be "table" when not displaying column'))
       self.cleaned_data['source'] = 'table'
       if self.cleaned_data.get('col_alias'):
-        raise forms.ValidationError('Column alias not applicable when not displaying column')
+        raise forms.ValidationError(_t('Column alias not applicable when not displaying column'))
     else:
       if not src:
-        raise forms.ValidationError('Source value missing')
+        raise forms.ValidationError(_t('Source value missing'))
 
 
   def clean_display(self):
@@ -308,25 +310,25 @@ class ReportColumnForm(forms.Form):
       return None                       # No point since we can't get source
 
     constant_val = self.cleaned_data.get('constant')
-    _field_source_check(source, 'Constant', constant_val, is_from_table=False)
+    _field_source_check(source, _t('Constant'), constant_val, is_from_table=False)
 
     table_val = self.cleaned_data.get('table')
-    _field_source_check(source, 'From table', table_val, is_from_table=True)
+    _field_source_check(source, _t('From table'), table_val, is_from_table=True)
 
     col_val = self.cleaned_data.get('col')
-    _field_source_check(source, 'From column', col_val, is_from_table=True)
+    _field_source_check(source, _t('From column'), col_val, is_from_table=True)
 
     if self.cleaned_data.get('sort', '') and not self.cleaned_data.get('sort_order', ''):
-      raise forms.ValidationError('Sort order missing')
+      raise forms.ValidationError(_t('Sort order missing'))
 
     if table_val:
       # Column must belong to the table
       self.qtable = report_gen.QTable(table_val, self.cleaned_data.get('table_alias'))
       if col_val == '*':
         if self.cleaned_data.get('col_alias'):
-          raise forms.ValidationError('Alias not applicable for selecting "*"')
+          raise forms.ValidationError(_t('Alias not applicable for selecting "*"'))
       elif col_val not in self.qtable.get_columns():
-        raise forms.ValidationError('Invalid column name "%s"' % (col_val,))
+        raise forms.ValidationError(_t('Invalid column name "%(column)s"') % {'column': col_val})
       # ColumnSelection object
       self.selection = report_gen.ColumnSelection(self.qtable,
                                                   col_val,
@@ -364,7 +366,7 @@ class ReportColumnBaseFormset(BaseSimpleFormSet):
       for qt in qt_list:
         # Error if a table has alias but another doesn't. (Tables with the same name.)
         if bool(curr.alias) ^ bool(qt.alias):
-          raise forms.ValidationError('Ambiguous table "%s" without alias' % (qt.name,))
+          raise forms.ValidationError(_t('Ambiguous table "%(table)s" without alias') % {'table': qt.name})
         if curr.alias == qt.alias:
           # Duplicate. Don't update.
           break
@@ -374,9 +376,9 @@ class ReportColumnBaseFormset(BaseSimpleFormSet):
 
     self.qtable_list = sum([ tbl_list for tbl_list in qt_by_name.values() ], [ ])
     if not self.qtable_list:
-      raise forms.ValidationError('Not selecting from any table column')
+      raise forms.ValidationError(_t('Not selecting from any table column'))
     if n_display == 0:
-      raise forms.ValidationError('Not displaying any selection')
+      raise forms.ValidationError(_t('Not displaying any selection'))
 
 
 ReportColumnFormset = simple_formset_factory(ReportColumnForm,
@@ -388,18 +390,18 @@ ReportColumnFormset = simple_formset_factory(ReportColumnForm,
 ###########
 
 class ReportConditionForm(forms.Form):
-  l_source = forms.ChoiceField(label='Source', initial='table',
+  l_source = forms.ChoiceField(label=_t('Source'), initial='table',
                               choices=common.to_choices(common.SELECTION_SOURCE))
-  l_table = forms.CharField(label='Table name/alias', required=False)
-  l_col = forms.CharField(label='Column name', required=False)
-  l_constant = forms.CharField(label='Constant', required=False)
-  op = forms.ChoiceField(label='Condition',
+  l_table = forms.CharField(label=_t('Table name/alias'), required=False)
+  l_col = forms.CharField(label=_t('Column name'), required=False)
+  l_constant = forms.CharField(label=_t('Constant'), required=False)
+  op = forms.ChoiceField(label=_t('Condition'),
                               choices=common.to_choices(common.RELATION_OPS))
-  r_source = forms.ChoiceField(label='Source', required=False, initial='table',
+  r_source = forms.ChoiceField(label=_t('Source'), required=False, initial='table',
                               choices=common.to_choices(common.SELECTION_SOURCE))
-  r_table = forms.CharField(label='Table name/alias', required=False)
-  r_col = forms.CharField(label='Column name', required=False)
-  r_constant = forms.CharField(label='Constant', required=False)
+  r_table = forms.CharField(label=_t('Table name/alias'), required=False)
+  r_col = forms.CharField(label=_t('Column name'), required=False)
+  r_constant = forms.CharField(label=_t('Constant'), required=False)
 
 
   def clean(self):
@@ -411,30 +413,30 @@ class ReportConditionForm(forms.Form):
     op = self.cleaned_data['op']
     if op in common.RELATION_OPS_UNARY:
       if self.cleaned_data.get('r_source') or self.cleaned_data.get('r_cond'):
-        raise forms.ValidationError('Operator %s does not take the right operand' % (op,))
+        raise forms.ValidationError(_t('Operator %(operator)s does not take the right operand') % {'operator': op})
       check_right = False
     else:
       if not self.cleaned_data.get('l_source') or not self.cleaned_data.get('r_source'):
-        raise forms.ValidationError('Operator %s takes both operands' % (op,))
+        raise forms.ValidationError(_t('Operator %(operator)s takes both operands') % {'operator': op})
 
     # Verify the lhs values match the source
     l_source = self.cleaned_data['l_source']
     l_constant = self.cleaned_data.get('l_constant')
-    _field_source_check(l_source, 'Constant (Left)', l_constant, is_from_table=False)
+    _field_source_check(l_source, _t('Constant (Left)'), l_constant, is_from_table=False)
     l_table = self.cleaned_data.get('l_table')
-    _field_source_check(l_source, 'Table (Left)', l_table, is_from_table=True)
+    _field_source_check(l_source, _t('Table (Left)'), l_table, is_from_table=True)
     l_col = self.cleaned_data.get('l_col')
-    _field_source_check(l_source, 'Column (Left)', l_col, is_from_table=True)
+    _field_source_check(l_source, _t('Column (Left)'), l_col, is_from_table=True)
 
     if check_right:
       # Verify the rhs values match the source
       r_source = self.cleaned_data['r_source']
       r_constant = self.cleaned_data.get('r_constant')
-      _field_source_check(r_source, 'Constant (Right)', r_constant, is_from_table=False)
+      _field_source_check(r_source, _t('Constant (Right)'), r_constant, is_from_table=False)
       r_table = self.cleaned_data.get('r_table')
-      _field_source_check(r_source, 'Table (Right)', r_table, is_from_table=True)
+      _field_source_check(r_source, _t('Table (Right)'), r_table, is_from_table=True)
       r_col = self.cleaned_data.get('r_col')
-      _field_source_check(r_source, 'Column (Right)', r_col, is_from_table=True)
+      _field_source_check(r_source, _t('Column (Right)'), r_col, is_from_table=True)
     return self.cleaned_data
 
 
@@ -465,7 +467,7 @@ class ReportConditionForm(forms.Form):
       try:
         return report_gen.ColumnSelection(table_alias_dict[table], col)
       except KeyError:
-        raise forms.ValidationError('Unknown table "%s" in condition' % (table,))
+        raise forms.ValidationError(_t('Unknown table "%(table)s" in condition') % {'table': table})
 
     constant = self.cleaned_data[prefix + 'constant']
     return report_gen.ConstSelection(constant)
@@ -482,7 +484,7 @@ class ReportConditionBoolForm(forms.Form):
 class UnionManagementForm(ManagementForm):
   def __init__(self, *args, **kwargs):
     ManagementForm.__init__(self, *args, **kwargs)
-    remove = forms.BooleanField(label='Remove', widget=SubmitButton, required=False)
+    remove = forms.BooleanField(label=_t('Remove'), widget=SubmitButton, required=False)
     remove.widget.label = '-'
     self.fields['remove'] = remove
 

+ 36 - 39
apps/beeswax/src/beeswax/views.py

@@ -53,6 +53,7 @@ from jobsub.parameterization import find_variables, substitute_variables
 
 from filebrowser.views import location_to_url
 
+from django.utils.translation import ugettext_lazy as _t
 
 LOG = logging.getLogger(__name__)
 
@@ -64,13 +65,13 @@ def authorized_get_design(request, design_id, owner_only=False, must_exist=False
     design = models.SavedQuery.objects.get(id=design_id)
   except models.SavedQuery.DoesNotExist:
     if must_exist:
-      raise PopupException('Design %s does not exist.' % (design_id,))
+      raise PopupException(_t('Design %(id)s does not exist.') % {'id': design_id})
     else:
       return None
 
   if not conf.SHARE_SAVED_QUERIES.get() and (not request.user.is_superuser or owner_only) \
       and design.owner != request.user:
-    raise PopupException('Cannot access design %s' % (design_id,))
+    raise PopupException(_t('Cannot access design %(id)s') % {'id': design_id})
   else:
     return design
 
@@ -81,13 +82,13 @@ def authorized_get_history(request, query_history_id, owner_only=False, must_exi
     query_history = models.QueryHistory.objects.get(id=query_history_id)
   except models.QueryHistory.DoesNotExist:
     if must_exist:
-      raise PopupException('QueryHistory %s does not exist.' % (query_history_id,))
+      raise PopupException(_t('QueryHistory %(id)s does not exist.') % {'id': query_history_id})
     else:
       return None
 
   if not conf.SHARE_SAVED_QUERIES.get() and (not request.user.is_superuser or owner_only) \
       and query_history.owner != request.user:
-    raise PopupException('Cannot access QueryHistory %s' % (query_history_id,))
+    raise PopupException(_t('Cannot access QueryHistory %(id)s') % {'id': query_history_id})
   else:
     return query_history
 
@@ -143,9 +144,9 @@ def drop_table(request, table):
     # but this was introduced in Hive 0.5, and therefore may not be available
     # with older metastores.
     if is_view:
-      title = "Do you really want to drop the view '%s'?" % (table,)
+      title = _t("Do you really want to drop the view '%(table)s'?") % {'table': table}
     else:
-      title = "This may delete the underlying data as well as the metadata.  Drop table '%s'?" % table
+      title = _t("This may delete the underlying data as well as the metadata.  Drop table '%(table)s'?") % {'table': table}
     return render('confirm.html', request, dict(url=request.path, title=title))
   elif request.method == 'POST':
     if is_view:
@@ -160,8 +161,8 @@ def drop_table(request, table):
     except BeeswaxException, ex:
       # Note that this state is difficult to get to.
       error_message, log = expand_exception(ex)
-      error = "Failed to remove %s.  Error: %s" % (table, error_message)
-      raise PopupException(error, title="Beeswax Error", detail=log)
+      error = _t("Failed to remove %(table)s.  Error: %(error)s") % {'table': table, 'error': error_message}
+      raise PopupException(error, title=_t("Beeswax Error"), detail=log)
 
 
 def read_table(request, table):
@@ -174,8 +175,8 @@ def read_table(request, table):
   except BeeswaxException, e:
     # Note that this state is difficult to get to.
     error_message, log = expand_exception(e)
-    error = "Failed to read table.  Error: " + error_message
-    raise PopupException(error, title="Beeswax Error", detail=log)
+    error = _t("Failed to read table. Error: %(error)s") % {'error': error_message}
+    raise PopupException(error, title=_t("Beeswax Error"), detail=log)
 
 
 def confirm_query(request, query, on_success_url=None):
@@ -228,7 +229,7 @@ def safe_get_design(request, design_type, design_id=None):
     try:
       design = models.SavedQuery.get(design_id, request.user, design_type)
     except models.SavedQuery.DoesNotExist:
-      request.flash.put('Design does not exist')
+      request.flash.put(_t('Design does not exist'))
   if design is None:
     design = models.SavedQuery(owner=request.user, type=design_type)
   return design
@@ -450,7 +451,7 @@ def _run_parameterized_query(request, design_id, explain):
   query_str = _strip_trailing_semicolon(query_form.query.cleaned_data["query"])
   parameterization_form_cls = make_parameterization_form(query_str)
   if not parameterization_form_cls:
-    raise PopupException("Query is not parameterizable.")
+    raise PopupException(_t("Query is not parameterizable."))
   parameterization_form = parameterization_form_cls(request.REQUEST, prefix="parameterization")
   if parameterization_form.is_valid():
     real_query = substitute_variables(query_str, parameterization_form.cleaned_data)
@@ -478,9 +479,9 @@ def expand_exception(exc):
     log = db_utils.db_client().get_log(exc.log_context)
   except:
     # Always show something, even if server has died on the job.
-    log = "Could not retrieve log."
+    log = _t("Could not retrieve log.")
   if not exc.message:
-    error_message = "Unknown exception."
+    error_message = _t("Unknown exception.")
   else:
     error_message = force_unicode(exc.message, strings_only=True, errors='replace')
   return error_message, log
@@ -513,7 +514,7 @@ def save_design(request, form, type, design, explicit_save):
   elif type == models.SavedQuery.REPORT:
     design_cls = beeswax.report.ReportDesign
   else:
-    raise ValueError('Invalid design type %s' % (type,))
+    raise ValueError(_t('Invalid design type %(type)s') % {'type': type})
 
   old_design = design
   design_obj = design_cls(form)
@@ -541,7 +542,7 @@ def save_design(request, form, type, design, explicit_save):
   LOG.info('Saved %sdesign "%s" (id %s) for %s' %
            (explicit_save and '' or 'auto ', design.name, design.id, design.owner))
   if explicit_save:
-    request.flash.put('Saved design "%s"' % (design.name,))
+    request.flash.put(_t('Saved design "%(name)s"') % {'name': design.name})
   # Design may now have a new/different id
   return design
 
@@ -675,7 +676,7 @@ def clone_design(request, design_id):
   copy.name = design.name + ' (copy)'
   copy.owner = request.user
   copy.save()
-  request.flash.put('Copied design: %s' % (design.name,))
+  request.flash.put(_t('Copied design: %(name)s') % {'name': design.name})
   return format_preserving_redirect(
       request, urlresolvers.reverse(execute_query, kwargs={'design_id': copy.id}))
 
@@ -727,14 +728,14 @@ def query_done_cb(request, server_id):
     return res
   design = history.design
   user = history.owner
-  subject = "Beeswax query completed"
+  subject = _t("Beeswax query completed")
   if design:
     subject += ": %s" % (design.name,)
 
   link = "%s/#launch=Beeswax:%s" % \
             (get_desktop_uri_prefix(),
              urlresolvers.reverse(watch_query, kwargs={'id': history.id}))
-  body = "%s. You may see the results here: %s\n\nQuery:\n%s" % (subject, link, history.query)
+  body = _t("%(subject)s. You may see the results here: %(link)s\n\nQuery:\n%(query)s") % {'subject': subject, 'link': link, 'query': history.query}
   try:
     user.email_user(subject, body)
   except Exception, ex:
@@ -780,7 +781,7 @@ def watch_query(request, id):
 
   # Query finished?
   if state == models.QueryHistory.STATE.expired:
-    raise PopupException("The result of this query has expired.")
+    raise PopupException(_t("The result of this query has expired."))
   elif state == models.QueryHistory.STATE.available:
     return format_preserving_redirect(request, on_success_url, request.GET)
   elif state == models.QueryHistory.STATE.failed:
@@ -826,12 +827,12 @@ def _get_server_id_and_state(query_history):
   ok, server_id = query_history.get_server_id()
   if not server_id:
     if ok:
-      raise PopupException("Query is still being submitted to the Beeswax Server")
-    raise PopupException("Failed to retrieve query state from the Beeswax Server")
+      raise PopupException(_t("Query is still being submitted to the Beeswax Server"))
+    raise PopupException(_t("Failed to retrieve query state from the Beeswax Server"))
 
   state = db_utils.get_query_state(query_history)
   if state is None:
-    raise PopupException("Failed to contact Beeswax Server to check query status")
+    raise PopupException(_t("Failed to contact Beeswax Server to check query status"))
   return (server_id, state)
 
 
@@ -897,7 +898,7 @@ def view_results(request, id, first_row=0):
   # Retrieve query results
   try:
     results = db_utils.db_client().fetch(handle, start_over, -1)
-    assert results.ready, 'Trying to display result that is not yet ready. Query id %s' % (id,)
+    assert results.ready, _t('Trying to display result that is not yet ready. Query id %(id)s') % {'id': id}
     # We display the "Download" button only when we know
     # that there are results:
     downloadable = (first_row > 0 or len(results.data) > 0)
@@ -954,7 +955,7 @@ def save_results(request, id):
   id = int(id)
   query_history = models.QueryHistory.objects.get(id=id)
   if query_history.owner != request.user:
-    raise PopupException('This action is only available to the user who submitted the query.')
+    raise PopupException(_t('This action is only available to the user who submitted the query.'))
   _, state = _get_server_id_and_state(query_history)
   query_history.save_state(state)
   error_msg, log = None, None
@@ -964,9 +965,9 @@ def save_results(request, id):
     # Note that we may still hit errors during the actual save
     if state != models.QueryHistory.STATE.available:
       if state in (models.QueryHistory.STATE.failed, models.QueryHistory.STATE.expired):
-        msg = 'This query has %s. Results unavailable.' % (state,)
+        msg = _t('This query has %(state)s. Results unavailable.') % {'state': state}
       else:
-        msg = 'The result of this query is not available yet.'
+        msg = _t('The result of this query is not available yet.')
       raise PopupException(msg)
 
     form = beeswax.forms.SaveResultsForm(request.POST)
@@ -983,24 +984,20 @@ def save_results(request, id):
         result_meta = db_utils.db_client().get_results_metadata(handle)
       except QueryNotFoundException, ex:
         LOG.exception(ex)
-        raise PopupException('Cannot find query.')
+        raise PopupException(_t('Cannot find query.'))
       if result_meta.table_dir:
         result_meta.table_dir = request.fs.urlsplit(result_meta.table_dir)[2]
 
       # 2. Check for partitioned tables
       if result_meta.table_dir is None:
-        raise PopupException(
-                  'Saving results from a partitioned table is not supported. '
-                  'You may copy from the HDFS location manually.')
+        raise PopupException(_t('Saving results from a partitioned table is not supported. You may copy from the HDFS location manually.'))
 
       # 3. Actual saving of results
       try:
         if form.cleaned_data['save_target'] == form.SAVE_TYPE_DIR:
           # To dir
           if result_meta.in_tablename:
-            raise PopupException(
-                      'Saving results from a table to a directory is not supported. '
-                      'You may copy from the HDFS location manually.')
+            raise PopupException(_t('Saving results from a table to a directory is not supported. You may copy from the HDFS location manually.'))
           target_dir = form.cleaned_data['target_dir']
           request.fs.rename_star(result_meta.table_dir, target_dir)
           LOG.debug("Moved results from %s to %s" % (result_meta.table_dir, target_dir))
@@ -1017,7 +1014,7 @@ def save_results(request, id):
             LOG.exception(bex)
             error_msg, log = expand_exception(bex)
       except WebHdfsException, ex:
-        raise PopupException('The table could not be saved.', detail=ex)
+        raise PopupException(_t('The table could not be saved.'), detail=ex)
       except IOError, ex:
         LOG.exception(ex)
         error_msg = str(ex)
@@ -1025,7 +1022,7 @@ def save_results(request, id):
     form = beeswax.forms.SaveResultsForm()
 
   if error_msg:
-    error_msg = 'Failed to save results from query: %s' % (error_msg,)
+    error_msg = _t('Failed to save results from query: %(error)s') % {'error': error_msg}
   return render('save_results.mako', request, dict(
     action=urlresolvers.reverse(save_results, kwargs={'id': str(id)}),
     form=form,
@@ -1082,7 +1079,7 @@ def _save_results_ctas(request, query_history, target_table, result_meta):
     table_loc = request.fs.urlsplit(table_obj.sd.location)[2]
     request.fs.rename_star(result_meta.table_dir, table_loc)
     LOG.debug("Moved results from %s to %s" % (result_meta.table_dir, table_loc))
-    request.flash.put('Saved query results as new table %s' % (target_table,))
+    request.flash.put(_t('Saved query results as new table %(table)s') % {'table': target_table})
     query_history.save_state(models.QueryHistory.STATE.expired)
   except Exception, ex:
     LOG.error('Error moving data into storage of table %s. Will drop table.' % (target_table,))
@@ -1134,7 +1131,7 @@ def install_examples(request):
   """
   if request.method == 'GET':
     return render('confirm.html', request,
-                  dict(url=request.path, title='Install sample tables and Beeswax examples?'))
+                  dict(url=request.path, title=_t('Install sample tables and Beeswax examples?')))
   elif request.method == 'POST':
     result = {}
     result['creationSucceeded'] = False
@@ -1153,7 +1150,7 @@ def install_examples(request):
 def describe_partitions(request, table):
   table_obj = db_utils.meta_client().get_table("default", table)
   if len(table_obj.partitionKeys) == 0:
-    raise PopupException("Table '%s' is not partitioned." % table)
+    raise PopupException(_t("Table '%(table)s' is not partitioned.") % {'table': table})
   partitions = db_utils.meta_client().get_partitions("default", table, max_parts=-1)
   return render("describe_partitions.mako", request,
                 dict(table=table_obj, partitions=partitions, request=request))