浏览代码

HUE-766 [core] Desktop i18n

Romain: solved conflicts + regenerated pot/po files
Enrico Berti 13 年之前
父节点
当前提交
166241a422

+ 3 - 1
desktop/core/src/desktop/appmanager.py

@@ -25,6 +25,8 @@ import pkg_resources
 import desktop
 import desktop
 from desktop.lib.paths import get_desktop_root
 from desktop.lib.paths import get_desktop_root
 
 
+from django.utils.translation import ugettext as _
+
 # Directories where apps and libraries are to be found
 # Directories where apps and libraries are to be found
 APP_DIRS = [get_desktop_root('core-apps'),
 APP_DIRS = [get_desktop_root('core-apps'),
             get_desktop_root('apps'),
             get_desktop_root('apps'),
@@ -219,7 +221,7 @@ def load_apps():
   global DESKTOP_APPS
   global DESKTOP_APPS
 
 
   if DESKTOP_APPS is not None:
   if DESKTOP_APPS is not None:
-    raise Exception("load_apps already has been called!")
+    raise Exception(_("load_apps already has been called!"))
   DESKTOP_APPS = []
   DESKTOP_APPS = []
 
 
   for sdk_app in pkg_resources.iter_entry_points("desktop.sdk.application"):
   for sdk_app in pkg_resources.iter_entry_points("desktop.sdk.application"):

+ 76 - 75
desktop/core/src/desktop/conf.py

@@ -23,49 +23,50 @@ from desktop.lib.paths import get_desktop_root
 import os
 import os
 import socket
 import socket
 import stat
 import stat
+from django.utils.translation import ugettext_lazy as _
 
 
 USE_CHERRYPY_SERVER = Config(
 USE_CHERRYPY_SERVER = Config(
   key="use_cherrypy_server",
   key="use_cherrypy_server",
-  help="If set to true, CherryPy will be used. Otherwise, Spawning will be used as the webserver.",
+  help=_("If set to true, CherryPy will be used. Otherwise, Spawning will be used as the webserver."),
   type=coerce_bool,
   type=coerce_bool,
   default=False)
   default=False)
 
 
 HTTP_HOST = Config(
 HTTP_HOST = Config(
   key="http_host",
   key="http_host",
-  help="HTTP Host to bind to",
+  help=_("HTTP Host to bind to"),
   type=str,
   type=str,
   default="0.0.0.0")
   default="0.0.0.0")
 HTTP_PORT = Config(
 HTTP_PORT = Config(
   key="http_port",
   key="http_port",
-  help="HTTP Port to bind to",
+  help=_("HTTP Port to bind to"),
   type=int,
   type=int,
   default=8888)
   default=8888)
 SSL_CERTIFICATE = Config(
 SSL_CERTIFICATE = Config(
   key="ssl_certificate",
   key="ssl_certificate",
-  help="Filename of SSL Certificate",
+  help=_("Filename of SSL Certificate"),
   default=None)
   default=None)
 SSL_PRIVATE_KEY = Config(
 SSL_PRIVATE_KEY = Config(
   key="ssl_private_key",
   key="ssl_private_key",
-  help="Filename of SSL RSA Private Key",
+  help=_("Filename of SSL RSA Private Key"),
   default=None)
   default=None)
 ENABLE_SERVER = Config(
 ENABLE_SERVER = Config(
   key="enable_server",
   key="enable_server",
-  help="If set to false, runcpserver will not actually start the web server.  Used if Apache is being used as a WSGI container.",
+  help=_("If set to false, runcpserver will not actually start the web server.  Used if Apache is being used as a WSGI container."),
   type=coerce_bool,
   type=coerce_bool,
   default=True)
   default=True)
 CHERRYPY_SERVER_THREADS = Config(
 CHERRYPY_SERVER_THREADS = Config(
   key="cherrypy_server_threads",
   key="cherrypy_server_threads",
-  help="Number of threads used by the CherryPy web server.",
+  help=_("Number of threads used by the CherryPy web server."),
   type=int,
   type=int,
   default=10)
   default=10)
 SECRET_KEY = Config(
 SECRET_KEY = Config(
   key="secret_key",
   key="secret_key",
-  help="Used in hashing algorithms for sessions.",
+  help=_("Used in hashing algorithms for sessions."),
   default="")
   default="")
 
 
 USER_ACCESS_HISTORY_SIZE = Config(
 USER_ACCESS_HISTORY_SIZE = Config(
   key="user_access_history_size",
   key="user_access_history_size",
-  help="Number of user access to remember per view per user.",
+  help=_("Number of user access to remember per view per user."),
   type=int,
   type=int,
   default=10)
   default=10)
 
 
@@ -90,46 +91,46 @@ def default_from_email():
 
 
 SMTP = ConfigSection(
 SMTP = ConfigSection(
   key='smtp',
   key='smtp',
-  help='Configuration options for connecting to an external SMTP server',
+  help=_('Configuration options for connecting to an external SMTP server'),
   members=dict(
   members=dict(
     HOST = Config(
     HOST = Config(
       key="host",
       key="host",
-      help="The SMTP server for email notification delivery",
+      help=_("The SMTP server for email notification delivery"),
       type=str,
       type=str,
       default="localhost"
       default="localhost"
     ),
     ),
 
 
     PORT = Config(
     PORT = Config(
       key="port",
       key="port",
-      help="The SMTP server port",
+      help=_("The SMTP server port"),
       type=int,
       type=int,
       default=25
       default=25
     ),
     ),
 
 
     USER = Config(
     USER = Config(
       key="user",
       key="user",
-      help="The username for the SMTP host",
+      help=_("The username for the SMTP host"),
       type=str,
       type=str,
       default=""
       default=""
     ),
     ),
 
 
     PASSWORD = Config(
     PASSWORD = Config(
       key="password",
       key="password",
-      help="The password for the SMTP user",
+      help=_("The password for the SMTP user"),
       type=str,
       type=str,
       default=""
       default=""
     ),
     ),
 
 
     USE_TLS = Config(
     USE_TLS = Config(
       key="tls",
       key="tls",
-      help="Whether to use a TLS (secure) connection when talking to the SMTP server",
+      help=_("Whether to use a TLS (secure) connection when talking to the SMTP server"),
       type=coerce_bool,
       type=coerce_bool,
       default=False
       default=False
     ),
     ),
 
 
     DEFAULT_FROM= Config(
     DEFAULT_FROM= Config(
       key="default_from_email",
       key="default_from_email",
-      help="Default email address to use for various automated notification from Hue",
+      help=_("Default email address to use for various automated notification from Hue"),
       type=str,
       type=str,
       dynamic_default=default_from_email
       dynamic_default=default_from_email
     ),
     ),
@@ -138,42 +139,42 @@ SMTP = ConfigSection(
 
 
 DATABASE = ConfigSection(
 DATABASE = ConfigSection(
   key='database',
   key='database',
-  help="""Configuration options for specifying the Desktop Database.
-          For more info, see http://docs.djangoproject.com/en/1.1/ref/settings/#database-engine""",
+  help=_("""Configuration options for specifying the Desktop Database.
+          For more info, see http://docs.djangoproject.com/en/1.1/ref/settings/#database-engine"""),
   members=dict(
   members=dict(
     ENGINE=Config(
     ENGINE=Config(
       key='engine',
       key='engine',
-      help='Database engine, eg postgresql, mysql, sqlite3, or oracle',
+      help=_('Database engine, eg postgresql, mysql, sqlite3, or oracle'),
       type=str,
       type=str,
       default='sqlite3',
       default='sqlite3',
     ),
     ),
     NAME=Config(
     NAME=Config(
       key='name',
       key='name',
-      help='Database name, or path to DB if using sqlite3',
+      help=_('Database name, or path to DB if using sqlite3'),
       type=str,
       type=str,
       default=get_desktop_root('desktop.db'),
       default=get_desktop_root('desktop.db'),
     ),
     ),
     USER=Config(
     USER=Config(
       key='user',
       key='user',
-      help='Database username',
+      help=_('Database username'),
       type=str,
       type=str,
       default='',
       default='',
     ),
     ),
     PASSWORD=Config(
     PASSWORD=Config(
       key='password',
       key='password',
-      help='Database password',
+      help=_('Database password'),
       type=str,
       type=str,
       default='',
       default='',
     ),
     ),
     HOST=Config(
     HOST=Config(
       key='host',
       key='host',
-      help='Database host',
+      help=_('Database host'),
       type=str,
       type=str,
       default='',
       default='',
     ),
     ),
     PORT=Config(
     PORT=Config(
       key='port',
       key='port',
-      help='Database port',
+      help=_('Database port'),
       type=int,
       type=int,
       default=0,
       default=0,
     ),
     ),
@@ -182,34 +183,34 @@ DATABASE = ConfigSection(
 
 
 KERBEROS = ConfigSection(
 KERBEROS = ConfigSection(
   key="kerberos",
   key="kerberos",
-  help="""Configuration options for specifying Hue's kerberos integration for
-          secured Hadoop clusters.""",
+  help=_("""Configuration options for specifying Hue's kerberos integration for
+          secured Hadoop clusters."""),
   members=dict(
   members=dict(
     HUE_KEYTAB=Config(
     HUE_KEYTAB=Config(
       key='hue_keytab',
       key='hue_keytab',
-      help="Path to a Kerberos keytab file containing Hue's service credentials.",
+      help=_("Path to a Kerberos keytab file containing Hue's service credentials."),
       type=str,
       type=str,
       default=None),
       default=None),
     HUE_PRINCIPAL=Config(
     HUE_PRINCIPAL=Config(
       key='hue_principal',
       key='hue_principal',
-      help="Kerberos principal name for hue. Typically 'hue/hostname.foo.com'",
+      help=_("Kerberos principal name for hue. Typically 'hue/hostname.foo.com'"),
       type=str,
       type=str,
       default="hue/%s" % socket.getfqdn()),
       default="hue/%s" % socket.getfqdn()),
     KEYTAB_REINIT_FREQUENCY=Config(
     KEYTAB_REINIT_FREQUENCY=Config(
       key='reinit_frequency',
       key='reinit_frequency',
-      help="Frequency in seconds with which Hue will renew its keytab",
+      help=_("Frequency in seconds with which Hue will renew its keytab"),
       type=int,
       type=int,
       default=60*60), #1h
       default=60*60), #1h
     CCACHE_PATH=Config(
     CCACHE_PATH=Config(
       key='ccache_path',
       key='ccache_path',
-      help="Path to keep kerberos credentials cached",
+      help=_("Path to keep kerberos credentials cached"),
       private=True,
       private=True,
       type=str,
       type=str,
       default="/tmp/hue_krb5_ccache",
       default="/tmp/hue_krb5_ccache",
     ),
     ),
     KINIT_PATH=Config(
     KINIT_PATH=Config(
       key='kinit_path',
       key='kinit_path',
-      help="Path to kerberos 'kinit' command",
+      help=_("Path to kerberos 'kinit' command"),
       type=str,
       type=str,
       default="kinit", # use PATH!
       default="kinit", # use PATH!
     )
     )
@@ -219,101 +220,101 @@ KERBEROS = ConfigSection(
 # See python's documentation for time.tzset for valid values.
 # See python's documentation for time.tzset for valid values.
 TIME_ZONE = Config(
 TIME_ZONE = Config(
   key="time_zone",
   key="time_zone",
-  help="Time zone name",
+  help=_("Time zone name"),
   type=str,
   type=str,
   default=os.environ.get("TZ", "America/Los_Angeles")
   default=os.environ.get("TZ", "America/Los_Angeles")
 )
 )
 
 
 DEFAULT_SITE_ENCODING = Config(
 DEFAULT_SITE_ENCODING = Config(
   key='default_site_encoding',
   key='default_site_encoding',
-  help='Default system-wide unicode encoding',
+  help=_('Default system-wide unicode encoding'),
   type=str,
   type=str,
   default='utf-8'
   default='utf-8'
 )
 )
 
 
 SERVER_USER = Config(
 SERVER_USER = Config(
   key="server_user",
   key="server_user",
-  help="Username to run servers as",
+  help=_("Username to run servers as"),
   type=str,
   type=str,
   default="hue")
   default="hue")
 SERVER_GROUP = Config(
 SERVER_GROUP = Config(
   key="server_group",
   key="server_group",
-  help="Group to run servers as",
+  help=_("Group to run servers as"),
   type=str,
   type=str,
   default="hue")
   default="hue")
 
 
 
 
 AUTH = ConfigSection(
 AUTH = ConfigSection(
   key="auth",
   key="auth",
-  help="Configuration options for user authentication into the web application",
+  help=_("Configuration options for user authentication into the web application"),
   members=dict(
   members=dict(
     BACKEND=Config("backend",
     BACKEND=Config("backend",
                    default="desktop.auth.backend.AllowFirstUserDjangoBackend",
                    default="desktop.auth.backend.AllowFirstUserDjangoBackend",
-                   help="Authentication backend.  Common settings are "
+                   help=_("Authentication backend.  Common settings are "
                         "django.contrib.auth.backends.ModelBackend (fully Django backend), " + 
                         "django.contrib.auth.backends.ModelBackend (fully Django backend), " + 
                         "desktop.auth.backend.AllowAllBackend (allows everyone), " +
                         "desktop.auth.backend.AllowAllBackend (allows everyone), " +
-                        "desktop.auth.backend.AllowFirstUserDjangoBackend (relies on Django and user manager, after the first login), "),
+                        "desktop.auth.backend.AllowFirstUserDjangoBackend (relies on Django and user manager, after the first login), ")),
     USER_AUGMENTOR=Config("user_augmentor",
     USER_AUGMENTOR=Config("user_augmentor",
                    default="desktop.auth.backend.DefaultUserAugmentor",
                    default="desktop.auth.backend.DefaultUserAugmentor",
-                   help="Class which defines extra accessor methods for User objects."),
+                   help=_("Class which defines extra accessor methods for User objects.")),
 ))
 ))
 
 
 LDAP = ConfigSection(
 LDAP = ConfigSection(
   key="ldap",
   key="ldap",
-  help="Configuration options for LDAP connectivity",
+  help=_("Configuration options for LDAP connectivity"),
   members=dict(
   members=dict(
     BASE_DN=Config("base_dn",
     BASE_DN=Config("base_dn",
                    default=None,
                    default=None,
-                   help="The base LDAP distinguished name to use for LDAP search."),
+                   help=_("The base LDAP distinguished name to use for LDAP search.")),
     NT_DOMAIN=Config("nt_domain",
     NT_DOMAIN=Config("nt_domain",
                      default=None,
                      default=None,
-                     help="The NT domain used for LDAP authentication."),
+                     help=_("The NT domain used for LDAP authentication.")),
     LDAP_URL=Config("ldap_url",
     LDAP_URL=Config("ldap_url",
                      default=None,
                      default=None,
-                     help="The LDAP URL to connect to."),
+                     help=_("The LDAP URL to connect to.")),
     LDAP_CERT=Config("ldap_cert",
     LDAP_CERT=Config("ldap_cert",
                      default=None,
                      default=None,
-                     help="The LDAP certificate for authentication over TLS."),
+                     help=_("The LDAP certificate for authentication over TLS.")),
     LDAP_USERNAME_PATTERN=Config("ldap_username_pattern",
     LDAP_USERNAME_PATTERN=Config("ldap_username_pattern",
                                  default=None,
                                  default=None,
-                                 help="A pattern to use for constructing LDAP usernames."),
+                                 help=_("A pattern to use for constructing LDAP usernames.")),
     BIND_DN=Config("bind_dn",
     BIND_DN=Config("bind_dn",
                    default=None,
                    default=None,
-                   help="The distinguished name to bind as, when importing from LDAP."),
+                   help=_("The distinguished name to bind as, when importing from LDAP.")),
     BIND_PASSWORD=Config("bind_password",
     BIND_PASSWORD=Config("bind_password",
                    default=None,
                    default=None,
-                   help="The password for the bind user."),
+                   help=_("The password for the bind user.")),
 
 
     USERS = ConfigSection(
     USERS = ConfigSection(
       key="users",
       key="users",
-      help="Configuration for LDAP user schema and search",
+      help=_("Configuration for LDAP user schema and search"),
       members=dict(
       members=dict(
         USER_FILTER=Config("user_filter",
         USER_FILTER=Config("user_filter",
                            default="objectclass=*",
                            default="objectclass=*",
-                           help="A base filter for use when searching for users."),
+                           help=_("A base filter for use when searching for users.")),
         USER_NAME_ATTR=Config("user_name_attr",
         USER_NAME_ATTR=Config("user_name_attr",
                               default="sAMAccountName",
                               default="sAMAccountName",
-                              help="The username attribute in the LDAP schema. "
+                              help=_("The username attribute in the LDAP schema. "
                                    "Typically, this is 'sAMAccountName' for AD and 'uid' "
                                    "Typically, this is 'sAMAccountName' for AD and 'uid' "
-                                   "for other LDAP systems."),
+                                   "for other LDAP systems.")),
       )
       )
     ),
     ),
 
 
     GROUPS = ConfigSection(
     GROUPS = ConfigSection(
       key="groups",
       key="groups",
-      help="Configuration for LDAP group schema and search",
+      help=_("Configuration for LDAP group schema and search"),
       members=dict(
       members=dict(
         GROUP_FILTER=Config("group_filter",
         GROUP_FILTER=Config("group_filter",
                            default="objectclass=*",
                            default="objectclass=*",
-                           help="A base filter for use when searching for groups."),
+                           help=_("A base filter for use when searching for groups.")),
         GROUP_NAME_ATTR=Config("group_name_attr",
         GROUP_NAME_ATTR=Config("group_name_attr",
                               default="cn",
                               default="cn",
-                              help="The group name attribute in the LDAP schema. "
-                                  "Typically, this is 'cn'."),
+                              help=_("The group name attribute in the LDAP schema. "
+                                  "Typically, this is 'cn'.")),
         GROUP_MEMBER_ATTR=Config("group_member_attr",
         GROUP_MEMBER_ATTR=Config("group_member_attr",
                                  default="member",
                                  default="member",
-                                 help="The LDAP attribute which specifies the "
-                                      "members of a group."),
+                                 help=_("The LDAP attribute which specifies the "
+                                      "members of a group.")),
       )
       )
     ),
     ),
 ))
 ))
@@ -322,12 +323,12 @@ LDAP = ConfigSection(
 
 
 LOCAL_FILESYSTEMS = UnspecifiedConfigSection(
 LOCAL_FILESYSTEMS = UnspecifiedConfigSection(
   key="local_filesystems",
   key="local_filesystems",
-  help="Paths on the local file system that users should be able to browse",
+  help=_("Paths on the local file system that users should be able to browse"),
   each=ConfigSection(
   each=ConfigSection(
     members=dict(
     members=dict(
       PATH=Config("path",
       PATH=Config("path",
                   required=True,
                   required=True,
-                  help="The path on the local FS"))))
+                  help=_("The path on the local FS")))))
 
 
 def default_feedback_url():
 def default_feedback_url():
   """A version-specific URL."""
   """A version-specific URL."""
@@ -335,36 +336,36 @@ def default_feedback_url():
   
   
 FEEDBACK_URL = Config(
 FEEDBACK_URL = Config(
   key="feedback_url",
   key="feedback_url",
-  help="Link for 'feedback' tab.",
+  help=_("Link for 'feedback' tab."),
   type=str,
   type=str,
   dynamic_default=default_feedback_url
   dynamic_default=default_feedback_url
 )
 )
 
 
 SEND_DBUG_MESSAGES = Config(
 SEND_DBUG_MESSAGES = Config(
   key="send_dbug_messages",
   key="send_dbug_messages",
-  help="Whether to send dbug messages from JavaScript to the server logs.",
+  help=_("Whether to send dbug messages from JavaScript to the server logs."),
   type=coerce_bool,
   type=coerce_bool,
   default=False
   default=False
 )
 )
 
 
 DATABASE_LOGGING = Config(
 DATABASE_LOGGING = Config(
   key="database_logging",
   key="database_logging",
-  help="If true, log all database requests.",
+  help=_("If true, log all database requests."),
   type=coerce_bool,
   type=coerce_bool,
   default=False)
   default=False)
 
 
 DJANGO_DEBUG_MODE = Config(
 DJANGO_DEBUG_MODE = Config(
   key="django_debug_mode",
   key="django_debug_mode",
-  help="Enable or disable django debug mode.",
+  help=_("Enable or disable django debug mode."),
   type=coerce_bool,
   type=coerce_bool,
   default=True
   default=True
 )
 )
 
 
 HTTP_500_DEBUG_MODE = Config(
 HTTP_500_DEBUG_MODE = Config(
   key='http_500_debug_mode',
   key='http_500_debug_mode',
-  help='Enable or disable debugging information in the 500 internal server error response. '
+  help=_('Enable or disable debugging information in the 500 internal server error response. '
        'Note that the debugging information may contain sensitive data. '
        'Note that the debugging information may contain sensitive data. '
-       'If django_debug_mode is True, this is automatically enabled.',
+       'If django_debug_mode is True, this is automatically enabled.'),
   type=coerce_bool,
   type=coerce_bool,
   default=True
   default=True
 )
 )
@@ -380,19 +381,19 @@ def config_validator():
 
 
   res = [ ]
   res = [ ]
   if not SECRET_KEY.get():
   if not SECRET_KEY.get():
-    res.append((SECRET_KEY, "Secret key should be configured as a random string."))
+    res.append((SECRET_KEY, unicode(_("Secret key should be configured as a random string."))))
 
 
   # Validate SSL setup
   # Validate SSL setup
   if SSL_CERTIFICATE.get():
   if SSL_CERTIFICATE.get():
     res.extend(validate_path(SSL_CERTIFICATE, is_dir=False))
     res.extend(validate_path(SSL_CERTIFICATE, is_dir=False))
     if not SSL_PRIVATE_KEY.get():
     if not SSL_PRIVATE_KEY.get():
-      res.append((SSL_PRIVATE_KEY, "SSL private key file should be set to enable HTTPS."))
+      res.append((SSL_PRIVATE_KEY, unicode(_("SSL private key file should be set to enable HTTPS."))))
     else:
     else:
       res.extend(validate_path(SSL_PRIVATE_KEY, is_dir=False))
       res.extend(validate_path(SSL_PRIVATE_KEY, is_dir=False))
 
 
   # Validate encoding
   # Validate encoding
   if not i18n.validate_encoding(DEFAULT_SITE_ENCODING.get()):
   if not i18n.validate_encoding(DEFAULT_SITE_ENCODING.get()):
-    res.append((DEFAULT_SITE_ENCODING, "Encoding not supported."))
+    res.append((DEFAULT_SITE_ENCODING, unicode(_("Encoding not supported."))))
 
 
   # Validate kerberos
   # Validate kerberos
   if KERBEROS.HUE_KEYTAB.get() is not None:
   if KERBEROS.HUE_KEYTAB.get() is not None:
@@ -401,8 +402,8 @@ def config_validator():
     kt_stat = os.stat(KERBEROS.HUE_KEYTAB.get())
     kt_stat = os.stat(KERBEROS.HUE_KEYTAB.get())
     if stat.S_IMODE(kt_stat.st_mode) & 0077:
     if stat.S_IMODE(kt_stat.st_mode) & 0077:
       res.append((KERBEROS.HUE_KEYTAB,
       res.append((KERBEROS.HUE_KEYTAB,
-                  "Keytab should have 0600 permissions (has %o)" %
-                  stat.S_IMODE(kt_stat.st_mode)))
+                  unicode(_("Keytab should have 0600 permissions (has %o)") %
+                  stat.S_IMODE(kt_stat.st_mode))))
 
 
     res.extend(validate_path(KERBEROS.KINIT_PATH, is_dir=False))
     res.extend(validate_path(KERBEROS.KINIT_PATH, is_dir=False))
     res.extend(validate_path(KERBEROS.CCACHE_PATH, is_dir=False))
     res.extend(validate_path(KERBEROS.CCACHE_PATH, is_dir=False))
@@ -411,20 +412,20 @@ def config_validator():
       LDAP.LDAP_USERNAME_PATTERN.get() is not None:
       LDAP.LDAP_USERNAME_PATTERN.get() is not None:
     if LDAP.LDAP_URL.get() is None:
     if LDAP.LDAP_URL.get() is None:
       res.append((LDAP.LDAP_URL,
       res.append((LDAP.LDAP_URL,
-                  "LDAP is only partially configured. An LDAP URL must be provided."))
+                  unicode(_("LDAP is only partially configured. An LDAP URL must be provided."))))
 
 
   if LDAP.LDAP_URL.get() is not None:
   if LDAP.LDAP_URL.get() is not None:
     if LDAP.NT_DOMAIN.get() is None and \
     if LDAP.NT_DOMAIN.get() is None and \
         LDAP.LDAP_USERNAME_PATTERN.get() is None:
         LDAP.LDAP_USERNAME_PATTERN.get() is None:
       res.append(LDAP.LDAP_URL,
       res.append(LDAP.LDAP_URL,
-                  "LDAP is only partially configured. An NT Domain or username "
-                  "search pattern must be provided.")
+                  unicode(_("LDAP is only partially configured. An NT Domain or username "
+                  "search pattern must be provided.")))
 
 
   if LDAP.LDAP_USERNAME_PATTERN.get() is not None and \
   if LDAP.LDAP_USERNAME_PATTERN.get() is not None and \
       '<username>' not in LDAP.LDAP_USERNAME_PATTERN.get():
       '<username>' not in LDAP.LDAP_USERNAME_PATTERN.get():
       res.append(LDAP.LDAP_USERNAME_PATTERN,
       res.append(LDAP.LDAP_USERNAME_PATTERN,
-                 "The LDAP username pattern should contain the special"
-                 "<username> replacement string for authentication.")
+                 unicode(_("The LDAP username pattern should contain the special"
+                 "<username> replacement string for authentication.")))
 
 
 
 
   return res
   return res

+ 2 - 1
desktop/core/src/desktop/decorators.py

@@ -17,6 +17,7 @@
 
 
 import logging
 import logging
 from desktop.lib.django_util import PopupException
 from desktop.lib.django_util import PopupException
+from django.utils.translation import ugettext as _
 
 
 try:
 try:
   from functools import wraps
   from functools import wraps
@@ -36,7 +37,7 @@ def hue_permission_required(action, app):
     @wraps(view_func)
     @wraps(view_func)
     def decorated(request, *args, **kwargs):
     def decorated(request, *args, **kwargs):
       if not request.user.has_hue_permission(action, app):
       if not request.user.has_hue_permission(action, app):
-        raise PopupException("Permission denied (%s/%s)" % (action, app))
+        raise PopupException(_("Permission denied (%(action)s/%(app)s)") % {'action': action, 'app': app})
       return view_func(request, *args, **kwargs)
       return view_func(request, *args, **kwargs)
     return decorated
     return decorated
   return decorator
   return decorator

+ 446 - 9
desktop/core/src/desktop/locale/django.pot

@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 msgstr ""
 "Project-Id-Version: PROJECT VERSION\n"
 "Project-Id-Version: PROJECT VERSION\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2012-07-09 21:58+0200\n"
+"POT-Creation-Date: 2012-07-23 10:40-0700\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,6 +17,344 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 0.9.6\n"
 "Generated-By: Babel 0.9.6\n"
 
 
+#: src/desktop/appmanager.py:224
+msgid "load_apps already has been called!"
+msgstr ""
+
+#: src/desktop/conf.py:30
+msgid ""
+"If set to true, CherryPy will be used. Otherwise, Spawning will be used "
+"as the webserver."
+msgstr ""
+
+#: src/desktop/conf.py:36
+msgid "HTTP Host to bind to"
+msgstr ""
+
+#: src/desktop/conf.py:41
+msgid "HTTP Port to bind to"
+msgstr ""
+
+#: src/desktop/conf.py:46
+msgid "Filename of SSL Certificate"
+msgstr ""
+
+#: src/desktop/conf.py:50
+msgid "Filename of SSL RSA Private Key"
+msgstr ""
+
+#: src/desktop/conf.py:54
+msgid ""
+"If set to false, runcpserver will not actually start the web server.  "
+"Used if Apache is being used as a WSGI container."
+msgstr ""
+
+#: src/desktop/conf.py:59
+msgid "Number of threads used by the CherryPy web server."
+msgstr ""
+
+#: src/desktop/conf.py:64
+msgid "Used in hashing algorithms for sessions."
+msgstr ""
+
+#: src/desktop/conf.py:69
+msgid "Number of user access to remember per view per user."
+msgstr ""
+
+#: src/desktop/conf.py:94
+msgid "Configuration options for connecting to an external SMTP server"
+msgstr ""
+
+#: src/desktop/conf.py:98
+msgid "The SMTP server for email notification delivery"
+msgstr ""
+
+#: src/desktop/conf.py:105
+msgid "The SMTP server port"
+msgstr ""
+
+#: src/desktop/conf.py:112
+msgid "The username for the SMTP host"
+msgstr ""
+
+#: src/desktop/conf.py:119
+msgid "The password for the SMTP user"
+msgstr ""
+
+#: src/desktop/conf.py:126
+msgid "Whether to use a TLS (secure) connection when talking to the SMTP server"
+msgstr ""
+
+#: src/desktop/conf.py:133
+msgid "Default email address to use for various automated notification from Hue"
+msgstr ""
+
+#: src/desktop/conf.py:142
+msgid ""
+"Configuration options for specifying the Desktop Database.\n"
+"          For more info, see "
+"http://docs.djangoproject.com/en/1.1/ref/settings/#database-engine"
+msgstr ""
+
+#: src/desktop/conf.py:147
+msgid "Database engine, eg postgresql, mysql, sqlite3, or oracle"
+msgstr ""
+
+#: src/desktop/conf.py:153
+msgid "Database name, or path to DB if using sqlite3"
+msgstr ""
+
+#: src/desktop/conf.py:159
+msgid "Database username"
+msgstr ""
+
+#: src/desktop/conf.py:165
+msgid "Database password"
+msgstr ""
+
+#: src/desktop/conf.py:171
+msgid "Database host"
+msgstr ""
+
+#: src/desktop/conf.py:177
+msgid "Database port"
+msgstr ""
+
+#: src/desktop/conf.py:186
+msgid ""
+"Configuration options for specifying Hue's kerberos integration for\n"
+"          secured Hadoop clusters."
+msgstr ""
+
+#: src/desktop/conf.py:191
+msgid "Path to a Kerberos keytab file containing Hue's service credentials."
+msgstr ""
+
+#: src/desktop/conf.py:196
+msgid "Kerberos principal name for hue. Typically 'hue/hostname.foo.com'"
+msgstr ""
+
+#: src/desktop/conf.py:201
+msgid "Frequency in seconds with which Hue will renew its keytab"
+msgstr ""
+
+#: src/desktop/conf.py:206
+msgid "Path to keep kerberos credentials cached"
+msgstr ""
+
+#: src/desktop/conf.py:213
+msgid "Path to kerberos 'kinit' command"
+msgstr ""
+
+#: src/desktop/conf.py:223
+msgid "Time zone name"
+msgstr ""
+
+#: src/desktop/conf.py:230
+msgid "Default system-wide unicode encoding"
+msgstr ""
+
+#: src/desktop/conf.py:237
+msgid "Username to run servers as"
+msgstr ""
+
+#: src/desktop/conf.py:242
+msgid "Group to run servers as"
+msgstr ""
+
+#: src/desktop/conf.py:249
+msgid "Configuration options for user authentication into the web application"
+msgstr ""
+
+#: src/desktop/conf.py:253
+msgid ""
+"Authentication backend.  Common settings are "
+"django.contrib.auth.backends.ModelBackend (fully Django backend), "
+"desktop.auth.backend.AllowAllBackend (allows everyone), "
+"desktop.auth.backend.AllowFirstUserDjangoBackend (relies on Django and "
+"user manager, after the first login), "
+msgstr ""
+
+#: src/desktop/conf.py:259
+msgid "Class which defines extra accessor methods for User objects."
+msgstr ""
+
+#: src/desktop/conf.py:264
+msgid "Configuration options for LDAP connectivity"
+msgstr ""
+
+#: src/desktop/conf.py:268
+msgid "The base LDAP distinguished name to use for LDAP search."
+msgstr ""
+
+#: src/desktop/conf.py:271
+msgid "The NT domain used for LDAP authentication."
+msgstr ""
+
+#: src/desktop/conf.py:274
+msgid "The LDAP URL to connect to."
+msgstr ""
+
+#: src/desktop/conf.py:277
+msgid "The LDAP certificate for authentication over TLS."
+msgstr ""
+
+#: src/desktop/conf.py:280
+msgid "A pattern to use for constructing LDAP usernames."
+msgstr ""
+
+#: src/desktop/conf.py:283
+msgid "The distinguished name to bind as, when importing from LDAP."
+msgstr ""
+
+#: src/desktop/conf.py:286
+msgid "The password for the bind user."
+msgstr ""
+
+#: src/desktop/conf.py:290
+msgid "Configuration for LDAP user schema and search"
+msgstr ""
+
+#: src/desktop/conf.py:294
+msgid "A base filter for use when searching for users."
+msgstr ""
+
+#: src/desktop/conf.py:297
+msgid ""
+"The username attribute in the LDAP schema. Typically, this is "
+"'sAMAccountName' for AD and 'uid' for other LDAP systems."
+msgstr ""
+
+#: src/desktop/conf.py:305
+msgid "Configuration for LDAP group schema and search"
+msgstr ""
+
+#: src/desktop/conf.py:309
+msgid "A base filter for use when searching for groups."
+msgstr ""
+
+#: src/desktop/conf.py:312
+msgid "The group name attribute in the LDAP schema. Typically, this is 'cn'."
+msgstr ""
+
+#: src/desktop/conf.py:316
+msgid "The LDAP attribute which specifies the members of a group."
+msgstr ""
+
+#: src/desktop/conf.py:326
+msgid "Paths on the local file system that users should be able to browse"
+msgstr ""
+
+#: src/desktop/conf.py:331
+msgid "The path on the local FS"
+msgstr ""
+
+#: src/desktop/conf.py:339
+msgid "Link for 'feedback' tab."
+msgstr ""
+
+#: src/desktop/conf.py:346
+msgid "Whether to send dbug messages from JavaScript to the server logs."
+msgstr ""
+
+#: src/desktop/conf.py:353
+msgid "If true, log all database requests."
+msgstr ""
+
+#: src/desktop/conf.py:359
+msgid "Enable or disable django debug mode."
+msgstr ""
+
+#: src/desktop/conf.py:366
+msgid ""
+"Enable or disable debugging information in the 500 internal server error "
+"response. Note that the debugging information may contain sensitive data."
+" If django_debug_mode is True, this is automatically enabled."
+msgstr ""
+
+#: src/desktop/conf.py:384
+msgid "Secret key should be configured as a random string."
+msgstr ""
+
+#: src/desktop/conf.py:390
+msgid "SSL private key file should be set to enable HTTPS."
+msgstr ""
+
+#: src/desktop/conf.py:396
+msgid "Encoding not supported."
+msgstr ""
+
+#: src/desktop/conf.py:405
+#, python-format
+msgid "Keytab should have 0600 permissions (has %o)"
+msgstr ""
+
+#: src/desktop/conf.py:415
+msgid "LDAP is only partially configured. An LDAP URL must be provided."
+msgstr ""
+
+#: src/desktop/conf.py:421
+msgid ""
+"LDAP is only partially configured. An NT Domain or username search "
+"pattern must be provided."
+msgstr ""
+
+#: src/desktop/conf.py:427
+msgid ""
+"The LDAP username pattern should contain the special<username> "
+"replacement string for authentication."
+msgstr ""
+
+#: src/desktop/decorators.py:40
+#, python-format
+msgid "Permission denied (%(action)s/%(app)s)"
+msgstr ""
+
+#: src/desktop/middleware.py:89
+#, python-format
+msgid "An error occurred: %(error)s"
+msgstr ""
+
+#: src/desktop/middleware.py:134
+#, python-format
+msgid "Cannot find HDFS called \"%(fs_ref)s\""
+msgstr ""
+
+#: src/desktop/middleware.py:215
+#, python-format
+msgid "%(module)s isn't a middleware module"
+msgstr ""
+
+#: src/desktop/middleware.py:220
+#, python-format
+msgid "Error importing middleware %(module)s: \"%(error)s\""
+msgstr ""
+
+#: src/desktop/middleware.py:224
+#, python-format
+msgid "Middleware module \"%(module)s\" does not define a \"%(class)s\" class"
+msgstr ""
+
+#: src/desktop/middleware.py:236
+#, python-format
+msgid ""
+"AppSpecificMiddleware module \"%(module)s\" has a process_request "
+"function which is impossible."
+msgstr ""
+
+#: src/desktop/middleware.py:278
+#, python-format
+msgid "You do not have permission to access the %(app_name)s application."
+msgstr ""
+
+#: src/desktop/views.py:56 src/desktop/views.py:94
+msgid "No logs found!"
+msgstr ""
+
+#: src/desktop/views.py:171 src/desktop/views.py:194 src/desktop/views.py:338
+msgid "You must be a superuser."
+msgstr ""
+
 #: src/desktop/lib/django_util.py:429
 #: src/desktop/lib/django_util.py:429
 msgid "year"
 msgid "year"
 msgid_plural "years"
 msgid_plural "years"
@@ -87,6 +425,110 @@ msgstr ""
 msgid "%(separator)s %(number)d %(type)s"
 msgid "%(separator)s %(number)d %(type)s"
 msgstr ""
 msgstr ""
 
 
+#: src/desktop/management/commands/config_dump.py:39
+msgid "Dumping configuration..."
+msgstr ""
+
+#: src/desktop/management/commands/config_dump.py:60
+#: src/desktop/management/commands/config_dump.py:70
+#: src/desktop/templates/dump_config.mako:82
+#: src/desktop/templates/dump_config.mako:94
+msgid "No help available."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:38
+msgid "Upgrades the Hue configuration with a mapping file."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:41
+msgid "Location of the mapping file."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:49
+#, python-format
+msgid "--%(param)s is required."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:60
+#, python-format
+msgid "Invalid mapping %(mapping)s in %(file)s"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:31
+msgid "Creates a Hue application directory structure."
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:33
+msgid "application name"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:37
+msgid "Expected arguments: app_name [app_dir]"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:45
+#, python-format
+msgid "App template dir missing: %(template)s"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:49
+#, python-format
+msgid "The template path, %(path)r, does not exist."
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:52
+#, python-format
+msgid ""
+"%(name)r is not a valid application name. Please use only numbers, "
+"letters and underscores."
+msgstr ""
+
+#: src/desktop/management/commands/create_test_fs.py:31
+#, python-format
+msgid "Created fs in: %(dir)s"
+msgstr ""
+
+#: src/desktop/management/commands/runcherrypyserver.py:47
+msgid "CherryPy Server for Desktop."
+msgstr ""
+
+#: src/desktop/management/commands/runcherrypyserver.py:108
+#, python-format
+msgid "starting server with options %(options)s"
+msgstr ""
+
+#: src/desktop/management/commands/runcpserver.py:34
+msgid "Web server for Hue."
+msgstr ""
+
+#: src/desktop/management/commands/runpylint.py:28
+msgid ""
+"\n"
+"  Runs pylint on desktop code.\n"
+"\n"
+"  With no arguments, or with \"all\", this will run pylint on all\n"
+"  installed apps.  Otherwise, specify modules to run, as well\n"
+"  as other parameters to pylint.  Note that you'll want to preface the "
+"section\n"
+"  of pylint arguments with \"--\" so Django's manage.py passes them "
+"along.\n"
+"\n"
+"  Examples:\n"
+"    python core/manage.py runpylint all -- -f parseable\n"
+"    python core/manage.py runpylint filebrowser\n"
+"    python core/manage.py runpylint\n"
+"  "
+msgstr ""
+
+#: src/desktop/management/commands/runpylint.py:61
+#, python-format
+msgid "Cannot find pylint at '%(path)s'. Please install pylint first."
+msgstr ""
+
+#: src/desktop/management/commands/runspawningserver.py:70
+msgid "Spawning Server for Hue."
+msgstr ""
+
 #: src/desktop/templates/404.mako:20
 #: src/desktop/templates/404.mako:20
 msgid "Not Found"
 msgid "Not Found"
 msgstr ""
 msgstr ""
@@ -147,15 +589,15 @@ msgstr ""
 msgid "All ok. Configuration check passed!"
 msgid "All ok. Configuration check passed!"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/common_header.mako:91
+#: src/desktop/templates/common_header.mako:92
 msgid "About Hue"
 msgid "About Hue"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/common_header.mako:98
+#: src/desktop/templates/common_header.mako:99
 msgid "Profile"
 msgid "Profile"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/common_header.mako:100
+#: src/desktop/templates/common_header.mako:101
 msgid "Sign Out"
 msgid "Sign Out"
 msgstr ""
 msgstr ""
 
 
@@ -171,11 +613,6 @@ msgstr ""
 msgid "Configuration Sections and Variables"
 msgid "Configuration Sections and Variables"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/dump_config.mako:82
-#: src/desktop/templates/dump_config.mako:94
-msgid "No help available."
-msgstr ""
-
 #: src/desktop/templates/dump_config.mako:95
 #: src/desktop/templates/dump_config.mako:95
 msgid "Default:"
 msgid "Default:"
 msgstr ""
 msgstr ""

+ 446 - 9
desktop/core/src/desktop/locale/en_US/LC_MESSAGES/django.po

@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 msgstr ""
 "Project-Id-Version: PROJECT VERSION\n"
 "Project-Id-Version: PROJECT VERSION\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2012-07-09 21:58+0200\n"
+"POT-Creation-Date: 2012-07-23 10:40-0700\n"
 "PO-Revision-Date: 2012-07-09 21:58+0200\n"
 "PO-Revision-Date: 2012-07-09 21:58+0200\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: en_US <LL@li.org>\n"
 "Language-Team: en_US <LL@li.org>\n"
@@ -17,6 +17,344 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 0.9.6\n"
 "Generated-By: Babel 0.9.6\n"
 
 
+#: src/desktop/appmanager.py:224
+msgid "load_apps already has been called!"
+msgstr ""
+
+#: src/desktop/conf.py:30
+msgid ""
+"If set to true, CherryPy will be used. Otherwise, Spawning will be used "
+"as the webserver."
+msgstr ""
+
+#: src/desktop/conf.py:36
+msgid "HTTP Host to bind to"
+msgstr ""
+
+#: src/desktop/conf.py:41
+msgid "HTTP Port to bind to"
+msgstr ""
+
+#: src/desktop/conf.py:46
+msgid "Filename of SSL Certificate"
+msgstr ""
+
+#: src/desktop/conf.py:50
+msgid "Filename of SSL RSA Private Key"
+msgstr ""
+
+#: src/desktop/conf.py:54
+msgid ""
+"If set to false, runcpserver will not actually start the web server.  "
+"Used if Apache is being used as a WSGI container."
+msgstr ""
+
+#: src/desktop/conf.py:59
+msgid "Number of threads used by the CherryPy web server."
+msgstr ""
+
+#: src/desktop/conf.py:64
+msgid "Used in hashing algorithms for sessions."
+msgstr ""
+
+#: src/desktop/conf.py:69
+msgid "Number of user access to remember per view per user."
+msgstr ""
+
+#: src/desktop/conf.py:94
+msgid "Configuration options for connecting to an external SMTP server"
+msgstr ""
+
+#: src/desktop/conf.py:98
+msgid "The SMTP server for email notification delivery"
+msgstr ""
+
+#: src/desktop/conf.py:105
+msgid "The SMTP server port"
+msgstr ""
+
+#: src/desktop/conf.py:112
+msgid "The username for the SMTP host"
+msgstr ""
+
+#: src/desktop/conf.py:119
+msgid "The password for the SMTP user"
+msgstr ""
+
+#: src/desktop/conf.py:126
+msgid "Whether to use a TLS (secure) connection when talking to the SMTP server"
+msgstr ""
+
+#: src/desktop/conf.py:133
+msgid "Default email address to use for various automated notification from Hue"
+msgstr ""
+
+#: src/desktop/conf.py:142
+msgid ""
+"Configuration options for specifying the Desktop Database.\n"
+"          For more info, see "
+"http://docs.djangoproject.com/en/1.1/ref/settings/#database-engine"
+msgstr ""
+
+#: src/desktop/conf.py:147
+msgid "Database engine, eg postgresql, mysql, sqlite3, or oracle"
+msgstr ""
+
+#: src/desktop/conf.py:153
+msgid "Database name, or path to DB if using sqlite3"
+msgstr ""
+
+#: src/desktop/conf.py:159
+msgid "Database username"
+msgstr ""
+
+#: src/desktop/conf.py:165
+msgid "Database password"
+msgstr ""
+
+#: src/desktop/conf.py:171
+msgid "Database host"
+msgstr ""
+
+#: src/desktop/conf.py:177
+msgid "Database port"
+msgstr ""
+
+#: src/desktop/conf.py:186
+msgid ""
+"Configuration options for specifying Hue's kerberos integration for\n"
+"          secured Hadoop clusters."
+msgstr ""
+
+#: src/desktop/conf.py:191
+msgid "Path to a Kerberos keytab file containing Hue's service credentials."
+msgstr ""
+
+#: src/desktop/conf.py:196
+msgid "Kerberos principal name for hue. Typically 'hue/hostname.foo.com'"
+msgstr ""
+
+#: src/desktop/conf.py:201
+msgid "Frequency in seconds with which Hue will renew its keytab"
+msgstr ""
+
+#: src/desktop/conf.py:206
+msgid "Path to keep kerberos credentials cached"
+msgstr ""
+
+#: src/desktop/conf.py:213
+msgid "Path to kerberos 'kinit' command"
+msgstr ""
+
+#: src/desktop/conf.py:223
+msgid "Time zone name"
+msgstr ""
+
+#: src/desktop/conf.py:230
+msgid "Default system-wide unicode encoding"
+msgstr ""
+
+#: src/desktop/conf.py:237
+msgid "Username to run servers as"
+msgstr ""
+
+#: src/desktop/conf.py:242
+msgid "Group to run servers as"
+msgstr ""
+
+#: src/desktop/conf.py:249
+msgid "Configuration options for user authentication into the web application"
+msgstr ""
+
+#: src/desktop/conf.py:253
+msgid ""
+"Authentication backend.  Common settings are "
+"django.contrib.auth.backends.ModelBackend (fully Django backend), "
+"desktop.auth.backend.AllowAllBackend (allows everyone), "
+"desktop.auth.backend.AllowFirstUserDjangoBackend (relies on Django and "
+"user manager, after the first login), "
+msgstr ""
+
+#: src/desktop/conf.py:259
+msgid "Class which defines extra accessor methods for User objects."
+msgstr ""
+
+#: src/desktop/conf.py:264
+msgid "Configuration options for LDAP connectivity"
+msgstr ""
+
+#: src/desktop/conf.py:268
+msgid "The base LDAP distinguished name to use for LDAP search."
+msgstr ""
+
+#: src/desktop/conf.py:271
+msgid "The NT domain used for LDAP authentication."
+msgstr ""
+
+#: src/desktop/conf.py:274
+msgid "The LDAP URL to connect to."
+msgstr ""
+
+#: src/desktop/conf.py:277
+msgid "The LDAP certificate for authentication over TLS."
+msgstr ""
+
+#: src/desktop/conf.py:280
+msgid "A pattern to use for constructing LDAP usernames."
+msgstr ""
+
+#: src/desktop/conf.py:283
+msgid "The distinguished name to bind as, when importing from LDAP."
+msgstr ""
+
+#: src/desktop/conf.py:286
+msgid "The password for the bind user."
+msgstr ""
+
+#: src/desktop/conf.py:290
+msgid "Configuration for LDAP user schema and search"
+msgstr ""
+
+#: src/desktop/conf.py:294
+msgid "A base filter for use when searching for users."
+msgstr ""
+
+#: src/desktop/conf.py:297
+msgid ""
+"The username attribute in the LDAP schema. Typically, this is "
+"'sAMAccountName' for AD and 'uid' for other LDAP systems."
+msgstr ""
+
+#: src/desktop/conf.py:305
+msgid "Configuration for LDAP group schema and search"
+msgstr ""
+
+#: src/desktop/conf.py:309
+msgid "A base filter for use when searching for groups."
+msgstr ""
+
+#: src/desktop/conf.py:312
+msgid "The group name attribute in the LDAP schema. Typically, this is 'cn'."
+msgstr ""
+
+#: src/desktop/conf.py:316
+msgid "The LDAP attribute which specifies the members of a group."
+msgstr ""
+
+#: src/desktop/conf.py:326
+msgid "Paths on the local file system that users should be able to browse"
+msgstr ""
+
+#: src/desktop/conf.py:331
+msgid "The path on the local FS"
+msgstr ""
+
+#: src/desktop/conf.py:339
+msgid "Link for 'feedback' tab."
+msgstr ""
+
+#: src/desktop/conf.py:346
+msgid "Whether to send dbug messages from JavaScript to the server logs."
+msgstr ""
+
+#: src/desktop/conf.py:353
+msgid "If true, log all database requests."
+msgstr ""
+
+#: src/desktop/conf.py:359
+msgid "Enable or disable django debug mode."
+msgstr ""
+
+#: src/desktop/conf.py:366
+msgid ""
+"Enable or disable debugging information in the 500 internal server error "
+"response. Note that the debugging information may contain sensitive data."
+" If django_debug_mode is True, this is automatically enabled."
+msgstr ""
+
+#: src/desktop/conf.py:384
+msgid "Secret key should be configured as a random string."
+msgstr ""
+
+#: src/desktop/conf.py:390
+msgid "SSL private key file should be set to enable HTTPS."
+msgstr ""
+
+#: src/desktop/conf.py:396
+msgid "Encoding not supported."
+msgstr ""
+
+#: src/desktop/conf.py:405
+#, python-format
+msgid "Keytab should have 0600 permissions (has %o)"
+msgstr ""
+
+#: src/desktop/conf.py:415
+msgid "LDAP is only partially configured. An LDAP URL must be provided."
+msgstr ""
+
+#: src/desktop/conf.py:421
+msgid ""
+"LDAP is only partially configured. An NT Domain or username search "
+"pattern must be provided."
+msgstr ""
+
+#: src/desktop/conf.py:427
+msgid ""
+"The LDAP username pattern should contain the special<username> "
+"replacement string for authentication."
+msgstr ""
+
+#: src/desktop/decorators.py:40
+#, python-format
+msgid "Permission denied (%(action)s/%(app)s)"
+msgstr ""
+
+#: src/desktop/middleware.py:89
+#, python-format
+msgid "An error occurred: %(error)s"
+msgstr ""
+
+#: src/desktop/middleware.py:134
+#, python-format
+msgid "Cannot find HDFS called \"%(fs_ref)s\""
+msgstr ""
+
+#: src/desktop/middleware.py:215
+#, python-format
+msgid "%(module)s isn't a middleware module"
+msgstr ""
+
+#: src/desktop/middleware.py:220
+#, python-format
+msgid "Error importing middleware %(module)s: \"%(error)s\""
+msgstr ""
+
+#: src/desktop/middleware.py:224
+#, python-format
+msgid "Middleware module \"%(module)s\" does not define a \"%(class)s\" class"
+msgstr ""
+
+#: src/desktop/middleware.py:236
+#, python-format
+msgid ""
+"AppSpecificMiddleware module \"%(module)s\" has a process_request "
+"function which is impossible."
+msgstr ""
+
+#: src/desktop/middleware.py:278
+#, python-format
+msgid "You do not have permission to access the %(app_name)s application."
+msgstr ""
+
+#: src/desktop/views.py:56 src/desktop/views.py:94
+msgid "No logs found!"
+msgstr ""
+
+#: src/desktop/views.py:171 src/desktop/views.py:194 src/desktop/views.py:338
+msgid "You must be a superuser."
+msgstr ""
+
 #: src/desktop/lib/django_util.py:429
 #: src/desktop/lib/django_util.py:429
 msgid "year"
 msgid "year"
 msgid_plural "years"
 msgid_plural "years"
@@ -87,6 +425,110 @@ msgstr ""
 msgid "%(separator)s %(number)d %(type)s"
 msgid "%(separator)s %(number)d %(type)s"
 msgstr ""
 msgstr ""
 
 
+#: src/desktop/management/commands/config_dump.py:39
+msgid "Dumping configuration..."
+msgstr ""
+
+#: src/desktop/management/commands/config_dump.py:60
+#: src/desktop/management/commands/config_dump.py:70
+#: src/desktop/templates/dump_config.mako:82
+#: src/desktop/templates/dump_config.mako:94
+msgid "No help available."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:38
+msgid "Upgrades the Hue configuration with a mapping file."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:41
+msgid "Location of the mapping file."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:49
+#, python-format
+msgid "--%(param)s is required."
+msgstr ""
+
+#: src/desktop/management/commands/config_upgrade.py:60
+#, python-format
+msgid "Invalid mapping %(mapping)s in %(file)s"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:31
+msgid "Creates a Hue application directory structure."
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:33
+msgid "application name"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:37
+msgid "Expected arguments: app_name [app_dir]"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:45
+#, python-format
+msgid "App template dir missing: %(template)s"
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:49
+#, python-format
+msgid "The template path, %(path)r, does not exist."
+msgstr ""
+
+#: src/desktop/management/commands/create_desktop_app.py:52
+#, python-format
+msgid ""
+"%(name)r is not a valid application name. Please use only numbers, "
+"letters and underscores."
+msgstr ""
+
+#: src/desktop/management/commands/create_test_fs.py:31
+#, python-format
+msgid "Created fs in: %(dir)s"
+msgstr ""
+
+#: src/desktop/management/commands/runcherrypyserver.py:47
+msgid "CherryPy Server for Desktop."
+msgstr ""
+
+#: src/desktop/management/commands/runcherrypyserver.py:108
+#, python-format
+msgid "starting server with options %(options)s"
+msgstr ""
+
+#: src/desktop/management/commands/runcpserver.py:34
+msgid "Web server for Hue."
+msgstr ""
+
+#: src/desktop/management/commands/runpylint.py:28
+msgid ""
+"\n"
+"  Runs pylint on desktop code.\n"
+"\n"
+"  With no arguments, or with \"all\", this will run pylint on all\n"
+"  installed apps.  Otherwise, specify modules to run, as well\n"
+"  as other parameters to pylint.  Note that you'll want to preface the "
+"section\n"
+"  of pylint arguments with \"--\" so Django's manage.py passes them "
+"along.\n"
+"\n"
+"  Examples:\n"
+"    python core/manage.py runpylint all -- -f parseable\n"
+"    python core/manage.py runpylint filebrowser\n"
+"    python core/manage.py runpylint\n"
+"  "
+msgstr ""
+
+#: src/desktop/management/commands/runpylint.py:61
+#, python-format
+msgid "Cannot find pylint at '%(path)s'. Please install pylint first."
+msgstr ""
+
+#: src/desktop/management/commands/runspawningserver.py:70
+msgid "Spawning Server for Hue."
+msgstr ""
+
 #: src/desktop/templates/404.mako:20
 #: src/desktop/templates/404.mako:20
 msgid "Not Found"
 msgid "Not Found"
 msgstr ""
 msgstr ""
@@ -147,15 +589,15 @@ msgstr ""
 msgid "All ok. Configuration check passed!"
 msgid "All ok. Configuration check passed!"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/common_header.mako:91
+#: src/desktop/templates/common_header.mako:92
 msgid "About Hue"
 msgid "About Hue"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/common_header.mako:98
+#: src/desktop/templates/common_header.mako:99
 msgid "Profile"
 msgid "Profile"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/common_header.mako:100
+#: src/desktop/templates/common_header.mako:101
 msgid "Sign Out"
 msgid "Sign Out"
 msgstr ""
 msgstr ""
 
 
@@ -171,11 +613,6 @@ msgstr ""
 msgid "Configuration Sections and Variables"
 msgid "Configuration Sections and Variables"
 msgstr ""
 msgstr ""
 
 
-#: src/desktop/templates/dump_config.mako:82
-#: src/desktop/templates/dump_config.mako:94
-msgid "No help available."
-msgstr ""
-
 #: src/desktop/templates/dump_config.mako:95
 #: src/desktop/templates/dump_config.mako:95
 msgid "Default:"
 msgid "Default:"
 msgstr ""
 msgstr ""

+ 5 - 3
desktop/core/src/desktop/management/commands/config_dump.py

@@ -25,6 +25,8 @@ from django.core.management.base import NoArgsCommand
 import desktop.appmanager
 import desktop.appmanager
 import textwrap
 import textwrap
 
 
+from django.utils.translation import ugettext as _
+
 from desktop.lib.conf import BoundContainer, is_anonymous
 from desktop.lib.conf import BoundContainer, is_anonymous
 
 
 class Command(NoArgsCommand):
 class Command(NoArgsCommand):
@@ -34,7 +36,7 @@ class Command(NoArgsCommand):
 
 
   """Prints documentation for configuration."""
   """Prints documentation for configuration."""
   def handle_noargs(self, **options):
   def handle_noargs(self, **options):
-    print "Dumping configuration..."
+    print _("Dumping configuration...")
     print
     print
     self.recurse(desktop.lib.conf.GLOBAL_CONFIG)
     self.recurse(desktop.lib.conf.GLOBAL_CONFIG)
 
 
@@ -55,7 +57,7 @@ class Command(NoArgsCommand):
 
 
       self.p("%s:" % key)
       self.p("%s:" % key)
       self.indent += 2
       self.indent += 2
-      print textwrap.fill(config_obj.config.help or "No help available.",
+      print textwrap.fill(config_obj.config.help or _("No help available."),
         initial_indent=" "*self.indent, subsequent_indent=" "*self.indent)
         initial_indent=" "*self.indent, subsequent_indent=" "*self.indent)
       print
       print
       for v in config_obj.get().values():
       for v in config_obj.get().values():
@@ -65,5 +67,5 @@ class Command(NoArgsCommand):
     else:
     else:
       self.p("%s=%s" % (config_obj.config.key, config_obj.get()))
       self.p("%s=%s" % (config_obj.config.key, config_obj.get()))
       self.indent += 2
       self.indent += 2
-      self.fill(config_obj.config.help or "No help available.")
+      self.fill(config_obj.config.help or _("No help available."))
       self.indent -= 2
       self.indent -= 2

+ 5 - 4
desktop/core/src/desktop/management/commands/config_upgrade.py

@@ -29,15 +29,16 @@ import desktop.log
 from optparse import make_option
 from optparse import make_option
 from desktop.lib.paths import get_desktop_root
 from desktop.lib.paths import get_desktop_root
 from django.core.management.base import BaseCommand, CommandError
 from django.core.management.base import BaseCommand, CommandError
+from django.utils.translation import ugettext as _
 
 
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):
   args = ''
   args = ''
-  help = 'Upgrades the Hue configuration with a mapping file.'
+  help = _('Upgrades the Hue configuration with a mapping file.')
 
 
   option_list = BaseCommand.option_list + (
   option_list = BaseCommand.option_list + (
-      make_option('--mapping_file', help='Location of the mapping file.'),
+      make_option('--mapping_file', help=_('Location of the mapping file.')),
   )
   )
 
 
   """Upgrades a configuration."""
   """Upgrades a configuration."""
@@ -45,7 +46,7 @@ class Command(BaseCommand):
     required = ("mapping_file",)
     required = ("mapping_file",)
     for r in required:
     for r in required:
       if not options.get(r):
       if not options.get(r):
-        raise CommandError("--%s is required." % r)
+        raise CommandError(_("--%(param)s is required.") % {'param': r})
   
   
     # Pull out all the mappings  
     # Pull out all the mappings  
     mapping_file = options["mapping_file"]
     mapping_file = options["mapping_file"]
@@ -56,7 +57,7 @@ class Command(BaseCommand):
       map_parts = map_parts.rstrip('/')
       map_parts = map_parts.rstrip('/')
       map_parts = map_parts.split('/')
       map_parts = map_parts.split('/')
       if len(map_parts) != 2:
       if len(map_parts) != 2:
-        raise CommandError("Invalid mapping %s in %s" % (mapping.strip(), mapping_file,))
+        raise CommandError(_("Invalid mapping %(mapping)s in %(file)s") % {'mapping': mapping.strip(), 'file': mapping_file})
       mappings.append(map_parts)
       mappings.append(map_parts)
 
 
     config_dir = os.getenv("HUE_CONF_DIR", get_desktop_root("conf"))
     config_dir = os.getenv("HUE_CONF_DIR", get_desktop_root("conf"))

+ 7 - 6
desktop/core/src/desktop/management/commands/create_desktop_app.py

@@ -23,17 +23,18 @@ from django.core.management.base import CommandError, BaseCommand
 from mako.template import Template
 from mako.template import Template
 
 
 import logging
 import logging
+from django.utils.translation import ugettext as _
 
 
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):
-  help = ("Creates a Hue application directory structure.")
+  help = _("Creates a Hue application directory structure.")
   args = "[appname]"
   args = "[appname]"
-  label = 'application name'
+  label = _('application name')
 
 
   def handle(self, *args, **options):
   def handle(self, *args, **options):
     if len(args) > 2 or len(args) == 0:
     if len(args) > 2 or len(args) == 0:
-      raise CommandError("Expected arguments: app_name [app_dir]")
+      raise CommandError(_("Expected arguments: app_name [app_dir]"))
     app_name = args[0]
     app_name = args[0]
     if len(args) == 2:
     if len(args) == 2:
       app_dir = args[0]
       app_dir = args[0]
@@ -41,14 +42,14 @@ class Command(BaseCommand):
       app_dir = os.getcwd()
       app_dir = os.getcwd()
 
 
     app_template = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','..','app_template'))
     app_template = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','..','app_template'))
-    assert os.path.isdir(app_template), "App template dir missing: " + app_template
+    assert os.path.isdir(app_template), _("App template dir missing: %(template)s") % {'template': app_template}
     app_dir = os.path.join(app_dir, app_name)
     app_dir = os.path.join(app_dir, app_name)
 
 
     if not os.path.exists(app_template):
     if not os.path.exists(app_template):
-      raise CommandError("The template path, %r, does not exist." % app_template)
+      raise CommandError(_("The template path, %(path)r, does not exist.") % {'path': app_template})
 
 
     if not re.search(r'^\w+$', app_name):
     if not re.search(r'^\w+$', app_name):
-      raise CommandError("%r is not a valid application name. Please use only numbers, letters and underscores." % app_name)
+      raise CommandError(_("%(name)r is not a valid application name. Please use only numbers, letters and underscores.") % {'name': app_name})
     try:
     try:
       os.makedirs(app_dir)
       os.makedirs(app_dir)
     except OSError, e:
     except OSError, e:

+ 2 - 1
desktop/core/src/desktop/management/commands/create_test_fs.py

@@ -19,6 +19,7 @@ from django.core.management.base import NoArgsCommand
 
 
 from desktop.lib.paths import get_build_dir
 from desktop.lib.paths import get_build_dir
 from hadoop.fs import fs_for_testing
 from hadoop.fs import fs_for_testing
+from django.utils.translation import ugettext as _
 
 
 class Command(NoArgsCommand):
 class Command(NoArgsCommand):
   """Creates file system for testing."""
   """Creates file system for testing."""
@@ -27,4 +28,4 @@ class Command(NoArgsCommand):
     if not os.path.isdir(fs_dir):
     if not os.path.isdir(fs_dir):
       os.makedirs(fs_dir)
       os.makedirs(fs_dir)
     fs_for_testing.create(fs_dir)
     fs_for_testing.create(fs_dir)
-    print "Created fs in: %s" % fs_dir
+    print _("Created fs in: %(dir)s") % {'dir': fs_dir}

+ 3 - 2
desktop/core/src/desktop/management/commands/runcherrypyserver.py

@@ -21,6 +21,7 @@ from django.core.management.base import BaseCommand
 
 
 from desktop import conf
 from desktop import conf
 from desktop.lib.daemon_utils import drop_privileges_if_necessary
 from desktop.lib.daemon_utils import drop_privileges_if_necessary
+from django.utils.translation import ugettext as _
 
 
 
 
 CPSERVER_HELP = r"""
 CPSERVER_HELP = r"""
@@ -43,7 +44,7 @@ CPSERVER_OPTIONS = {
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):
-    help = "CherryPy Server for Desktop."
+    help = _("CherryPy Server for Desktop.")
     args = ""
     args = ""
 
 
     def handle(self, *args, **options):
     def handle(self, *args, **options):
@@ -104,7 +105,7 @@ def runcpserver(argset=[], **kwargs):
         return
         return
 
 
     # Start the webserver
     # Start the webserver
-    print 'starting server with options %s' % options
+    print _('starting server with options %(options)s') % {'options': options}
     start_server(options)
     start_server(options)
 
 
 
 

+ 2 - 1
desktop/core/src/desktop/management/commands/runcpserver.py

@@ -21,6 +21,7 @@ from desktop import conf
 from desktop import supervisor
 from desktop import supervisor
 import os
 import os
 import sys
 import sys
+from django.utils.translation import ugettext as _
 
 
 SERVER_HELP = r"""
 SERVER_HELP = r"""
   Run Hue using either the CherryPy server or the Spawning server, based on
   Run Hue using either the CherryPy server or the Spawning server, based on
@@ -30,7 +31,7 @@ SERVER_HELP = r"""
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):
-  help = "Web server for Hue."
+  help = _("Web server for Hue.")
 
 
   def handle(self, *args, **options):
   def handle(self, *args, **options):
     runserver()
     runserver()

+ 4 - 3
desktop/core/src/desktop/management/commands/runpylint.py

@@ -22,9 +22,10 @@ import subprocess
 from django.core.management.base import BaseCommand, CommandError
 from django.core.management.base import BaseCommand, CommandError
 from django.conf import settings
 from django.conf import settings
 from desktop.lib import paths
 from desktop.lib import paths
+from django.utils.translation import ugettext as _
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):
-  help = """
+  help = _("""
   Runs pylint on desktop code.
   Runs pylint on desktop code.
 
 
   With no arguments, or with "all", this will run pylint on all
   With no arguments, or with "all", this will run pylint on all
@@ -36,7 +37,7 @@ class Command(BaseCommand):
     python core/manage.py runpylint all -- -f parseable
     python core/manage.py runpylint all -- -f parseable
     python core/manage.py runpylint filebrowser
     python core/manage.py runpylint filebrowser
     python core/manage.py runpylint
     python core/manage.py runpylint
-  """
+  """)
 
 
   def handle(self, *args, **options):
   def handle(self, *args, **options):
     """Check the source code using PyLint."""
     """Check the source code using PyLint."""
@@ -57,7 +58,7 @@ class Command(BaseCommand):
     pylint_args = [pylint_prog, "--rcfile=" + settings.PYLINTRC] + pylint_args
     pylint_args = [pylint_prog, "--rcfile=" + settings.PYLINTRC] + pylint_args
 
 
     if not os.path.exists(pylint_prog):
     if not os.path.exists(pylint_prog):
-      msg = "Cannot find pylint at '%s'. Please install pylint first." % (pylint_prog,)
+      msg = _("Cannot find pylint at '%(path)s'. Please install pylint first.") % {'path': pylint_prog}
       logging.error(msg)
       logging.error(msg)
       raise CommandError(msg)
       raise CommandError(msg)
 
 

+ 3 - 1
desktop/core/src/desktop/management/commands/runspawningserver.py

@@ -27,6 +27,8 @@ from desktop import conf
 import spawning.spawning_controller
 import spawning.spawning_controller
 from desktop.lib.daemon_utils import drop_privileges_if_necessary
 from desktop.lib.daemon_utils import drop_privileges_if_necessary
 
 
+from django.utils.translation import ugettext as _
+
 SPAWNING_SERVER_HELP = r"""
 SPAWNING_SERVER_HELP = r"""
   Run Hue using the Spawning WSGI server in asynchronous mode.
   Run Hue using the Spawning WSGI server in asynchronous mode.
 """
 """
@@ -65,7 +67,7 @@ SPAWNING_SERVER_OPTIONS = {
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):
-    help = "Spawning Server for Hue."
+    help = _("Spawning Server for Hue.")
 
 
     def handle(self, *args, **options):
     def handle(self, *args, **options):
         from django.conf import settings
         from django.conf import settings

+ 10 - 8
desktop/core/src/desktop/middleware.py

@@ -39,6 +39,8 @@ from desktop import appmanager
 from hadoop import cluster
 from hadoop import cluster
 import simplejson
 import simplejson
 
 
+from django.utils.translation import ugettext as _
+
 MIDDLEWARE_HEADER = "X-Hue-Middleware-Response"
 MIDDLEWARE_HEADER = "X-Hue-Middleware-Response"
 
 
 # Views inside Django that don't require login
 # Views inside Django that don't require login
@@ -84,7 +86,7 @@ class ExceptionMiddleware(object):
     # need to do some kind of nicer handling than the built-in page
     # need to do some kind of nicer handling than the built-in page
     # Note that exception may actually be an Http404 or similar.
     # Note that exception may actually be an Http404 or similar.
     if request.ajax:
     if request.ajax:
-      err = "An error occurred: %s" % (exception,)
+      err = _("An error occurred: %(error)s") % {'error': exception}
       logging.exception("Middleware caught an exception")
       logging.exception("Middleware caught an exception")
       return PopupException(err, detail=None).response(request)
       return PopupException(err, detail=None).response(request)
 
 
@@ -129,7 +131,7 @@ class ClusterMiddleware(object):
     try:
     try:
       request.fs = cluster.get_hdfs(request.fs_ref)
       request.fs = cluster.get_hdfs(request.fs_ref)
     except KeyError:
     except KeyError:
-      raise KeyError('Cannot find HDFS called "%s"' % (request.fs_ref,))
+      raise KeyError(_('Cannot find HDFS called "%(fs_ref)s"') % {'fs_ref': request.fs_ref})
 
 
     if request.user.is_authenticated():
     if request.user.is_authenticated():
       if request.fs is not None:
       if request.fs is not None:
@@ -210,16 +212,16 @@ class AppSpecificMiddleware(object):
       try:
       try:
           dot = middleware_path.rindex('.')
           dot = middleware_path.rindex('.')
       except ValueError:
       except ValueError:
-          raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
+          raise exceptions.ImproperlyConfigured, _('%(module)s isn\'t a middleware module') % {'module': middleware_path}
       mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
       mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
       try:
       try:
           mod = __import__(mw_module, {}, {}, [''])
           mod = __import__(mw_module, {}, {}, [''])
       except ImportError, e:
       except ImportError, e:
-          raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
+          raise exceptions.ImproperlyConfigured, _('Error importing middleware %(module)s: "%(error)s"') % {'module': mw_module, 'error': e}
       try:
       try:
           mw_class = getattr(mod, mw_classname)
           mw_class = getattr(mod, mw_classname)
       except AttributeError:
       except AttributeError:
-          raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
+          raise exceptions.ImproperlyConfigured, _('Middleware module "%(module)s" does not define a "%(class)s" class') % {'module': mw_module, 'class':mw_classname}
 
 
       try:
       try:
         mw_instance = mw_class()
         mw_instance = mw_class()
@@ -231,8 +233,8 @@ class AppSpecificMiddleware(object):
       # application will handle the request at the point process_request is called
       # application will handle the request at the point process_request is called
       if hasattr(mw_instance, 'process_request'):
       if hasattr(mw_instance, 'process_request'):
         raise exceptions.ImproperlyConfigured, \
         raise exceptions.ImproperlyConfigured, \
-              ('AppSpecificMiddleware module "%s" has a process_request function' + \
-              ' which is impossible.') % middleware_path
+              _('AppSpecificMiddleware module "%(module)s" has a process_request function' + \
+              ' which is impossible.') % {'module': middleware_path}
       if hasattr(mw_instance, 'process_view'):
       if hasattr(mw_instance, 'process_view'):
         result['view'].append(mw_instance.process_view)
         result['view'].append(mw_instance.process_view)
       if hasattr(mw_instance, 'process_response'):
       if hasattr(mw_instance, 'process_response'):
@@ -273,7 +275,7 @@ class LoginAndPermissionMiddleware(object):
           request._desktop_app != "desktop" and \
           request._desktop_app != "desktop" and \
           not request.user.has_hue_permission(action="access", app=request._desktop_app):
           not request.user.has_hue_permission(action="access", app=request._desktop_app):
         access_log(request, 'permission denied', level=access_log_level)
         access_log(request, 'permission denied', level=access_log_level)
-        return PopupException("You do not have permission to access the %s application." % (request._desktop_app.capitalize())).response(request)
+        return PopupException(_("You do not have permission to access the %(app_name)s application.") % {'app_name': request._desktop_app.capitalize()}).response(request)
       else:
       else:
         log_page_hit(request, view_func, level=access_log_level)
         log_page_hit(request, view_func, level=access_log_level)
         return None
         return None

+ 7 - 5
desktop/core/src/desktop/views.py

@@ -37,6 +37,8 @@ from desktop import appmanager
 import desktop.conf
 import desktop.conf
 import desktop.log.log_buffer
 import desktop.log.log_buffer
 
 
+from django.utils.translation import ugettext as _
+
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 @access_log_level(logging.WARN)
 @access_log_level(logging.WARN)
@@ -51,7 +53,7 @@ def log_view(request):
     if isinstance(h, desktop.log.log_buffer.FixedBufferHandler):
     if isinstance(h, desktop.log.log_buffer.FixedBufferHandler):
       return render('logs.mako', request, dict(log=[l for l in h.buf]))
       return render('logs.mako', request, dict(log=[l for l in h.buf]))
 
 
-  return render('logs.mako', request, dict(log=["No logs found!"]))
+  return render('logs.mako', request, dict(log=[_("No logs found!")]))
 
 
 @access_log_level(logging.WARN)
 @access_log_level(logging.WARN)
 def download_log_view(request):
 def download_log_view(request):
@@ -89,7 +91,7 @@ def download_log_view(request):
         logging.exception("Couldn't construct zip file to write logs to!")
         logging.exception("Couldn't construct zip file to write logs to!")
         return log_view(request)
         return log_view(request)
 
 
-  return render_to_response("logs.html", dict(log=["No logs found!"]))
+  return render_to_response("logs.mako", dict(log=[_("No logs found!")]))
 
 
 
 
 @access_log_level(logging.DEBUG)
 @access_log_level(logging.DEBUG)
@@ -166,7 +168,7 @@ def dump_config(request):
   conf_dir = os.path.realpath(get_desktop_root('conf'))
   conf_dir = os.path.realpath(get_desktop_root('conf'))
 
 
   if not request.user.is_superuser:
   if not request.user.is_superuser:
-    return HttpResponse("You must be a superuser.")
+    return HttpResponse(_("You must be a superuser."))
 
 
   if request.GET.get("private"):
   if request.GET.get("private"):
     show_private = True
     show_private = True
@@ -189,7 +191,7 @@ else:
 def threads(request):
 def threads(request):
   """Dumps out server threads.  Useful for debugging."""
   """Dumps out server threads.  Useful for debugging."""
   if not request.user.is_superuser:
   if not request.user.is_superuser:
-    return HttpResponse("You must be a superuser.")
+    return HttpResponse(_("You must be a superuser."))
 
 
   out = []
   out = []
   for thread_id, stack in _threads():
   for thread_id, stack in _threads():
@@ -333,7 +335,7 @@ def _get_config_errors(cache=True):
 def check_config(request):
 def check_config(request):
   """Check config and view for the list of errors"""
   """Check config and view for the list of errors"""
   if not request.user.is_superuser:
   if not request.user.is_superuser:
-    return HttpResponse("You must be a superuser.")
+    return HttpResponse(_("You must be a superuser."))
   conf_dir = os.path.realpath(get_desktop_root('conf'))
   conf_dir = os.path.realpath(get_desktop_root('conf'))
   return render('check_config.mako', request, dict(
   return render('check_config.mako', request, dict(
                     error_list=_get_config_errors(cache=False),
                     error_list=_get_config_errors(cache=False),