Index: htdocs/js/trac.js =================================================================== --- htdocs/js/trac.js (revision 5935) +++ htdocs/js/trac.js (working copy) @@ -129,3 +129,44 @@ addLinks(container.getElementsByTagName('h' + lvl)); } } + +function clearAuthenticationCache(page) { + // Default to a non-existing page (give error 500). + // An empty page is better, here. + if (!page) page = '.force_logout'; + try{ + var agt=navigator.userAgent.toLowerCase(); + if (agt.indexOf("msie") != -1) { + // IE clear HTTP Authentication + document.execCommand("ClearAuthenticationCache"); + } + else { + // Let's create an xmlhttp object + var xmlhttp = createXMLObject(); + // Let's prepare invalid credentials + xmlhttp.open("GET", page, true, "logout", "logout"); + // Let's send the request to the server + xmlhttp.send(""); + // Let's abort the request + xmlhttp.abort(); + } + } catch(e) { + // There was an error + return; + } +} + +function createXMLObject() { + try { + if (window.XMLHttpRequest) { + xmlhttp = new XMLHttpRequest(); + } + // code for IE + else if (window.ActiveXObject) { + xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + } catch (e) { + xmlhttp=false + } + return xmlhttp; +} Index: trac/env.py =================================================================== --- trac/env.py (revision 5935) +++ trac/env.py (working copy) @@ -70,19 +70,19 @@ setups, usually involving running Trac behind a HTTP proxy, you may need to use this option to force Trac to use the correct URL.""") - project_name = Option('project', 'name', 'My Project', + project_name = Option('project', 'name', 'Mi Proyecto', """Name of the project.""") - project_description = Option('project', 'descr', 'My example project', + project_description = Option('project', 'descr', 'Mi proyecto ejemplo', """Short description of the project.""") - project_url = Option('project', 'url', 'http://example.org/', + project_url = Option('project', 'url', 'http://ejemplo.org/', """URL of the main project web site.""") project_footer = Option('project', 'footer', - 'Visit the Trac open source project at
' + unicode('Visite el proyecto de código abierto Trac en
' '' - 'http://trac.edgewall.org/', + 'http://trac.edgewall.org/', 'utf-8'), """Page footer text (right-aligned).""") project_icon = Option('project', 'icon', 'common/trac.ico', @@ -330,7 +330,7 @@ db_str = self.config.get('trac', 'database') if not db_str.startswith('sqlite:'): - raise EnvironmentError('Can only backup sqlite databases') + raise EnvironmentError(unicode('Sólo se pueden realizar copias de seguridad de las bases de datos sqlite', 'utf-8')) db_name = os.path.join(self.path, db_str[7:]) if not dest: dest = '%s.%i.bak' % (db_name, self.get_version()) @@ -398,7 +398,7 @@ if dbver == db_default.db_version: return False elif dbver > db_default.db_version: - raise TracError, 'Database newer than Trac version' + raise TracError, unicode('La base de datos es más actual que la versión de Trac', 'utf-8') return True def upgrade_environment(self, db): @@ -410,7 +410,7 @@ upgrades = __import__('upgrades', globals(), locals(), [name]) script = getattr(upgrades, name) except AttributeError: - err = 'No upgrade module for version %i (%s.py)' % (i, name) + err = unicode('No existe un módulo de actualización para la versión %i (%s.py)', 'utf-8') % (i, name) raise TracError, err script.do_upgrade(self.env, i, cursor) cursor.execute("UPDATE system SET value=%s WHERE " @@ -448,12 +448,12 @@ if not env_path: env_path = os.getenv('TRAC_ENV') if not env_path: - raise TracError, 'Missing environment variable "TRAC_ENV". Trac ' \ - 'requires this variable to point to a valid Trac ' \ - 'environment.' + raise TracError, unicode('Falta la variable de entorno "TRAC_ENV". Trac ' \ + 'requiere que esta variable apunte a un entorno Trac ' \ + 'válido.', 'utf-8') env = Environment(env_path) if env.needs_upgrade(): - raise TracError, 'The Trac Environment needs to be upgraded. Run ' \ + raise TracError, 'El entorno Trac necesita ser actualizado. Ejecute ' \ 'trac-admin %s upgrade"' % env_path return env Index: trac/core.py =================================================================== --- trac/core.py (revision 5935) +++ trac/core.py (working copy) @@ -45,7 +45,7 @@ """ property.__init__(self, self.extensions) self.interface = interface - self.__doc__ = 'List of components that implement `%s`' % \ + self.__doc__ = 'Lista de componentes que implementan `%s`' % \ self.interface.__name__ def extensions(self, component): @@ -56,7 +56,7 @@ def __repr__(self): """Return a textual representation of the extension point.""" - return '' % self.interface.__name__ + return unicode('', 'utf-8') % self.interface.__name__ class ComponentMeta(type): @@ -174,11 +174,11 @@ component = self.components.get(cls) if not component: if cls not in ComponentMeta._components: - raise TracError, 'Component "%s" not registered' % cls.__name__ + raise TracError, unicode('El componente "%s" no está registrado', 'utf-8') % cls.__name__ try: component = cls(self) except TypeError, e: - raise TracError, 'Unable to instantiate component %r (%s)' \ + raise TracError, 'No se puede instanciar el componente %r (%s)' \ % (cls, e) return component Index: trac/attachment.py =================================================================== --- trac/attachment.py (revision 5935) +++ trac/attachment.py (working copy) @@ -100,8 +100,8 @@ cursor.close() if not row: self.filename = filename - raise TracError('Attachment %s does not exist.' % (self.title), - 'Invalid Attachment') + raise TracError('El adjunto %s no existe.' % (self.title), + unicode('Adjunto Inválido', 'utf-8')) self.filename = row[0] self.description = row[1] self.size = row[2] and int(row[2]) or 0 @@ -130,7 +130,7 @@ title = property(_get_title) def delete(self, db=None): - assert self.filename, 'Cannot delete non-existent attachment' + assert self.filename, 'No se puede eliminar un adjunto que no existe' if not db: db = self.env.get_db_cnx() handle_ta = True @@ -149,7 +149,7 @@ self.path, exc_info=True) if handle_ta: db.rollback() - raise TracError, 'Could not delete attachment' + raise TracError, 'No se pudo eliminar el adjunto' self.env.log.info('Attachment removed: %s' % self.title) if handle_ta: @@ -250,7 +250,7 @@ try: fd = open(self.path, 'rb') except IOError: - raise TracError('Attachment %s not found' % self.filename) + raise TracError(unicode('El adjunto %s no fué encontrado', 'utf-8') % self.filename) return fd @@ -336,9 +336,9 @@ parent_type = req.args.get('type') path = req.args.get('path') if not parent_type or not path: - raise HTTPBadRequest('Bad request') + raise HTTPBadRequest('Mala solicitud') if not parent_type in ['ticket', 'wiki']: - raise HTTPBadRequest('Unknown attachment type') + raise HTTPBadRequest('Tipo de adjunto desconocido') action = req.args.get('action', 'view') if action == 'new': @@ -351,7 +351,7 @@ self._render_list(req, parent_type, last_segment) return 'attachment.cs', None if not last_segment: - raise HTTPBadRequest('Bad request') + raise HTTPBadRequest('Mala solicitud') attachment = Attachment(self.env, parent_type, parent_id, last_segment) parent_link, parent_text = self._parent_to_hdf( @@ -419,7 +419,7 @@ for change, type, id, filename, time, descr, author in \ self.get_history(start, stop, type): title = html.EM(os.path.basename(filename)) + \ - ' attached to ' + display(id) + ' adjunto a ' + display(id) if format == 'rss': title = Markup(title).striptags() descr = wiki_to_html(descr or '--', self.env, req, db, @@ -427,7 +427,7 @@ href = req.abs_href else: descr = wiki_to_oneliner(descr, self.env, db, shorten=True) - title += Markup(' by %s', author) + title += Markup(' por %s', author) href = req.href yield('attachment', href.attachment(type, id, filename), title, time, author, descr) @@ -443,7 +443,7 @@ upload = req.args['attachment'] if not hasattr(upload, 'filename') or not upload.filename: - raise TracError('No file uploaded') + raise TracError(unicode('No se cargó el archivo adjunto', 'utf-8')) if hasattr(upload.file, 'fileno'): size = os.fstat(upload.file.fileno())[6] else: @@ -451,13 +451,13 @@ size = upload.file.tell() upload.file.seek(0) if size == 0: - raise TracError("Can't upload empty file") + raise TracError(unicode('No se puede cargar un fichero vacío', 'utf-8')) # Maximum attachment size (in bytes) max_size = self.max_size if max_size >= 0 and size > max_size: - raise TracError('Maximum attachment size: %d bytes' % max_size, - 'Upload failed') + raise TracError(unicode('El tamaño máximo para adjuntos es: %d bytes', 'utf-8') % max_size, + unicode('La carga del adjunto falló', 'utf-8')) # We try to normalize the filename to unicode NFC if we can. # Files uploaded from OS X might be in NFD. @@ -466,7 +466,7 @@ filename = filename.replace('\\', '/').replace(':', '/') filename = os.path.basename(filename) if not filename: - raise TracError('No file uploaded') + raise TracError(unicode('No se cargó el archivo adjunto', 'utf-8')) attachment.description = req.args.get('description', '') attachment.author = get_reporter_id(req, 'author') @@ -476,10 +476,10 @@ for manipulator in self.manipulators: for field, message in manipulator.validate_attachment(req, attachment): if field: - raise InvalidAttachment('Attachment field %s is invalid: %s' + raise InvalidAttachment(unicode('El campo -adjunto- %s es inválido: %s', 'utf-8') % (field, message)) else: - raise InvalidAttachment('Invalid attachment: %s' % message) + raise InvalidAttachment(unicode('Adjunto inválido: %s', 'utf-8') % message) if req.args.get('replace'): try: @@ -514,7 +514,7 @@ perm_map = {'ticket': 'TICKET_ADMIN', 'wiki': 'WIKI_DELETE'} req.perm.assert_permission(perm_map[attachment.parent_type]) - req.hdf['title'] = '%s (delete)' % attachment.title + req.hdf['title'] = '%s (eliminar)' % attachment.title req.hdf['attachment'] = {'filename': attachment.filename, 'mode': 'delete'} @@ -576,12 +576,12 @@ if (self.render_unsafe_content and mime_type and not mime_type.startswith('text/plain')): plaintext_href = attachment.href(req, format='txt') - add_link(req, 'alternate', plaintext_href, 'Plain Text', + add_link(req, 'alternate', plaintext_href, 'Texto Plano', mime_type) # add ''Original Format'' alternate link (always) raw_href = attachment.href(req, format='raw') - add_link(req, 'alternate', raw_href, 'Original Format', mime_type) + add_link(req, 'alternate', raw_href, 'Formato Original', mime_type) self.log.debug("Rendering preview of file %s with mime-type %s" % (attachment.filename, mime_type)) @@ -622,7 +622,7 @@ if formatter.req: href = attachment.href(formatter.req) + params return html.A(label, class_='attachment', href=href, - title='Attachment %s' % attachment.title) + title='Adjunto %s' % attachment.title) except TracError: return html.A(label, class_='missing attachment', rel='nofollow', href=formatter.href()) Index: trac/db_default.py =================================================================== --- trac/db_default.py (revision 5935) +++ trac/db_default.py (working copy) @@ -166,106 +166,106 @@ def get_reports(db): owner = db.concat('owner', "' *'") return ( -('Active Tickets', +('Tickets Activos', """ - * List all active tickets by priority. - * Color each row based on priority. - * If a ticket has been accepted, a '*' is appended after the owner's name + * Listar todos los tickets activos por prioridad. + * Colorear cada fila de acuerdo a la prioridad. + * Si un ticket ha sido aceptado, se añadirá un '*' después del nombre del responsable """, """ SELECT p.value AS __color__, - id AS ticket, summary, component, version, milestone, t.type AS type, - (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS owner, + id AS ticket, summary AS summary, component AS componente, version AS versión, milestone AS Hito, t.type AS tipo, + (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS responsable, time AS created, - changetime AS _changetime, description AS _description, - reporter AS _reporter + changetime AS _ultimo_cambio, description AS _description, + reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE status IN ('new', 'assigned', 'reopened') ORDER BY p.value, milestone, t.type, time """ % owner), #---------------------------------------------------------------------------- - ('Active Tickets by Version', + ('Tickets Activos por Versión', """ -This report shows how to color results by priority, -while grouping results by version. +Este reporte muestra cómo colorear los resultados por prioridad, +y al mismo tiempo, agruparlos por versión. -Last modification time, description and reporter are included as hidden fields -for useful RSS export. +Fecha de la última modificación, descripción y quién-lo-reportó se incluyen como campos ocultos +para su útil exportación hacia RSS. """, """ SELECT p.value AS __color__, version AS __group__, - id AS ticket, summary, component, version, t.type AS type, - (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS owner, + id AS ticket, summary AS summary, component AS componente, version AS versión, t.type AS tipo, + (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS responsable, time AS created, - changetime AS _changetime, description AS _description, - reporter AS _reporter + changetime AS _ultimo_cambio, description AS _description, + reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE status IN ('new', 'assigned', 'reopened') ORDER BY (version IS NULL),version, p.value, t.type, time """ % owner), #---------------------------------------------------------------------------- -('Active Tickets by Milestone', +('Tickets Activos por Hito', """ -This report shows how to color results by priority, -while grouping results by milestone. +Este reporte muestra como colorear los resultados por prioridad, +y al mismo tiempo, agrupar los resultados por hito. -Last modification time, description and reporter are included as hidden fields -for useful RSS export. +Fecha de la última modificación, descripción y quién-lo-reportó se incluyen como campos ocultos +para su útil exportación hacia RSS. """, """ SELECT p.value AS __color__, %s AS __group__, - id AS ticket, summary, component, version, t.type AS type, - (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS owner, + id AS ticket, summary AS summary, component AS componente, version AS versión, t.type AS tipo, + (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS responsable, time AS created, - changetime AS _changetime, description AS _description, - reporter AS _reporter + changetime AS _ultimo_cambio, description AS _description, + reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE status IN ('new', 'assigned', 'reopened') ORDER BY (milestone IS NULL),milestone, p.value, t.type, time -""" % (db.concat('milestone', "' Release'"), owner)), +""" % (db.concat("'Lanzamiento '", 'milestone'), owner)), #---------------------------------------------------------------------------- -('Assigned, Active Tickets by Owner', +('Tickets Asignados y Activos por Responsable', """ -List assigned tickets, group by ticket owner, sorted by priority. +Lista los tickets asignados, agrupados por responsable del ticket, ordenados por prioridad. """, """ SELECT p.value AS __color__, owner AS __group__, - id AS ticket, summary, component, milestone, t.type AS type, time AS created, - changetime AS _changetime, description AS _description, - reporter AS _reporter + id AS ticket, summary AS summary, component AS componente, milestone AS hito, t.type AS tipo, time AS created, + changetime AS _ultimo_cambio, description AS _description, + reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE status = 'assigned' ORDER BY owner, p.value, t.type, time """), #---------------------------------------------------------------------------- -('Assigned, Active Tickets by Owner (Full Description)', +('Tickets Asignados y Activos por Responsable (Descripción completa)', """ -List tickets assigned, group by ticket owner. -This report demonstrates the use of full-row display. +Lista los tickets asignados, agrupados por responsable del ticket. +Este reporte demuestra el uso de vista-de-fila-completa. """, """ SELECT p.value AS __color__, owner AS __group__, - id AS ticket, summary, component, milestone, t.type AS type, time AS created, - description AS _description_, - changetime AS _changetime, reporter AS _reporter + id AS ticket, summary AS summary, component AS componente, milestone AS hito, t.type AS tipo, time AS created, + description AS _description_, + changetime AS _ultimo_cambio, reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE status = 'assigned' ORDER BY owner, p.value, t.type, time """), #---------------------------------------------------------------------------- -('All Tickets By Milestone (Including closed)', +('Todos los Tickets por Hito (Incluyendo los cerrados)', """ -A more complex example to show how to make advanced reports. +Un ejemplo más complejo para mostrar el cómo hacer reportes avanzados. """, """ SELECT p.value AS __color__, @@ -275,51 +275,51 @@ ELSE (CASE owner WHEN $USER THEN 'font-weight: bold' END) END) AS __style__, - id AS ticket, summary, component, status, - resolution,version, t.type AS type, priority, owner, + id AS ticket, summary AS summary, component AS componente, status AS estado, + resolution AS resolución, version AS versión, t.type AS tipo, priority AS prioridad, owner AS responsable, changetime AS modified, - time AS _time,reporter AS _reporter + time AS _fecha, reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'), (CASE status WHEN 'closed' THEN modified ELSE (-1)*p.value END) DESC """), #---------------------------------------------------------------------------- -('My Tickets', +('Mis Tickets', """ -This report demonstrates the use of the automatically set -USER dynamic variable, replaced with the username of the -logged in user when executed. +Este reporte demuestra el uso de la variable dinámica y automáticamente fijada +USER, la cuál es reemplazada con el nombre del usuario que ha iniciado sesión +a la hora de ser ejecutado. """, """ SELECT p.value AS __color__, - (CASE status WHEN 'assigned' THEN 'Assigned' ELSE 'Owned' END) AS __group__, - id AS ticket, summary, component, version, milestone, - t.type AS type, priority, time AS created, - changetime AS _changetime, description AS _description, - reporter AS _reporter + (CASE status WHEN 'assigned' THEN 'Asignado' ELSE 'Responsable' END) AS __group__, + id AS ticket, summary AS summary, component AS componente, version AS versión, milestone AS hito, + t.type AS tipo, priority AS prioridad, time AS created, + changetime AS _ultimo_cambio, description AS _descripción, + reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE t.status IN ('new', 'assigned', 'reopened') AND owner = $USER ORDER BY (status = 'assigned') DESC, p.value, milestone, t.type, time """), #---------------------------------------------------------------------------- -('Active Tickets, Mine first', +('Tickets Activos, primero los Míos', """ - * List all active tickets by priority. - * Show all tickets owned by the logged in user in a group first. + * Lista todos los tickets activos por prioridad. + * Muestra primero, en un grupo, todos los tickets de los cuales es responsable el usuario que ha iniciado sesión. """, """ SELECT p.value AS __color__, (CASE owner - WHEN $USER THEN 'My Tickets' - ELSE 'Active Tickets' + WHEN $USER THEN 'Mis Tickets' + ELSE 'Tickets Activos' END) AS __group__, - id AS ticket, summary, component, version, milestone, t.type AS type, - (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS owner, + id AS ticket, summary AS summary, component AS componente, version AS versión, milestone AS hito, t.type AS tipo, + (CASE status WHEN 'assigned' THEN %s ELSE owner END) AS responsable, time AS created, - changetime AS _changetime, description AS _description, - reporter AS _reporter + changetime AS _ultimo_cambio, description AS _description, + reporter AS _reportado_por FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' WHERE status IN ('new', 'assigned', 'reopened') @@ -335,14 +335,14 @@ def get_data(db): return (('component', ('name', 'owner'), - (('component1', 'somebody'), - ('component2', 'somebody'))), + (('componente1', 'somebody'), + ('componente2', 'somebody'))), ('milestone', ('name', 'due', 'completed'), - (('milestone1', 0, 0), - ('milestone2', 0, 0), - ('milestone3', 0, 0), - ('milestone4', 0, 0))), + (('hito1', 0, 0), + ('hito2', 0, 0), + ('hito3', 0, 0), + ('hito4', 0, 0))), ('version', ('name', 'time'), (('1.0', 0), @@ -358,14 +358,14 @@ ('resolution', 'wontfix', 3), ('resolution', 'duplicate', 4), ('resolution', 'worksforme', 5), - ('priority', 'blocker', 1), - ('priority', 'critical', 2), - ('priority', 'major', 3), - ('priority', 'minor', 4), + ('priority', 'bloqueante', 1), + ('priority', 'critica', 2), + ('priority', 'mayor', 3), + ('priority', 'menor', 4), ('priority', 'trivial', 5), - ('ticket_type', 'defect', 1), - ('ticket_type', 'enhancement', 2), - ('ticket_type', 'task', 3))), + ('ticket_type', 'defecto', 1), + ('ticket_type', 'mejora', 2), + ('ticket_type', 'tarea', 3))), ('permission', ('username', 'action'), (('anonymous', 'LOG_VIEW'), Index: trac/mimeview/rst.py =================================================================== --- trac/mimeview/rst.py (revision 5935) +++ trac/mimeview/rst.py (working copy) @@ -52,9 +52,9 @@ from docutils.parsers import rst from docutils import __version__ except ImportError: - raise TracError, 'Docutils not found' + raise TracError, unicode('No se encontró Docutils', 'utf-8') if StrictVersion(__version__) < StrictVersion('0.3.9'): - raise TracError, 'Docutils version >= %s required, %s found' \ + raise TracError, unicode('Se requiere Docutils versión >= %s, se encontró %s', 'utf-8') \ % ('0.3.9', __version__) def trac_get_reference(rawtext, target, text): @@ -113,7 +113,7 @@ # didn't find a match (invalid TracLink), # report a warning warning = state_machine.reporter.warning( - '%s is not a valid TracLink' % (arguments[0]), + unicode('%s no es un TracLink válido', 'utf-8') % (arguments[0]), nodes.literal_block(block_text, block_text), line=lineno) return [warning] @@ -130,7 +130,7 @@ if reference: return [reference], [] warning = nodes.warning(None, nodes.literal_block(text, - 'WARNING: %s is not a valid TracLink' % rawtext)) + unicode('ADVERTENCIA: %s no es un TracLink válido', 'utf-8') % rawtext)) return warning, [] # 1 required arg, 1 optional arg, spaces allowed in last arg Index: trac/mimeview/api.py =================================================================== --- trac/mimeview/api.py (revision 5935) +++ trac/mimeview/api.py (working copy) @@ -376,7 +376,7 @@ candidates = list(self.get_supported_conversions(mimetype)) candidates = [c for c in candidates if key in (c[0], c[4])] if not candidates: - raise TracError('No available MIME conversions from %s to %s' % + raise TracError(unicode('No están disponibles conversiones MIME de %s a %s', 'utf-8') % (mimetype, key)) # First successful conversion wins @@ -386,7 +386,7 @@ if not output: continue return (output[0], output[1], ext) - raise TracError('No available MIME conversions from %s to %s' % + raise TracError(unicode('No están disponibles conversiones MIME de %s a %s', 'utf-8') % (mimetype, key)) def get_annotation_types(self): Index: trac/mimeview/tests/php.py =================================================================== --- trac/mimeview/tests/php.py (revision 5935) +++ trac/mimeview/tests/php.py (working copy) @@ -66,7 +66,7 @@ s = StringIO(stuff) else: raise NotImplementedException( - "Pass either type=file or type=string") + unicode("Pase ya sea type=file ó type=string", 'utf-8')) result = list(r.render(None, None, s)) return result Index: trac/mimeview/silvercity.py =================================================================== --- trac/mimeview/silvercity.py (revision 5935) +++ trac/mimeview/silvercity.py (working copy) @@ -109,7 +109,7 @@ except IndexError: pass except (KeyError, AttributeError): - err = "No SilverCity lexer found for mime-type '%s'." % mimetype + err = unicode("No se encontró ningún analizador de léxico SilverCity para el tipo-mime '%s'.", 'utf-8') % mimetype raise Exception, err # SilverCity does not like unicode strings Index: trac/mimeview/patch.py =================================================================== --- trac/mimeview/patch.py (revision 5935) +++ trac/mimeview/patch.py (working copy) @@ -69,7 +69,7 @@ d = self._diff_to_hdf(content.splitlines(), Mimeview(self.env).tab_width) if not d: - raise TracError, 'Invalid unified diff content' + raise TracError, unicode('El contenido diff unificado es inválido', 'utf-8') hdf = HDFWrapper(loadpaths=[self.env.get_templates_dir(), self.config.get('trac', 'templates_dir')]) hdf['diff.files'] = d Index: trac/mimeview/enscript.py =================================================================== --- trac/mimeview/enscript.py (revision 5935) +++ trac/mimeview/enscript.py (working copy) @@ -137,7 +137,7 @@ np = NaivePopen(cmdline, content.encode('utf-8'), capturestderr=1) if np.errorlevel or np.err: - err = 'Running (%s) failed: %s, %s.' % (cmdline, np.errorlevel, + err = unicode('La ejecución de (%s) falló: %s, %s.', 'utf-8') % (cmdline, np.errorlevel, np.err) raise Exception, err odata = np.out Index: trac/mimeview/php.py =================================================================== --- trac/mimeview/php.py (revision 5935) +++ trac/mimeview/php.py (working copy) @@ -83,7 +83,7 @@ content = content.encode('utf-8') np = NaivePopen(cmdline, content, capturestderr=1) if (os.name != 'nt' and np.errorlevel) or np.err: - msg = 'Running (%s) failed: %s, %s.' % (cmdline, + msg = unicode('La ejecución de (%s) falló: %s, %s.', 'utf-8') % (cmdline, np.errorlevel, np.err) raise Exception(msg) @@ -91,9 +91,9 @@ odata = ''.join(np.out.splitlines()[1:-1]) if odata.startswith('X-Powered-By:') or \ odata.startswith('Content-type:'): - raise TracError('You appear to be using the PHP CGI ' - 'binary. Trac requires the CLI version ' - 'for syntax highlighting.') + raise TracError(unicode('Parece que se está utilizando el binario PHP CGI ' + 'Trac requiere la versión CLI ' + 'para resaltar (colorear) la sintaxis.', 'utf-8')) epilogues = ["", ""] for e in epilogues: Index: trac/ticket/api.py =================================================================== --- trac/ticket/api.py (revision 5935) +++ trac/ticket/api.py (working copy) @@ -244,7 +244,7 @@ cnum = target if href: return html.A(label, href="%s#comment:%s" % (href, cnum), - title="Comment %s for %s:%s" % (cnum, type, id)) + title="Comentario %s para %s:%s" % (cnum, type, id)) else: return label Index: trac/ticket/web_ui.py =================================================================== --- trac/ticket/web_ui.py (revision 5935) +++ trac/ticket/web_ui.py (working copy) @@ -57,10 +57,10 @@ value = ticket[name] if value: if value not in field['options']: - raise InvalidTicket('"%s" is not a valid value for ' - 'the %s field.' % (value, name)) + raise InvalidTicket(unicode('"%s" no es un valor válido para ' + 'el campo %s.', 'utf-8') % (value, name)) elif not field.get('optional', False): - raise InvalidTicket('field %s must be set' % name) + raise InvalidTicket('El campo %s debe ser fijado' % name) try: # comment index must be a number @@ -70,16 +70,16 @@ if replyto != 'description': int(replyto or 0) except ValueError: - raise InvalidTicket('Invalid comment threading identifier') + raise InvalidTicket(unicode('Identificador de serie de comentarios inválido', 'utf-8')) # Custom validation rules for manipulator in self.ticket_manipulators: for field, message in manipulator.validate_ticket(req, ticket): if field: - raise InvalidTicket("The ticket %s field is invalid: %s" % + raise InvalidTicket(unicode("EL campo %s del ticket es inválido: %s", 'utf-8') % (field, message)) else: - raise InvalidTicket("Invalid ticket: %s" % message) + raise InvalidTicket(unicode("Ticket inválido: %s", 'utf-8') % message) class NewticketModule(TicketModuleBase): @@ -118,7 +118,7 @@ if not req.perm.has_permission('TICKET_CREATE'): return yield ('mainnav', 'newticket', - html.A('New Ticket', href=req.href.newticket(), accesskey=7)) + html.A('Nuevo Ticket', href=req.href.newticket(), accesskey=7)) # IRequestHandler methods @@ -145,7 +145,7 @@ description = wiki_to_html(ticket['description'], self.env, req, db) req.hdf['newticket.description_preview'] = description - req.hdf['title'] = 'New Ticket' + req.hdf['title'] = 'Nuevo Ticket' req.hdf['newticket'] = ticket.values field_names = [field['name'] for field in ticket.fields @@ -167,10 +167,11 @@ 'resolution'): field['skip'] = True elif name == 'owner': - field['label'] = 'Assign to' + field['label'] = 'Asignar a' if not req.perm.has_permission('TICKET_MODIFY'): field['skip'] = True elif name == 'milestone': + field['label'] = 'Hito' # Don't make completed milestones available for selection options = field['options'][:] for option in field['options']: @@ -179,6 +180,30 @@ options.remove(option) field['options'] = options req.hdf['newticket.fields.' + name] = field + + #el siguiente bloque, no funciona como se esperaba + if name == 'summary': + field['label'] = 'Sumario' + if name == 'reporter': + field['label'] = 'Informante' + if name == 'description': + field['label'] = unicode('Descripción', 'utf-8') + if name == 'type': + field['label'] = 'Tipo' + if name == 'status': + field['label'] = 'Estado' + if name == 'resolution': + field['label'] = unicode('Resolución', 'utf-8') + if name == 'priority': + field['label'] = 'Prioridad' + if name == 'severity': + field['label'] = 'Severidad' + if name == 'component': + field['label'] = 'Componente' + if name == 'version': + field['label'] = unicode('Versión', 'utf-8') + if name == 'keywords': + field['label'] = 'Palabras clave' if req.perm.has_permission('TICKET_APPEND'): req.hdf['newticket.can_attach'] = True @@ -191,7 +216,7 @@ def _do_create(self, req, db): if not req.args.get('summary'): - raise TracError('Tickets must contain a summary.') + raise TracError('Los tickets deben contener un sumario.') ticket = Ticket(self.env, db=db) ticket.populate(req.args) @@ -243,11 +268,11 @@ # IContentConverter methods def get_supported_conversions(self): - yield ('csv', 'Comma-delimited Text', 'csv', + yield ('csv', 'Texto separado por comas', 'csv', 'trac.ticket.Ticket', 'text/csv', 8) - yield ('tab', 'Tab-delimited Text', 'tsv', + yield ('tab', 'Texto separado por tabulaciones', 'tsv', 'trac.ticket.Ticket', 'text/tab-separated-values', 8) - yield ('rss', 'RSS Feed', 'xml', + yield ('rss', 'Fuente en formato RSS', 'xml', 'trac.ticket.Ticket', 'application/rss+xml', 8) def convert_content(self, req, mimetype, ticket, key): @@ -350,17 +375,17 @@ def get_timeline_filters(self, req): if req.perm.has_permission('TICKET_VIEW'): - yield ('ticket', 'Ticket changes') + yield ('ticket', 'Cambios en tickets') if self.timeline_details: - yield ('ticket_details', 'Ticket details', False) + yield ('ticket_details', 'Detalles en Tickets', False) def get_timeline_events(self, req, start, stop, filters): format = req.args.get('format') - status_map = {'new': ('newticket', 'created'), - 'reopened': ('newticket', 'reopened'), - 'closed': ('closedticket', 'closed'), - 'edit': ('editedticket', 'updated')} + status_map = {'new': ('newticket', 'creado'), + 'reopened': ('newticket', 'reabierto'), + 'closed': ('closedticket', 'cerrado'), + 'edit': ('editedticket', 'modificado')} href = format == 'rss' and req.abs_href or req.href @@ -371,7 +396,7 @@ info = '' if len(fields) > 0: info = ', '.join(['%s' % f for f in \ - fields.keys()]) + ' changed
' + fields.keys()]) + ' modificado
' else: return None elif 'ticket' in filters: @@ -389,7 +414,7 @@ (id, type_ and type_.lower() or '', verb, summary) else: typeinfo = type_ and '(%s)' % type_ or '' - title = Markup('Ticket #%s %s %s by %s', + title = Markup('Ticket #%s %s %s por %s', summary, id, typeinfo, verb, author) ticket_href = href.ticket(id) if cid: @@ -510,7 +535,7 @@ if req.perm.has_permission('TICKET_CHGPROP'): # TICKET_CHGPROP gives permission to edit the ticket if not req.args.get('summary'): - raise TracError('Tickets must contain summary.') + raise TracError('Los tickets deben contener un sumario.') if req.args.has_key('description') or req.args.has_key('reporter'): req.perm.assert_permission('TICKET_ADMIN') @@ -521,15 +546,15 @@ # Mid air collision? if int(req.args.get('ts')) != ticket.time_changed: - raise TracError("Sorry, can not save your changes. " - "This ticket has been modified by someone else " - "since you started", 'Mid Air Collision') + raise TracError(unicode("Lo siento, no se pueden guardar tus cambios. " + "Este ticket ha sido modificado por alguien más " + "desde que tu comenzaste", 'utf-8'), unicode('Colisión en pleno aire', 'utf-8')) # Do any action on the ticket? action = req.args.get('action') actions = TicketSystem(self.env).get_available_actions(ticket, req.perm) if action not in actions: - raise TracError('Invalid action') + raise TracError(unicode('Acción inválida', 'utf-8')) # TODO: this should not be hard-coded like this if action == 'accept': @@ -618,7 +643,7 @@ def quote_original(author, original, link): if not 'comment' in req.args: # i.e. the comment was not yet edited req.hdf['ticket.comment'] = '\n'.join( - ['Replying to [%s %s]:' % (link, author)] + + ['En respuesta a [%s %s]:' % (link, author)] + ['> %s' % line for line in original.splitlines()] + ['']) if replyto == 'description': Index: trac/ticket/report.py =================================================================== --- trac/ticket/report.py (revision 5935) +++ trac/ticket/report.py (working copy) @@ -46,7 +46,7 @@ if not req.perm.has_permission('REPORT_VIEW'): return yield ('mainnav', 'tickets', - html.A('View Tickets', href=req.href.report())) + html.A('Ver Tickets', href=req.href.report())) # IPermissionRequestor methods @@ -93,7 +93,7 @@ return resp if id != -1 or action == 'new': - add_link(req, 'up', req.href.report(), 'Available Reports') + add_link(req, 'up', req.href.report(), 'Reportes disponibles') # Kludge: Reset session vars created by query module so that the # query navigation links on the ticket page don't confuse the user @@ -163,9 +163,9 @@ cursor.execute("SELECT title FROM report WHERE id = %s", (id,)) row = cursor.fetchone() if not row: - raise TracError('Report %s does not exist.' % id, - 'Invalid Report Number') - req.hdf['title'] = 'Delete Report {%s} %s' % (id, row[0]) + raise TracError('El Reporte %s no existe.' % id, + unicode('Número de Reporte Inválido', 'utf-8')) + req.hdf['title'] = 'Eliminar Reporte {%s} %s' % (id, row[0]) req.hdf['report'] = { 'id': id, 'mode': 'delete', @@ -184,8 +184,8 @@ "WHERE id=%s", (id,)) row = cursor.fetchone() if not row: - raise TracError('Report %s does not exist.' % id, - 'Invalid Report Number') + raise TracError('El Reporte %s no existe.' % id, + unicode('Número de Reporte Inválido', 'utf-8')) title = row[0] or '' description = row[1] or '' query = row[2] or '' @@ -194,11 +194,11 @@ title += ' (copy)' if copy or id == -1: - req.hdf['title'] = 'Create New Report' + req.hdf['title'] = 'Crear Nuevo Reporte' req.hdf['report.href'] = req.href.report() req.hdf['report.action'] = 'new' else: - req.hdf['title'] = 'Edit Report {%d} %s' % (id, title) + req.hdf['title'] = 'Editar Reporte {%d} %s' % (id, title) req.hdf['report.href'] = req.href.report(id) req.hdf['report.action'] = 'edit' @@ -223,7 +223,7 @@ try: args = self.get_var_args(req) except ValueError,e: - raise TracError, 'Report failed: %s' % e + raise TracError, unicode('Falló el Reporte: %s', 'utf-8') % e title, description, sql = self.get_info(db, id, args) @@ -245,7 +245,7 @@ try: cols, rows = self.execute_report(req, db, id, sql, args) except Exception, e: - req.hdf['report.message'] = 'Report execution failed: %s' % e + req.hdf['report.message'] = unicode('Falló la ejecución del Reporte: %s', 'utf-8') % e return 'report.cs', None # Convert the header info to HDF-format @@ -381,20 +381,20 @@ href = '' if params: href = '&' + unicode_urlencode(params) - add_link(req, 'alternate', '?format=rss' + href, 'RSS Feed', + add_link(req, 'alternate', '?format=rss' + href, 'Fuente en formato RSS', 'application/rss+xml', 'rss') add_link(req, 'alternate', '?format=csv' + href, - 'Comma-delimited Text', 'text/plain') + 'Texto separado por comas', 'text/plain') add_link(req, 'alternate', '?format=tab' + href, - 'Tab-delimited Text', 'text/plain') + 'Texto separado por tabulaciones', 'text/plain') if req.perm.has_permission('REPORT_SQL_VIEW'): - add_link(req, 'alternate', '?format=sql', 'SQL Query', + add_link(req, 'alternate', '?format=sql', 'Consulta SQL', 'text/plain') def execute_report(self, req, db, id, sql, args): sql, args = self.sql_sub_vars(req, sql, args, db) if not sql: - raise TracError('Report %s has no SQL query.' % id) + raise TracError('El Reporte %s no tiene una consulta SQL.' % id) if sql.find('__group__') == -1: req.hdf['report.sorting.enabled'] = 1 @@ -415,17 +415,17 @@ if id == -1: # If no particular report was requested, display # a list of available reports instead - title = 'Available Reports' + title = 'Reportes Disponibles' sql = 'SELECT id AS report, title FROM report ORDER BY report' - description = 'This is a list of reports available.' + description = 'Esta es una lista de los reportes disponibles.' else: cursor = db.cursor() cursor.execute("SELECT title,query,description from report " "WHERE id=%s", (id,)) row = cursor.fetchone() if not row: - raise TracError('Report %d does not exist.' % id, - 'Invalid Report Number') + raise TracError('El Reporte %d no existe.' % id, + unicode('Número de Reporte Inválido', 'utf-8')) title = row[0] or '' sql = row[1] description = row[2] or '' @@ -453,7 +453,7 @@ try: arg = args[aname] except KeyError: - raise TracError("Dynamic variable '$%s' not defined." \ + raise TracError(unicode("La variable Dinámica '$%s' no esta definida.", 'utf-8') \ % aname) req.hdf['report.var.' + aname] = arg values.append(arg) Index: trac/ticket/model.py =================================================================== --- trac/ticket/model.py (revision 5935) +++ trac/ticket/model.py (working copy) @@ -83,8 +83,8 @@ % ','.join(std_fields), (tkt_id,)) row = cursor.fetchone() if not row: - raise TracError('Ticket %d does not exist.' % tkt_id, - 'Invalid Ticket Number') + raise TracError('El Ticket %d no existe.' % tkt_id, + unicode('Número de Ticket Inválido', 'utf-8')) self.id = tkt_id for i in range(len(std_fields)): @@ -131,7 +131,7 @@ def insert(self, when=0, db=None): """Add ticket to database""" - assert not self.exists, 'Cannot insert an existing ticket' + assert not self.exists, 'No se puede insertar un ticket ya existente' db, handle_ta = self._get_db_for_write(db) # Add a timestamp @@ -187,7 +187,7 @@ the database. Returns False if there were no changes to save, True otherwise. """ - assert self.exists, 'Cannot update a new ticket' + assert self.exists, 'No se puede actualizar un nuevo ticket' if not self._old and not comment: return False # Not modified @@ -331,7 +331,7 @@ (self.type, name)) row = cursor.fetchone() if not row: - raise TracError, '%s %s does not exist.' % (self.type, name) + raise TracError, '%s %s no existe.' % (self.type, name) self.value = self._old_value = row[0] self.name = self._old_name = name else: @@ -341,7 +341,7 @@ exists = property(fget=lambda self: self._old_value is not None) def delete(self, db=None): - assert self.exists, 'Cannot deleting non-existent %s' % self.type + assert self.exists, 'No se puede eliminar el inexistente %s' % self.type if not db: db = self.env.get_db_cnx() handle_ta = True @@ -359,8 +359,8 @@ self.name = self._old_name = None def insert(self, db=None): - assert not self.exists, 'Cannot insert existing %s' % self.type - assert self.name, 'Cannot create %s with no name' % self.type + assert not self.exists, 'No se puede insertar el existente %s' % self.type + assert self.name, 'No se puede crear %s sin nombre' % self.type self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -384,8 +384,8 @@ self._old_value = self.value def update(self, db=None): - assert self.exists, 'Cannot update non-existent %s' % self.type - assert self.name, 'Cannot update %s with no name' % self.type + assert self.exists, 'No se puede actualizar el inexistente %s' % self.type + assert self.name, 'No se puede actualizar %s sin nombre' % self.type self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -457,7 +457,7 @@ "WHERE name=%s", (name,)) row = cursor.fetchone() if not row: - raise TracError, 'Component %s does not exist.' % name + raise TracError, 'El componente %s no existe.' % name self.name = self._old_name = name self.owner = row[0] or None self.description = row[1] or '' @@ -469,7 +469,7 @@ exists = property(fget=lambda self: self._old_name is not None) def delete(self, db=None): - assert self.exists, 'Cannot deleting non-existent component' + assert self.exists, 'No se puede eliminar un componente inexistente' if not db: db = self.env.get_db_cnx() handle_ta = True @@ -486,8 +486,8 @@ db.commit() def insert(self, db=None): - assert not self.exists, 'Cannot insert existing component' - assert self.name, 'Cannot create component with no name' + assert not self.exists, 'No se puede insertar un componente ya existente' + assert self.name, 'No se puede crear un componente sin nombre' self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -505,8 +505,8 @@ db.commit() def update(self, db=None): - assert self.exists, 'Cannot update non-existent component' - assert self.name, 'Cannot update component with no name' + assert self.exists, 'No se puede actualizar un componente inexistente' + assert self.name, 'No se puede actualizar un componente sin nombre' self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -564,8 +564,8 @@ "FROM milestone WHERE name=%s", (name,)) row = cursor.fetchone() if not row: - raise TracError('Milestone %s does not exist.' % name, - 'Invalid Milestone Name') + raise TracError('El Hito %s no existe.' % name, + unicode('Nombre de Hito inválido', 'utf-8')) self.name = row[0] self.due = row[1] and int(row[1]) or 0 self.completed = row[2] and int(row[2]) or 0 @@ -594,14 +594,14 @@ for tkt_id in tkt_ids: ticket = Ticket(self.env, tkt_id, db) ticket['milestone'] = retarget_to - ticket.save_changes(author, 'Milestone %s deleted' % self.name, + ticket.save_changes(author, 'El Hito %s ha sido eliminado' % self.name, now, db=db) if handle_ta: db.commit() def insert(self, db=None): - assert self.name, 'Cannot create milestone with no name' + assert self.name, 'No se puede crear un hito sin nombre' self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -619,7 +619,7 @@ db.commit() def update(self, db=None): - assert self.name, 'Cannot update milestone with no name' + assert self.name, 'No se puede actualizar un hito sin nombre' self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -678,7 +678,7 @@ "WHERE name=%s", (name,)) row = cursor.fetchone() if not row: - raise TracError, 'Version %s does not exist.' % name + raise TracError, unicode('La versión %s no existe.', 'utf-8') % name self.name = self._old_name = name self.time = row[0] and int(row[0]) or None self.description = row[1] or '' @@ -690,7 +690,7 @@ exists = property(fget=lambda self: self._old_name is not None) def delete(self, db=None): - assert self.exists, 'Cannot deleting non-existent version' + assert self.exists, unicode('No puede eliminarse una versión inexistente', 'utf-8') if not db: db = self.env.get_db_cnx() handle_ta = True @@ -707,8 +707,8 @@ db.commit() def insert(self, db=None): - assert not self.exists, 'Cannot insert existing version' - assert self.name, 'Cannot create version with no name' + assert not self.exists, unicode('No puede insertarse una versión ya existente', 'utf-8') + assert self.name, unicode('No puede crearse una versión sin nombre', 'utf-8') self.name = self.name.strip() if not db: db = self.env.get_db_cnx() @@ -726,8 +726,8 @@ db.commit() def update(self, db=None): - assert self.exists, 'Cannot update non-existent version' - assert self.name, 'Cannot update version with no name' + assert self.exists, unicode('No puede actualizarse una versión inexistente', 'utf-8') + assert self.name, unicode('No puede actualizarse una versión sin nombre', 'utf-8') self.name = self.name.strip() if not db: db = self.env.get_db_cnx() Index: trac/ticket/roadmap.py =================================================================== --- trac/ticket/roadmap.py (revision 5935) +++ trac/ticket/roadmap.py (working copy) @@ -129,7 +129,7 @@ if not req.perm.has_permission('ROADMAP_VIEW'): return yield ('mainnav', 'roadmap', - html.a('Roadmap', href=req.href.roadmap(), accesskey=3)) + html.a('Hitos', href=req.href.roadmap(), accesskey=3)) # IPermissionRequestor methods @@ -143,7 +143,7 @@ def process_request(self, req): req.perm.assert_permission('ROADMAP_VIEW') - req.hdf['title'] = 'Roadmap' + req.hdf['title'] = 'Hitos' showall = req.args.get('show') == 'all' req.hdf['roadmap.showall'] = showall @@ -236,7 +236,7 @@ % __version__) write_prop('METHOD', 'PUBLISH') write_prop('X-WR-CALNAME', - self.config.get('project', 'name') + ' - Roadmap') + self.config.get('project', 'name') + ' - Hitos') for milestone in milestones: uid = '<%s/milestone/%s@%s>' % (req.base_path, milestone['name'], host) @@ -289,7 +289,7 @@ # INavigationContributor methods def get_active_navigation_item(self, req): - return 'roadmap' + return 'hitos' def get_navigation_items(self, req): return [] @@ -306,7 +306,7 @@ def get_timeline_filters(self, req): if req.perm.has_permission('MILESTONE_VIEW'): - yield ('milestone', 'Milestones') + yield ('milestone', 'Hitos') def get_timeline_events(self, req, start, stop, filters): if 'milestone' in filters: @@ -317,7 +317,7 @@ "WHERE completed>=%s AND completed<=%s", (start, stop,)) for completed, name, description in cursor: - title = Markup('Milestone %s completed', name) + title = Markup('El hito %s ha sido completado', name) if format == 'rss': href = req.abs_href.milestone(name) message = wiki_to_html(description, self.env, req, db, @@ -343,7 +343,7 @@ req.perm.assert_permission('MILESTONE_VIEW') - add_link(req, 'up', req.href.roadmap(), 'Roadmap') + add_link(req, 'up', req.href.roadmap(), 'Hitos') db = self.env.get_db_cnx() milestone = Milestone(self.env, milestone_id, db) @@ -391,23 +391,23 @@ req.perm.assert_permission('MILESTONE_CREATE') if not req.args.has_key('name'): - raise TracError('You must provide a name for the milestone.', - 'Required Field Missing') + raise TracError('Debes proveer un nombre para el hito.', + 'Falta un Campo Requerido') due = req.args.get('duedate', '') try: milestone.due = due and parse_date(due) or 0 except ValueError, e: - raise TracError(to_unicode(e), 'Invalid Date Format') + raise TracError(to_unicode(e), unicode('Formato de Fecha Inválido', 'utf-8')) if req.args.has_key('completed'): completed = req.args.get('completeddate', '') try: milestone.completed = completed and parse_date(completed) or 0 except ValueError, e: - raise TracError(to_unicode(e), 'Invalid Date Format') + raise TracError(to_unicode(e), unicode('Formato de Fecha Inválido', 'utf-8')) if milestone.completed > time(): - raise TracError('Completion date may not be in the future', - 'Invalid Completion Date') + raise TracError(unicode('La fecha de conclusión no puede estar en el futuro', 'utf-8'), + unicode('Fecha de Conclusión Inválida', 'utf-8')) retarget_to = req.args.get('target') if req.args.has_key('retarget'): cursor = db.cursor() @@ -435,7 +435,7 @@ def _render_confirm(self, req, db, milestone): req.perm.assert_permission('MILESTONE_DELETE') - req.hdf['title'] = 'Milestone %s' % milestone.name + req.hdf['title'] = 'Hito %s' % milestone.name req.hdf['milestone'] = milestone_to_hdf(self.env, db, req, milestone) req.hdf['milestone.mode'] = 'delete' @@ -447,14 +447,14 @@ def _render_editor(self, req, db, milestone): if milestone.exists: req.perm.assert_permission('MILESTONE_MODIFY') - req.hdf['title'] = 'Milestone %s' % milestone.name + req.hdf['title'] = 'Hito %s' % milestone.name req.hdf['milestone.mode'] = 'edit' req.hdf['milestones'] = [m.name for m in Milestone.select(self.env) if m.name != milestone.name] else: req.perm.assert_permission('MILESTONE_CREATE') - req.hdf['title'] = 'New Milestone' + req.hdf['title'] = 'Nuevo Hito' req.hdf['milestone.mode'] = 'new' from trac.util.datefmt import get_date_format_hint, \ @@ -465,7 +465,7 @@ req.hdf['milestone.datetime_now'] = format_datetime() def _render_view(self, req, db, milestone): - req.hdf['title'] = 'Milestone %s' % milestone.name + req.hdf['title'] = 'Hito %s' % milestone.name req.hdf['milestone.mode'] = 'view' req.hdf['milestone'] = milestone_to_hdf(self.env, db, req, milestone) Index: trac/ticket/query.py =================================================================== --- trac/ticket/query.py (revision 5935) +++ trac/ticket/query.py (working copy) @@ -67,11 +67,11 @@ for filter in filters: filter = filter.split('=') if len(filter) != 2: - raise QuerySyntaxError, 'Query filter requires field and ' \ - 'constraints separated by a "="' + raise QuerySyntaxError, unicode('El filtro de consultas requiere que los campos y ' \ + 'sus criterios de búsqueda están separadas por un "="', 'utf-8') field,values = filter if not field: - raise QuerySyntaxError, 'Query filter requires field name' + raise QuerySyntaxError, 'El filtro de consultas requiere un nombre de campo' values = values.split('|') mode, neg = '', '' if field[-1] in ('~', '^', '$'): @@ -352,11 +352,11 @@ # IContentConverter methods def get_supported_conversions(self): - yield ('rss', 'RSS Feed', 'xml', + yield ('rss', 'Fuente en formato RSS', 'xml', 'trac.ticket.Query', 'application/rss+xml', 8) - yield ('csv', 'Comma-delimited Text', 'csv', + yield ('csv', 'Texto separado por comas', 'csv', 'trac.ticket.Query', 'text/csv', 8) - yield ('tab', 'Tab-delimited Text', 'tsv', + yield ('tab', 'Texto separado por tabulaciones', 'tsv', 'trac.ticket.Query', 'text/tab-separated-values', 8) def convert_content(self, req, mimetype, query, key): @@ -377,7 +377,7 @@ if req.perm.has_permission('TICKET_VIEW') and \ not self.env.is_component_enabled(ReportModule): yield ('mainnav', 'tickets', - html.A('View Tickets', href=req.href.query())) + html.A('Ver Tickets', href=req.href.query())) # IRequestHandler methods @@ -485,21 +485,21 @@ def _get_constraint_modes(self): modes = {} modes['text'] = [ - {'name': "contains", 'value': "~"}, - {'name': "doesn't contain", 'value': "!~"}, - {'name': "begins with", 'value': "^"}, - {'name': "ends with", 'value': "$"}, - {'name': "is", 'value': ""}, - {'name': "is not", 'value': "!"} + {'name': "contenga", 'value': "~"}, + {'name': "no contenga", 'value': "!~"}, + {'name': "empieze con", 'value': "^"}, + {'name': "termine con", 'value': "$"}, + {'name': "es", 'value': ""}, + {'name': "no es", 'value': "!"} ] modes['select'] = [ - {'name': "is", 'value': ""}, - {'name': "is not", 'value': "!"} + {'name': "es", 'value': ""}, + {'name': "no es", 'value': "!"} ] return modes def display_html(self, req, query): - req.hdf['title'] = 'Custom Query' + req.hdf['title'] = 'Consulta Personalizada' add_stylesheet(req, 'common/css/report.css') add_script(req, 'common/js/query.js') @@ -717,7 +717,7 @@ return html.SPAN(alist[0], *[(', ', a) for a in alist[1:]]) elif count: cnt = len(tickets) - return html.SPAN(cnt, title='%d tickets for which %s' % + return html.SPAN(cnt, title='%d tickets para los cuales %s' % (cnt, query_string)) else: return html.DL([(html.DT(ticket_anchor(ticket)), Index: trac/db/sqlite_backend.py =================================================================== --- trac/db/sqlite_backend.py (revision 5935) +++ trac/db/sqlite_backend.py (working copy) @@ -116,7 +116,7 @@ if path != ':memory:': # make the directory to hold the database if os.path.exists(path): - raise TracError, 'Database already exists at %s' % path + raise TracError, 'Ya existe una base de datos en %s' % path os.makedirs(os.path.split(path)[0]) cnx = sqlite.connect(path, timeout=int(params.get('timeout', 10000))) cursor = cnx.cursor() @@ -141,15 +141,15 @@ self.cnx = None if path != ':memory:': if not os.access(path, os.F_OK): - raise TracError, 'Database "%s" not found.' % path + raise TracError, 'No se encuentra la base de datos "%s".' % path dbdir = os.path.dirname(path) if not os.access(path, os.R_OK + os.W_OK) or \ not os.access(dbdir, os.R_OK + os.W_OK): from getpass import getuser - raise TracError('The user %s requires read _and_ write ' \ - 'permission to the database file %s and the ' \ - 'directory it is located in.' \ + raise TracError(unicode('El usuario %s requiere permisos de lectura ' \ + '_y_ escritura para el archivo base de datos %s y el ' \ + 'directorio donde éste se encuentra.', 'utf-8') \ % (getuser(), path)) if have_pysqlite == 2: Index: trac/db/api.py =================================================================== --- trac/db/api.py (revision 5935) +++ trac/db/api.py (working copy) @@ -94,7 +94,7 @@ candidates[scheme] = (connector, priority) connector = candidates.get(scheme, [None])[0] if not connector: - raise TracError('Unsupported database type "%s"' % scheme) + raise TracError('Tipo de base de datos no soportado "%s"' % scheme) if scheme == 'sqlite': # Special case for SQLite to support a path relative to the @@ -116,8 +116,8 @@ host = None path = rest else: - raise TracError('Database connection string must start with ' - 'scheme:/') + raise TracError(unicode('La cadena de conexión a la base de datos debe comenzar con ' + 'esquema:/', 'utf-8')) else: if rest.startswith('/') and not rest.startswith('//'): host = None Index: trac/db/pool.py =================================================================== --- trac/db/pool.py (revision 5935) +++ trac/db/pool.py (working copy) @@ -104,8 +104,8 @@ else: if timeout: if (time.time() - start) >= timeout: - raise TimeoutError('Unable to get database ' - 'connection within %d seconds' + raise TimeoutError(unicode('No se pudo obtener una conexión a la ' + 'base de datos en el plazo de %d segundos', 'utf-8') % timeout) self._available.wait(timeout) else: # Warning: without timeout, Trac *might* hang Index: trac/db/mysql_backend.py =================================================================== --- trac/db/mysql_backend.py (revision 5935) +++ trac/db/mysql_backend.py (working copy) @@ -122,7 +122,7 @@ def _set_character_set(self, cnx, charset): vers = tuple([ int(n) for n in cnx.get_server_info().split('.')[:2] ]) if vers < (4, 1): - raise TracError, 'MySQL servers older than 4.1 are not supported!' + raise TracError, 'Los servidores MySQL anteriores a 4.1 no son soportados!' cnx.query('SET NAMES %s' % charset) cnx.store_result() cnx.charset = charset Index: trac/versioncontrol/api.py =================================================================== --- trac/versioncontrol/api.py (revision 5935) +++ trac/versioncontrol/api.py (working copy) @@ -88,9 +88,9 @@ continue heappush(candidates, (-prio, connector)) if not candidates: - raise TracError('Unsupported version control system "%s". ' - 'Check that the Python bindings for "%s" are ' - 'correctly installed.' % + raise TracError(unicode('Sistema de control de versiones no soportado "%s". ' + 'Verifique que las librerías Python para "%s" están ' + 'correctamente instaladas.', 'utf-8') % ((self.repository_type,)*2)) self._connector = heappop(candidates)[1] db = self.env.get_db_cnx() # prevent possible deadlock, see #4465 @@ -119,11 +119,11 @@ class NoSuchChangeset(TracError): def __init__(self, rev): - TracError.__init__(self, "No changeset %s in the repository" % rev) + TracError.__init__(self, "No existe el conjunto de cambios %s en el repositorio" % rev) class NoSuchNode(TracError): def __init__(self, path, rev, msg=None): - TracError.__init__(self, "%sNo node %s at revision %s" \ + TracError.__init__(self, unicode("%sNo existe el nodo %s en la revisión %s", 'utf-8') \ % (msg and '%s: ' % msg or '', path, rev)) class Repository(object): @@ -298,7 +298,7 @@ def __init__(self, path, rev, kind): assert kind in (Node.DIRECTORY, Node.FILE), \ - "Unknown node kind %s" % kind + "Tipo de nodo desconocido %s" % kind self.path = unicode(path) self.rev = rev self.kind = kind @@ -442,12 +442,12 @@ def assert_permission(self, path): if not self.has_permission(path): raise PermissionDenied, \ - 'Insufficient permissions to access %s' % path + 'Permisos insuficientes para acceder a %s' % path def assert_permission_for_changeset(self, rev): if not self.has_permission_for_changeset(rev): raise PermissionDenied, \ - 'Insufficient permissions to access changeset %s' % rev + 'Permisos insuficientes para acceder al conjunto de cambios %s' % rev def has_permission(self, path): return True Index: trac/versioncontrol/svn_fs.py =================================================================== --- trac/versioncontrol/svn_fs.py (revision 5935) +++ trac/versioncontrol/svn_fs.py (working copy) @@ -254,7 +254,7 @@ self.path = path # might be needed by __del__()/close() self.log = log if core.SVN_VER_MAJOR < 1: - raise TracError("Subversion >= 1.0 required: Found %d.%d.%d" % \ + raise TracError(unicode("Se requiere Subversion >= 1.0: Se encontró %d.%d.%d", 'utf-8') % \ (core.SVN_VER_MAJOR, core.SVN_VER_MINOR, core.SVN_VER_MICRO)) @@ -266,7 +266,7 @@ path = os.path.normpath(path).replace('\\', '/') self.path = repos.svn_repos_find_root_path(path, self.pool()) if self.path is None: - raise TracError("%s does not appear to be a Subversion repository." \ + raise TracError("%s no parece ser un repositorio Subversion." \ % path) self.repos = repos.svn_repos_open(self.path, self.pool()) @@ -475,14 +475,14 @@ if self.has_node(old_path, old_rev): old_node = self.get_node(old_path, old_rev) else: - raise NoSuchNode(old_path, old_rev, 'The Base for Diff is invalid') + raise NoSuchNode(old_path, old_rev, unicode('La base para el Diff es inválida', 'utf-8')) if self.has_node(new_path, new_rev): new_node = self.get_node(new_path, new_rev) else: - raise NoSuchNode(new_path, new_rev, 'The Target for Diff is invalid') + raise NoSuchNode(new_path, new_rev, unicode('El objetivo para el Diff es inválido', 'utf-8')) if new_node.kind != old_node.kind: - raise TracError('Diff mismatch: Base is a %s (%s in revision %s) ' - 'and Target is a %s (%s in revision %s).' \ + raise TracError(unicode('Incoincidencia Diff: La Base es %s (%s en la revisión %s) ' + 'y el Objetivo es %s (%s en la revisión %s).', 'utf-8') \ % (old_node.kind, old_path, old_rev, new_node.kind, new_path, new_rev)) subpool = Pool(self.pool) Index: trac/versioncontrol/web_ui/util.py =================================================================== --- trac/versioncontrol/web_ui/util.py (revision 5935) +++ trac/versioncontrol/web_ui/util.py (working copy) @@ -72,7 +72,7 @@ return changes def get_path_links(href, fullpath, rev): - links = [{'name': 'root', 'href': href.browser(rev=rev)}] + links = [{'name': unicode('raíz', 'utf-8'), 'href': href.browser(rev=rev)}] path = '' for part in [p for p in fullpath.split('/') if p]: path += part + '/' @@ -97,9 +97,9 @@ try: return repos.get_node(path, rev) except NoSuchNode, e: - raise TracError(Markup('%s

You can search ' - 'in the repository history to see if that path ' - 'existed but was later removed.

', e.message, + raise TracError(Markup(unicode('%s

Tu puedes buscar ' + 'en el historial del repositorio para ver si la ruta ' + 'existía pero fué posteriormente eliminada.

', 'utf-8'), e.message, req.href.log(path, rev=rev, mode='path_history'))) Index: trac/versioncontrol/web_ui/changeset.py =================================================================== --- trac/versioncontrol/web_ui/changeset.py (revision 5935) +++ trac/versioncontrol/web_ui/changeset.py (working copy) @@ -259,9 +259,9 @@ 'new': new, 'old_path': old_path, 'old': old}) - add_link(req, 'alternate', '?format=diff&'+diff_params, 'Unified Diff', + add_link(req, 'alternate', '?format=diff&'+diff_params, 'Diff Unificado', 'text/plain', 'diff') - add_link(req, 'alternate', '?format=zip&'+diff_params, 'Zip Archive', + add_link(req, 'alternate', '?format=zip&'+diff_params, 'Archivo Zip', 'application/zip', 'zip') add_stylesheet(req, 'common/css/changeset.css') add_stylesheet(req, 'common/css/diff.css') @@ -304,9 +304,9 @@ def _changeset_title(rev): if restricted: - return 'Changeset %s for %s' % (rev, path) + return 'Conjunto de cambios %s para %s' % (rev, path) else: - return 'Changeset %s' % rev + return 'Conjunto de cambios %s' % rev title = _changeset_title(rev) properties = [] @@ -335,7 +335,7 @@ prev_path = prev_rev = None else: add_link(req, 'first', req.href.changeset(oldest_rev), - 'Changeset %s' % oldest_rev) + 'Conjunto de cambios %s' % oldest_rev) prev_path = diff.old_path prev_rev = repos.previous_rev(chgset.rev) if prev_rev: @@ -353,7 +353,7 @@ next_href = req.href.changeset(next_rev) else: add_link(req, 'last', req.href.changeset(youngest_rev), - 'Changeset %s' % youngest_rev) + 'Conjunto de cambios %s' % youngest_rev) next_rev = repos.next_rev(chgset.rev) if next_rev: next_href = req.href.changeset(next_rev) @@ -626,7 +626,7 @@ def get_timeline_filters(self, req): if req.perm.has_permission('CHANGESET_VIEW'): - yield ('changeset', 'Repository checkins') + yield ('changeset', 'Cambios en el repositorio') def get_timeline_events(self, req, start, stop, filters): if 'changeset' in filters: @@ -644,7 +644,7 @@ shortlog = shorten_line(message) if format == 'rss': - title = Markup('Changeset [%s]: %s', chgset.rev, shortlog) + title = Markup('Conjunto de cambios [%s]: %s', chgset.rev, shortlog) href = req.abs_href.changeset(chgset.rev) if wiki_format: message = wiki_to_html(message, self.env, req, db, @@ -652,7 +652,7 @@ else: message = html.PRE(message) else: - title = Markup('Changeset [%s] by %s', chgset.rev, + title = Markup('Conjunto de cambios [%s] por %s', chgset.rev, chgset.author) href = req.href.changeset(chgset.rev) @@ -750,7 +750,7 @@ def get_search_filters(self, req): if req.perm.has_permission('CHANGESET_VIEW'): - yield ('changeset', 'Changesets') + yield ('changeset', 'Conjuntos de cambios') def get_search_results(self, req, terms, filters): if not 'changeset' in filters: Index: trac/versioncontrol/web_ui/log.py =================================================================== --- trac/versioncontrol/web_ui/log.py (revision 5935) +++ trac/versioncontrol/web_ui/log.py (working copy) @@ -94,7 +94,7 @@ path_links = get_path_links(req.href, path, rev) req.hdf['log.path'] = path_links if path_links: - add_link(req, 'up', path_links[-1]['href'], 'Parent directory') + add_link(req, 'up', path_links[-1]['href'], 'Directorio superior') # The `history()` method depends on the mode: # * for ''stop on copy'' and ''follow copies'', it's `Node.history()` @@ -134,9 +134,9 @@ previous_path = old_path if info == []: # FIXME: we should send a 404 error here - raise TracError("The file or directory '%s' doesn't exist " - "at revision %s or at any previous revision." - % (path, rev), 'Nonexistent path') + raise TracError(unicode("El archivo o directorio '%s' no existe " + "en la revisión %s o ni en ninguna revisión previa.", 'utf-8') + % (path, rev), 'Ruta inexistente') def make_log_href(path, **args): link_rev = rev @@ -152,7 +152,7 @@ next_rev = info[-1]['rev'] next_path = info[-1]['path'] add_link(req, 'next', make_log_href(next_path, rev=next_rev), - 'Revision Log (restarting at %s, rev. %s)' + unicode('Bitácora de Revisiones (reiniciando en %s, rev. %s)', 'utf-8') % (next_path, next_rev)) # now, only show 'limit' results del info[-1] @@ -202,11 +202,11 @@ add_stylesheet(req, 'common/css/diff.css') rss_href = make_log_href(path, format='rss', stop_rev=stop_rev) - add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml', + add_link(req, 'alternate', rss_href, 'Fuente en formato RSS', 'application/rss+xml', 'rss') changelog_href = make_log_href(path, format='changelog', stop_rev=stop_rev) - add_link(req, 'alternate', changelog_href, 'ChangeLog', 'text/plain') + add_link(req, 'alternate', changelog_href, unicode('Bitácora de cambios', 'utf-8'), 'text/plain') return 'log.cs', None Index: trac/versioncontrol/web_ui/browser.py =================================================================== --- trac/versioncontrol/web_ui/browser.py (revision 5935) +++ trac/versioncontrol/web_ui/browser.py (working copy) @@ -78,7 +78,7 @@ if not req.perm.has_permission('BROWSER_VIEW'): return yield ('mainnav', 'browser', - html.A('Browse Source', href=req.href.browser())) + html.A('Explorar repositorio', href=req.href.browser())) # IPermissionRequestor methods @@ -140,7 +140,7 @@ path_links = get_path_links(req.href, path, rev) if len(path_links) > 1: - add_link(req, 'up', path_links[-2]['href'], 'Parent directory') + add_link(req, 'up', path_links[-2]['href'], 'Directorio superior') req.hdf['browser.path'] = path_links if node.isdir: @@ -205,7 +205,7 @@ filter(None, [fnmatchcase(node.path, p) for p in patterns]): zip_href = req.href.changeset(rev or repos.youngest_rev, node.path, old=rev, old_path='/', format='zip') - add_link(req, 'alternate', zip_href, 'Zip Archive', + add_link(req, 'alternate', zip_href, 'Archivo Zip', 'application/zip', 'zip') req.hdf['browser'] = {'order': order, 'desc': desc and 1 or 0, @@ -270,12 +270,12 @@ # add ''Plain Text'' alternate link if needed if not is_binary(chunk) and mime_type != 'text/plain': plain_href = req.href.browser(node.path, rev=rev, format='txt') - add_link(req, 'alternate', plain_href, 'Plain Text', + add_link(req, 'alternate', plain_href, 'Texto Plano', 'text/plain') # add ''Original Format'' alternate link (always) raw_href = req.href.export(rev or repos.youngest_rev, node.path) - add_link(req, 'alternate', raw_href, 'Original Format', mime_type) + add_link(req, 'alternate', raw_href, 'Formato Original', mime_type) self.log.debug("Rendering preview of node %s@%s with mime-type %s" % (node.name, str(rev), mime_type)) Index: trac/versioncontrol/cache.py =================================================================== --- trac/versioncontrol/cache.py (revision 5935) +++ trac/versioncontrol/cache.py (working copy) @@ -81,8 +81,8 @@ if repository_dir != self.name: self.log.info("'repository_dir' has changed from %r to %r" % (repository_dir, self.name)) - raise TracError("The 'repository_dir' has changed, " - "a 'trac-admin resync' operation is needed.") + raise TracError(unicode("La entrada 'repository_dir' ha cambiado, " + "es necesario realizar la operación 'trac-admin resync'.", 'utf-8')) elif repository_dir is None: # self.log.info('Storing initial "repository_dir": %s' % self.name) cursor.execute("INSERT INTO system (name,value) VALUES (%s,%s)", @@ -100,7 +100,7 @@ # -- retrieve the youngest revision cached so far if CACHE_YOUNGEST_REV not in metadata: - raise TracError('Missing "youngest_rev" in cache metadata') + raise TracError(unicode('No existe "youngest_rev" en el caché de meta-datos', 'utf-8')) self.youngest = metadata[CACHE_YOUNGEST_REV] Index: trac/Settings.py =================================================================== --- trac/Settings.py (revision 5935) +++ trac/Settings.py (working copy) @@ -33,7 +33,7 @@ def get_navigation_items(self, req): yield ('metanav', 'settings', - html.A('Settings', href=req.href.settings())) + html.A(unicode('Configuración', 'utf-8'), href=req.href.settings())) # IRequestHandler methods @@ -49,7 +49,7 @@ elif action == 'load': self._do_load(req) - req.hdf['title'] = 'Settings' + req.hdf['title'] = unicode('Configuración', 'utf-8') req.hdf['settings'] = req.session if req.authname == 'anonymous': req.hdf['settings.session_id'] = req.session.sid Index: trac/perm.py =================================================================== --- trac/perm.py (revision 5935) +++ trac/perm.py (working copy) @@ -32,7 +32,7 @@ self.action = action def __str__ (self): - return '%s privileges are required to perform this operation' % self.action + return unicode('Se requiere el privilegio %s para realizar esta operación', 'utf-8') % self.action class IPermissionRequestor(Interface): @@ -185,7 +185,7 @@ """Grant the user with the given name permission to perform to specified action.""" if action.isupper() and action not in self.get_actions(): - raise TracError, '%s is not a valid action.' % action + raise TracError, unicode('%s no es una acción válida.', 'utf-8') % action self.store.grant_permission(username, action) Index: trac/Search.py =================================================================== --- trac/Search.py (revision 5935) +++ trac/Search.py (working copy) @@ -74,7 +74,7 @@ parameters. The result is returned as a (string, params) tuple. """ if len(columns) < 1 or len(terms) < 1: - raise TracError('Empty search attempt, this should really not happen.') + raise TracError(unicode('Intento de búsqueda con criterio vacío, esto no debería pasar realmente.', 'utf-8')) likes = ['%s %s' % (i, db.like()) for i in columns] c = ' OR '.join(likes) @@ -132,7 +132,7 @@ if not req.perm.has_permission('SEARCH_VIEW'): return yield ('mainnav', 'search', - html.A('Search', href=req.href.search(), accesskey=4)) + html.A('Buscar', href=req.href.search(), accesskey=4)) # IPermissionRequestor methods @@ -162,7 +162,7 @@ 'active': filter[0] in filters } for filter in available_filters] - req.hdf['title'] = 'Search' + req.hdf['title'] = 'Buscar' query = req.args.get('q') if query: @@ -173,9 +173,9 @@ terms = search_terms(query) # Refuse queries that obviously would result in a huge result set if len(terms) == 1 and len(terms[0]) < self.min_query_length: - raise TracError('Search query too short. ' - 'Query must be at least %d characters long.' % \ - self.min_query_length, 'Search Error') + raise TracError(unicode('El criterio de búsqueda es demasiado corto. ' + 'El criterio de búsqueda debe tener al menos %d caracteres de longitud.', 'utf-8') % \ + self.min_query_length, unicode('Error en la Búsqueda', 'utf-8')) results = [] for source in self.search_sources: results += list(source.get_search_results(req, terms, filters)) @@ -185,7 +185,7 @@ n_pages = (n-1) / page_size + 1 results = results[(page-1) * page_size: page * page_size] - req.hdf['title'] = 'Search Results' + req.hdf['title'] = unicode('Resultados de la Búsqueda', 'utf-8') req.hdf['search.q'] = req.args.get('q') req.hdf['search.page'] = page req.hdf['search.n_hits'] = n @@ -195,12 +195,12 @@ next_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), page=page + 1, noquickjump=1) - add_link(req, 'next', next_href, 'Next Page') + add_link(req, 'next', next_href, unicode('Siguiente página', 'utf-8')) if page > 1: prev_href = req.href.search(zip(filters, ['on'] * len(filters)), q=req.args.get('q'), page=page - 1, noquickjump=1) - add_link(req, 'prev', prev_href, 'Previous Page') + add_link(req, 'prev', prev_href, unicode('Página anterior', 'utf-8')) req.hdf['search.page_href'] = req.href.search( zip(filters, ['on'] * len(filters)), q=req.args.get('q'), noquickjump=1) @@ -222,7 +222,7 @@ if kwd[0] == '/': quickjump_href = req.href.browser(kwd) name = kwd - description = 'Browse repository path ' + kwd + description = 'Buscar ruta en el repositorio ' + kwd else: link = wiki_to_link(kwd, self.env, req) if isinstance(link, Element): Index: trac/config.py =================================================================== --- trac/config.py (revision 5935) +++ trac/config.py (working copy) @@ -220,7 +220,7 @@ yield option def __repr__(self): - return '
' % (self.name) + return unicode('', 'utf-8') % (self.name) def get(self, name, default=None): """Return the value of the specified option.""" @@ -332,7 +332,7 @@ return None def __set__(self, instance, value): - raise AttributeError, 'can\'t set attribute' + raise AttributeError, 'no se puede fijar el valor del atributo' def __repr__(self): return '<%s [%s] "%s">' % (self.__class__.__name__, self.section, @@ -376,9 +376,9 @@ for impl in self.xtnpt.extensions(instance): if impl.__class__.__name__ == value: return impl - raise AttributeError('Cannot find an implementation of the "%s" ' - 'interface named "%s". Please update the option ' - '%s.%s in trac.ini.' + raise AttributeError(unicode('No se puede encontrar una implementación de la interfaz "%s" ' + 'denominada "%s". Por favor actualice la opción ' + '%s.%s en trac.ini.', 'utf-8') % (self.xtnpt.interface.__name__, value, self.section, self.name)) Index: trac/Timeline.py =================================================================== --- trac/Timeline.py (revision 5935) +++ trac/Timeline.py (working copy) @@ -77,7 +77,7 @@ if not req.perm.has_permission('TIMELINE_VIEW'): return yield ('mainnav', 'timeline', - html.A('Timeline', href=req.href.timeline(), accesskey=2)) + html.A(unicode('Cronología', 'utf-8'), href=req.href.timeline(), accesskey=2)) # IPermissionRequestor methods @@ -151,7 +151,7 @@ if maxrows and len(events) > maxrows: del events[maxrows:] - req.hdf['title'] = 'Timeline' + req.hdf['title'] = unicode('Cronología', 'utf-8') # Get the email addresses of all known users email_map = {} @@ -192,7 +192,7 @@ add_stylesheet(req, 'common/css/timeline.css') rss_href = req.href.timeline([(f, 'on') for f in filters], daysback=90, max=50, format='rss') - add_link(req, 'alternate', rss_href, 'RSS Feed', 'application/rss+xml', + add_link(req, 'alternate', rss_href, 'Fuente en formato RSS', 'application/rss+xml', 'rss') for idx,fltr in enumerate(available_filters): req.hdf['timeline.filters.%d' % idx] = {'name': fltr[0], @@ -216,8 +216,8 @@ 'daysback')] href = req.href.timeline(args+[(f, 'on') for f in other_filters]) raise TracError(Markup( - '%s event provider (%s) failed:

' + unicode('El proveedor de eventos %s (%s) falló:

' '%s: %s' - '

You may want to see the other kind of events from the ' - 'Timeline

', + '

Tal vez quiera ver los otros tipos de eventos de la ' + 'Cronología

', 'utf-8'), ", ".join(guilty_kinds), ep_name, exc_name, to_unicode(exc), href)) Index: trac/About.py =================================================================== --- trac/About.py (revision 5935) +++ trac/About.py (working copy) @@ -38,7 +38,7 @@ def get_navigation_items(self, req): yield ('metanav', 'about', - html.a('About Trac', href=req.href.about())) + html.a('Acerca de Trac', href=req.href.about())) # IPermissionRequestor methods @@ -56,7 +56,7 @@ def process_request(self, req): page = req.args.get('page', 'default') - req.hdf['title'] = 'About Trac' + req.hdf['title'] = 'Acerca de Trac' if req.perm.has_permission('CONFIG_VIEW'): req.hdf['about.config_href'] = req.href.about('config') req.hdf['about.plugins_href'] = req.href.about('plugins') Index: trac/wiki/web_ui.py =================================================================== --- trac/wiki/web_ui.py (revision 5935) +++ trac/wiki/web_ui.py (working copy) @@ -51,7 +51,7 @@ # IContentConverter methods def get_supported_conversions(self): - yield ('txt', 'Plain Text', 'txt', 'text/x-trac-wiki', 'text/plain', 9) + yield ('txt', 'Texto Plano', 'txt', 'text/x-trac-wiki', 'text/plain', 9) def convert_content(self, req, mimetype, content, key): return (content, 'text/plain;charset=utf-8') @@ -67,7 +67,7 @@ yield ('mainnav', 'wiki', html.A('Wiki', href=req.href.wiki(), accesskey=1)) yield ('metanav', 'help', - html.A('Help/Guide', href=req.href.wiki('TracGuide'), + html.A(unicode('Ayuda/Guía', 'utf-8'), href=req.href.wiki('TracGuide'), accesskey=6)) # IPermissionRequestor methods @@ -142,7 +142,7 @@ def get_timeline_filters(self, req): if req.perm.has_permission('WIKI_VIEW'): - yield ('wiki', 'Wiki changes') + yield ('wiki', 'Cambios en el Wiki') def get_timeline_events(self, req, start, stop, filters): if 'wiki' in filters: @@ -155,7 +155,7 @@ "FROM wiki WHERE time>=%s AND time<=%s", (start, stop)) for t,name,comment,author,version in cursor: - title = Markup('%s edited by %s', + title = Markup('%s editado por %s', wiki.format_page_name(name), author) diff_link = html.A('diff', href=href.wiki(name, action='diff', version=version)) @@ -230,10 +230,10 @@ for manipulator in self.page_manipulators: for field, message in manipulator.validate_wiki_page(req, page): if field: - raise InvalidWikiPage("The Wiki page field %s is invalid: %s" + raise InvalidWikiPage(unicode("El campo %s de la página del wiki es inválido: %s", 'utf-8') % (field, message)) else: - raise InvalidWikiPage("Invalid Wiki page: %s" % message) + raise InvalidWikiPage(unicode("Página del wiki inválida: %s", 'utf-8') % message) page.save(get_reporter_id(req, 'author'), req.args.get('comment'), req.remote_addr) @@ -265,7 +265,7 @@ req.perm.assert_permission('WIKI_VIEW') if not page.exists: - raise TracError("Version %s of page %s does not exist" % + raise TracError(unicode("La versión %s de la página %s no existe", 'utf-8') % (req.args.get('version'), page.name)) add_stylesheet(req, 'common/css/diff.css') @@ -322,11 +322,11 @@ if prev_version: add_link(req, 'prev', req.href.wiki(page.name, action='diff', version=prev_version), - 'Version %d' % prev_version) + unicode('Versión %d', 'utf-8') % prev_version) if next_version: add_link(req, 'next', req.href.wiki(page.name, action='diff', version=next_version), - 'Version %d' % next_version) + unicode('Versión %d', 'utf-8') % next_version) # -- text diffs diff_style, diff_options = get_diff_options(req) @@ -396,7 +396,7 @@ req.perm.assert_permission('WIKI_VIEW') if not page.exists: - raise TracError, "Page %s does not exist" % page.name + raise TracError, unicode("La página %s no existe", 'utf-8') % page.name self._set_title(req, page, 'history') @@ -454,8 +454,8 @@ } else: if not req.perm.has_permission('WIKI_CREATE'): - raise HTTPNotFound('Page %s not found', page.name) - req.hdf['wiki.page_html'] = html.P('Describe "%s" here' % page_name) + raise HTTPNotFound(unicode('No se encontró la página %s', 'utf-8'), page.name) + req.hdf['wiki.page_html'] = html.P(unicode('Describa aquí "%s"', 'utf-8') % page_name) # Show attachments req.hdf['wiki.attachments'] = attachments_to_hdf(self.env, req, db, Index: trac/wiki/intertrac.py =================================================================== --- trac/wiki/intertrac.py (revision 5935) +++ trac/wiki/intertrac.py (working copy) @@ -41,13 +41,13 @@ def process_request(self, req): link = req.args.get('link', '') if not link: - raise TracError('No TracLinks given') + raise TracError(unicode('No se pasó un TracLink', 'utf-8')) link_elt = wiki_to_link(link, self.env, req) if isinstance(link_elt, Element): href = link_elt.attr['href'] if href: req.redirect(href) - raise TracError('"%s" is not a TracLinks' % link) + raise TracError('"%s" no es un TracLink' % link) # IWikiMacroProvider methods @@ -56,7 +56,7 @@ yield 'InterTrac' def get_macro_description(self, name): - return "Provide a list of known InterTrac prefixes." + return "Proveer una lista de prefijos conocidos InterTrac." def render_macro(self, req, name, content): intertracs = {} @@ -73,7 +73,7 @@ intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield html.TR(html.TD(html.B(prefix)), - html.TD('Alias for ', html.B(intertrac))) + html.TD('Alias para ', html.B(intertrac))) else: url = intertrac.get('url', '') if url: @@ -83,5 +83,5 @@ html.TD(html.A(title, href=url))) return html.TABLE(class_="wiki intertrac")( - html.TR(html.TH(html.EM('Prefix')), html.TH(html.EM('Trac Site'))), + html.TR(html.TH(html.EM('Prefijo')), html.TH(html.EM('Sitio Trac'))), [generate_prefix(p) for p in sorted(intertracs.keys())]) Index: trac/wiki/model.py =================================================================== --- trac/wiki/model.py (revision 5935) +++ trac/wiki/model.py (working copy) @@ -68,7 +68,7 @@ exists = property(fget=lambda self: self.version > 0) def delete(self, version=None, db=None): - assert self.exists, 'Cannot delete non-existent page' + assert self.exists, unicode('No se puede eliminar una página no existente', 'utf-8') if not db: db = self.env.get_db_cnx() handle_ta = True @@ -131,7 +131,7 @@ cursor.execute("UPDATE wiki SET readonly=%s WHERE name=%s", (self.readonly, self.name)) else: - raise TracError('Page not modified') + raise TracError(unicode('La página no se modificó', 'utf-8')) if handle_ta: db.commit() Index: trac/wiki/formatter.py =================================================================== --- trac/wiki/formatter.py (revision 5935) +++ trac/wiki/formatter.py (working copy) @@ -72,7 +72,7 @@ self.processor = self._mimeview_processor else: self.processor = self._default_processor - self.error = "No macro or processor named '%s' found" % name + self.error = unicode("No se encontró un macro ó procesador (processor) denominado '%s'", 'utf-8') % name # builtin processors @@ -107,8 +107,8 @@ def process(self, req, text, in_paragraph=False): if self.error: - text = system_message(Markup('Error: Failed to load processor ' - '%s', self.name), + text = system_message(Markup(unicode('Error: Falló la carga del procesador ' + '%s', 'utf-8'), self.name), self.error) else: text = self.processor(req, text) @@ -380,7 +380,7 @@ intertrac_config = self.env.config['intertrac'] url = intertrac_config.get(ns+'.url') if url: - name = intertrac_config.get(ns+'.title', 'Trac project %s' % ns) + name = intertrac_config.get(ns+'.title', 'Proyecto Trac %s' % ns) compat = intertrac_config.getbool(ns+'.compat', 'true') # TODO: set `compat` default to False once 0.10 gets widely used # and remove compatibility code altogether once 0.[89] disappear... @@ -442,7 +442,7 @@ except Exception, e: self.env.log.error('Macro %s(%s) failed' % (name, args), exc_info=True) - return system_message('Error: Macro %s(%s) failed' % (name, args), + return system_message(unicode('Error: Falló el macro %s(%s)', 'utf-8') % (name, args), e) # Headings Index: trac/wiki/macros.py =================================================================== --- trac/wiki/macros.py (revision 5935) +++ trac/wiki/macros.py (working copy) @@ -252,7 +252,7 @@ # we expect the 1st argument to be a filename (filespec) args = content.split(',') if len(args) == 0: - raise Exception("No argument.") + raise Exception("Faltan argumentos.") filespec = args[0] size_re = re.compile('[0-9]+%?$') attr_re = re.compile('(align|border|width|height|alt' @@ -293,7 +293,7 @@ if parts[0] in ['wiki', 'ticket']: module, id, file = parts else: - raise Exception("%s module can't have attachments" % parts[0]) + raise Exception(unicode("El módulo %s no puede tener adjuntos", 'utf-8') % parts[0]) elif len(parts) == 2: from trac.versioncontrol.web_ui import BrowserModule try: @@ -334,9 +334,9 @@ if len(path_info) > 2: id = path_info[2] if module not in ['wiki', 'ticket']: - raise Exception('Cannot reference local attachment from here') + raise Exception(unicode('No se puede referenciar a un adjunto local desde aquí', 'utf-8')) else: - raise Exception('No filespec given') + raise Exception(unicode('No se pasó el argumento "filespec"', 'utf-8')) if not url: # this is an attachment from trac.attachment import Attachment attachment = Attachment(self.env, module, id, file) @@ -380,7 +380,7 @@ descr = wiki_to_html(descr or '', self.env, req) except Exception, e: descr = Markup(system_message( - "Error: Can't get description for macro %s" \ + unicode("Error: No se puede obtener la descripción para el macro %s", 'utf-8') \ % macro_name, e)) yield (macro_name, descr) @@ -466,4 +466,4 @@ macro_file = os.path.join(path, name + '.py') if os.path.isfile(macro_file): return imp.load_source(name, macro_file) - raise TracError, 'Macro %s not found' % name + raise TracError, unicode('No se encontró el macro %s', 'utf-8') % name Index: trac/wiki/interwiki.py =================================================================== --- trac/wiki/interwiki.py (revision 5935) +++ trac/wiki/interwiki.py (working copy) @@ -131,7 +131,7 @@ yield 'InterWiki' def get_macro_description(self, name): - return "Provide a description list for the known InterWiki prefixes." + return "Proveer una lista descriptiva de los prefijos InterWiki conocidos." def render_macro(self, req, name, content): from trac.util import sorted @@ -144,7 +144,7 @@ 'rc_url': self._expand_or_append(url, ['RecentChanges']), 'description': title == prefix and url or title}) - return _.TABLE(_.TR(_.TH(_.EM("Prefix")), _.TH(_.EM("Site"))), + return _.TABLE(_.TR(_.TH(_.EM("Prefijo")), _.TH(_.EM("Sitio"))), [ _.TR(_.TD(_.A(w['prefix'], href=w['rc_url'])), _.TD(_.A(w['description'], href=w['url']))) for w in interwikis ], Index: trac/upgrades/db10.py =================================================================== --- trac/upgrades/db10.py (revision 5935) +++ trac/upgrades/db10.py (working copy) @@ -22,4 +22,4 @@ def do_upgrade(env, ver, cursor): for s in sql: cursor.execute(s) - print 'Please perform a "resync" after this upgrade.' + print unicode('Por favor realice un "resync" después de esta actualización.', 'utf-8').encode('utf-8') Index: trac/web/standalone.py =================================================================== --- trac/web/standalone.py (revision 5935) +++ trac/web/standalone.py (working copy) @@ -106,26 +106,26 @@ def main(): from optparse import OptionParser, OptionValueError - parser = OptionParser(usage='usage: %prog [options] [projenv] ...', + parser = OptionParser(usage='uso: %prog [opciones] [proyecto] ...', version='%%prog %s' % VERSION) auths = {} def _auth_callback(option, opt_str, value, parser, cls): info = value.split(',', 3) if len(info) != 3: - raise OptionValueError("Incorrect number of parameters for %s" + raise OptionValueError(unicode("Número incorrecto de parámetros para %s", 'utf-8') % option) env_name, filename, realm = info if env_name in auths: - print >>sys.stderr, 'Ignoring duplicate authentication option for ' \ - 'project: %s' % env_name + print >>sys.stderr, unicode('Ignorando opción de autenticación duplicada para ' \ + 'el proyecto: %s', 'utf-8').encode('utf-8') % env_name else: auths[env_name] = cls(os.path.abspath(filename), realm) def _validate_callback(option, opt_str, value, parser, valid_values): if value not in valid_values: - raise OptionValueError('%s must be one of: %s, not %s' + raise OptionValueError('%s debe ser uno de: %s, no %s' % (opt_str, '|'.join(valid_values), value)) setattr(parser.values, option.dest, value) @@ -174,15 +174,15 @@ options, args = parser.parse_args() if not args and not options.env_parent_dir: - parser.error('either the --env-parent-dir option or at least one ' - 'environment must be specified') + parser.error(unicode('ya sea la opción --env-parent-dir ó al menos un ' + 'entorno deben ser especificados', 'utf-8').encode('utf-8')) if options.single_env: if options.env_parent_dir: - parser.error('the --single-env option cannot be used with ' - '--env-parent-dir') + parser.error(unicode('la opción --single-env no puede ser utilizada en conjunto a ' + '--env-parent-dir', 'utf-8').encode('utf-8')) elif len(args) > 1: - parser.error('the --single-env option cannot be used with ' - 'more than one enviroment') + parser.error(unicode('la opción --single-env no puede ser utilizada con ' + 'más de un entorno', 'utf-8').encode('utf-8')) if options.port is None: options.port = { @@ -196,9 +196,9 @@ if options.daemonize and options.autoreload: for path in args + [options.env_parent_dir, options.pidfile]: if path and not os.path.isabs(path): - parser.error('"%s" is not an absolute path.\n\n' - 'when using both --auto-reload and --daemonize ' - 'all path arguments must be absolute' + parser.error('"%s" no es una ruta absoluta.\n\n' + 'cuando se utiliza en conjunto --auto-reload y --daemonize ' + 'todos los argumentos referentes a rutas deben ser absolutos' % path) # relative paths don't work when daemonized @@ -251,7 +251,7 @@ if e.errno != errno.ESRCH: raise else: - sys.exit("tracd is already running with pid %s" % pid) + sys.exit(unicode("tracd ya está corriendo con el pid %s", 'utf-8').encode('utf-8') % pid) realserve = serve def serve(): try: @@ -270,7 +270,7 @@ if options.autoreload: def modification_callback(file): - print>>sys.stderr, 'Detected modification of %s, restarting.' \ + print>>sys.stderr, unicode('Se detectó la modificación de %s, reiniciando.', 'utf-8').encode('utf-8') \ % file autoreload.main(serve, modification_callback) else: Index: trac/web/auth.py =================================================================== --- trac/web/auth.py (revision 5935) +++ trac/web/auth.py (working copy) @@ -83,12 +83,13 @@ def get_navigation_items(self, req): if req.authname and req.authname != 'anonymous': - yield ('metanav', 'login', 'logged in as %s' % req.authname) + yield ('metanav', 'login', unicode('sesión iniciada como %s', 'utf-8') % req.authname) yield ('metanav', 'logout', - html.A('Logout', href=req.href.logout())) + html.A(unicode('Cerrar Sesión', 'utf-8'), href=req.href.logout(), + onclick="clearAuthenticationCache(\'%s\')" % req.href.logout())) else: yield ('metanav', 'login', - html.A('Login', href=req.href.login())) + html.A(unicode('Iniciar Sesión', 'utf-8'), href=req.href.login())) # IRequestHandler methods @@ -119,10 +120,10 @@ case sensitive regarding user names and domain names """ if not req.remote_user: - raise TracError(html("Authentication information not available. " - "Please refer to the ", - html.a('installation documentation', - title="Configuring Authentication", + raise TracError(html(unicode("La información de autenticación no está disponible. " + "Por favor, refiérase a la ", 'utf-8'), + html.a(unicode('documentación de instalación', 'utf-8'), + title=unicode("Configurando Autenticación", 'utf-8'), href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication"), ".")) remote_user = req.remote_user @@ -130,7 +131,7 @@ remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ - 'Already logged in as %s.' % req.authname + unicode('Ya ha iniciado sesión como %s.', 'utf-8') % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() @@ -242,17 +243,17 @@ try: u, h = line.split(':') except ValueError: - print >>sys.stderr, 'Warning: invalid password line in %s: %s' \ + print >>sys.stderr, unicode('Advertencia: contraseña inválida en %s: %s', 'utf-8').encode('utf-8') \ % (filename, line) continue if '$' in h or self.crypt: self.hash[u] = h else: - print >>sys.stderr, 'Warning: cannot parse password for ' \ - 'user "%s" without the "crypt" module' % u + print >>sys.stderr, unicode('Advertencia: no se puede verificar la contraseña del ' \ + 'usuario "%s" sin el módulo "crypt"', 'utf-8').encode('utf-8') % u if self.hash == {}: - print >> sys.stderr, "Warning: found no users in file:", filename + print >> sys.stderr, "Advertencia: no existen usuarios en el archivo:", filename def test(self, user, password): self.check_reload() @@ -304,13 +305,13 @@ try: u, r, a1 = line.split(':') except ValueError: - print >>sys.stderr, 'Warning: invalid digest line in %s: %s' \ + print >>sys.stderr, unicode('Advertencia: entrada "digest" inválida en %s: %s', 'utf-8').encode('utf-8') \ % (filename, line) continue if r == self.realm: self.hash[u] = a1 if self.hash == {}: - print >> sys.stderr, "Warning: found no users in realm:", self.realm + print >> sys.stderr, "Advertencia: no existen usuarios en el dominio:", self.realm def parse_auth_header(self, authorization): values = {} Index: trac/web/api.py =================================================================== --- trac/web/api.py (revision 5935) +++ trac/web/api.py (working copy) @@ -44,7 +44,7 @@ self.message = message if args: self.message = self.message % args - Exception.__init__(self, '%s %s (%s)' % (self.code, self.reason, + Exception.__init__(self, unicode('%s %s (%s)', 'utf-8') % (self.code, self.reason, self.message)) return self @@ -408,7 +408,7 @@ "304 Not Modified" response if it matches. """ if not os.path.isfile(path): - raise HTTPNotFound("File %s not found" % path) + raise HTTPNotFound(unicode("No se encontró el archivo %s", 'utf-8') % path) stat = os.stat(path) last_modified = http_date(stat.st_mtime) Index: trac/web/clearsilver.py =================================================================== --- trac/web/clearsilver.py (revision 5935) +++ trac/web/clearsilver.py (working copy) @@ -132,7 +132,7 @@ import neo_util self.hdf = neo_util.HDF() except ImportError, e: - raise TracError, "ClearSilver not installed (%s)" % e + raise TracError, unicode("ClearSilver no está instalado (%s)", 'utf-8') % e self['hdf.loadpaths'] = loadpaths Index: trac/web/session.py =================================================================== --- trac/web/session.py (revision 5935) +++ trac/web/session.py (working copy) @@ -99,9 +99,9 @@ cursor = db.cursor() cursor.execute("SELECT sid FROM session WHERE sid=%s", (new_sid,)) if cursor.fetchone(): - raise TracError(Markup('Session "%s" already exists.
' - 'Please choose a different session ID.', - new_sid), 'Error renaming session') + raise TracError(Markup(unicode('La sesión "%s" ya existe.
' + 'Por favor escoja un diferente "identificador" (ID) de sesión.', 'utf-8'), + new_sid), unicode('Error al renombrar sesión', 'utf-8')) self.env.log.debug('Changing session ID %s to %s' % (self.sid, new_sid)) cursor.execute("UPDATE session SET sid=%s WHERE sid=%s " "AND authenticated=0", (new_sid, self.sid)) Index: trac/util/datefmt.py =================================================================== --- trac/util/datefmt.py (revision 5935) +++ trac/util/datefmt.py (working copy) @@ -30,17 +30,17 @@ if not time2: time2 = time.time() if time1 > time2: time2, time1 = time1, time2 - units = ((3600 * 24 * 365, 'year', 'years'), - (3600 * 24 * 30, 'month', 'months'), - (3600 * 24 * 7, 'week', 'weeks'), - (3600 * 24, 'day', 'days'), - (3600, 'hour', 'hours'), - (60, 'minute', 'minutes')) + units = ((3600 * 24 * 365, unicode('año', 'utf-8'), unicode('años', 'utf-8')), + (3600 * 24 * 30, 'mes', 'meses'), + (3600 * 24 * 7, 'semana', 'semanas'), + (3600 * 24, unicode('día', 'utf-8'), unicode('días', 'utf-8')), + (3600, 'hora', 'horas'), + (60, 'minuto', 'minutos')) age_s = int(time2 - time1) if resolution and age_s < resolution: return '' if age_s < 60: - return '%i second%s' % (age_s, age_s != 1 and 's' or '') + return '%i segundo%s' % (age_s, age_s != 1 and 's' or '') for u, unit, unit_plural in units: r = float(age_s) / float(u) if r >= 0.9: @@ -111,5 +111,5 @@ except ValueError: continue if seconds == None: - raise ValueError, '%s is not a known date format.' % text + raise ValueError, '%s no es un formato de fecha conocido.' % text return seconds Index: trac/notification.py =================================================================== --- trac/notification.py (revision 5935) +++ trac/notification.py (working copy) @@ -190,7 +190,7 @@ self._charset.input_codec = None self._charset.output_charset = 'ascii' else: - raise TracError, 'Invalid email encoding setting: %s' % pref + raise TracError, unicode('Configuración de codificación de correo electrónico inválida: %s', 'utf-8') % pref def notify(self, resid, subject): self.subject = subject @@ -203,11 +203,11 @@ self.replyto_email = self.config['notification'].get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: - raise TracError(Markup('Unable to send email due to identity ' - 'crisis.

Neither notification.from ' - 'nor notification.reply_to are ' - 'specified in the configuration.

'), - 'SMTP Notification Error') + raise TracError(Markup(unicode('No se pudo enviar correo electrónico debido a una crisis ' + 'de identidad.

Ni notification.from ' + 'ni notification.reply_to han sido' + 'especificados en la configuración.

', 'utf-8')), + unicode('Error de Notificación SMTP', 'utf-8')) # Authentication info (optional) self.user_name = self.config['notification'].get('smtp_user') @@ -220,7 +220,7 @@ maxlength = MAXHEADERLEN-(len(key)+2) # Do not sent ridiculous short headers if maxlength < 10: - raise TracError, "Header length is too short" + raise TracError, "La longitud del encabezado es demasiado corta" try: tmp = name.encode('ascii') header = Header(tmp, 'ascii', maxlinelen=maxlength) @@ -280,7 +280,7 @@ if self._use_tls: self.server.ehlo() if not self.server.esmtp_features.has_key('starttls'): - raise TracError, "TLS enabled but server does not support TLS" + raise TracError, unicode("TLS está habilitado pero el servidor no soporta TLS", 'utf-8') self.server.starttls() self.server.ehlo() if self.user_name: @@ -349,8 +349,8 @@ try: dummy = body.encode('ascii') except UnicodeDecodeError: - raise TracError, "Ticket contains non-Ascii chars. " \ - "Please change encoding setting" + raise TracError, unicode("El ticket contiene caracteres no-Ascii. " \ + "Por favor modifique la configuración de codificación", 'utf-8') msg = MIMEText(body, 'plain') # Message class computes the wrong type from MIMEText constructor, # which does not take a Charset object as initializer. Reset the