From 4608fb2e889cf7f3807a4a2fcc723a31f8da3e4e Mon Sep 17 00:00:00 2001 From: ffuentes Date: Sat, 3 Apr 2021 19:47:54 +0000 Subject: =?UTF-8?q?traducci=C3=B3n=20bru=20(python.patch)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clients/urwid/main.py | 473 +++++++++++++++----------- python.patch | 893 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1172 insertions(+), 194 deletions(-) create mode 100644 python.patch diff --git a/clients/urwid/main.py b/clients/urwid/main.py index 3adeeff..a8a5e57 100644 --- a/clients/urwid/main.py +++ b/clients/urwid/main.py @@ -87,7 +87,7 @@ obnoxious_logo = """ 8 888888888P 8 888888888P `Y888888 ' . % %""" -welcome = """>>> Bienvenido al BBS de Texto-Plano! ------------------@ +welcome = """>>> -------- Bienvenido al BBS de Texto-Plano! -----------@ | BBJ es un muro de discusión persistente y ordenado | | temporalmente para tildes. Puedes ingresar | | registrar un usuario nuevo, or participar anónimamente | @@ -97,7 +97,7 @@ welcome = """>>> Bienvenido al BBS de Texto-Plano! ------------------@ @_________________________________________________________@ """ -anon_warn = """>>> \033[1;31mSolo un recordatorio!\033[0m ----------------------------------@ +anon_warn = """>>> \033[1;31m¡Solo un recordatorio!\033[0m ----------------------------@ | No estás logueado en BBJ, y estás posteando | | tu mensaje anónimamente. Si no ingresas con usuario | | no podrás borrar o editar este mensaje | @@ -106,102 +106,186 @@ anon_warn = """>>> \033[1;31mSolo un recordatorio!\033[0m ---------------------- """ format_help = [ - "Quick reminder: \[rainbow: expressions work like this]. You may scroll " - "this message, or press Q or escape to close it.\n\n" - - "BBJ supports **bolding**, __underlining__, and [rainbow: coloring] text " - "using markdown-style symbols as well as tag-like expressions. Markdown " - "is **NOT** fully implemented, but several of the more obvious concepts " - "have been brought over. Additionally, we have chan-style greentext and " - "numeric post referencing, ala >>3 for the third reply.", - - "[red: Whitespace]", - - "When you're composing, it is desirable to not include your own linebreaks " - "into paragraphs of your post, because clients handle text wrapping on their " - "own. Adding them yourself can cause your posts to look very strange. You can " - "always edit your posts after submitting them if you do this by accident, as " - "long as you are not anonymous.", - - "In previous versions of BBJ, linebreaks were joined into sentences if they " - "occured in the same paragraph, however this confused many users and has been " - "reverted to just use whatever was submitted, as-is.", - - - "[red: Colors, Bold, Underline & Expressions]", - - "You can use [rainbow: rainbow], [red: red], [yellow: yellow], [green: green], " - "[blue: blue], [cyan: cyan], [magenta: and magenta], [dim: dim], **bold**, and __underline__ " - "inside of your posts. \**bold works like this\**, \__and underlines like this\__. " - "You can escape these expressions \\\**like this\\\**. They can span up to the full width " - "of the same line. They are best used on shorter phrases. " - "However, you can use a different syntax for it, which is also required to use " - "colors: these expressions \[bold: look like this] and have less restrictions.", - - "The colon and the space following it are important. When you use these " - "expressions, the __first__ space is not part of the content, but any characters, " - "including spaces, that follow it are included in the body. The formatting will " - "apply until the closing ]. You can escape such an expression \\\[cyan: like this] " - "and can also \\[blue: escape \\\] other closing brackets] inside of it. Only " - "closing brackets need to be escaped within an expression. Any backslashes used " - "for escaping will not show in the body unless you use two slashes.", - - "This peculiar syntax elimiates false positives. You never have to escape [normal] " - "brackets when using the board. Only expressions with **valid and defined** directives " - "will be affected. [so: this is totally valid and requires no escapes] because 'so' is " - "not a directive. [red this will pass too] because the colon is missing.", - - "The following directives may be used in this form: red, yellow, green, blue, cyan, " - "magenta, bold, underline, dim, and rainbow. Nesting expressions into eachother will " - "override the parent directives until the innermost expression closes. Thus, nesting " - "is valid but doesn't produce layered results on the command line client.", - - "[red: Quotes & Greentext]", - - "You can refer to a post number using two angle brackets pointing into a number. >>432 " - "like this. You can color a whole line green by proceeding it with a '>'. Note that " - "this violates the sentence structure outlined in the **Whitespace** section above, " - "so you may introduce >greentext without splicing into seperate paragraphs. The '>' " - "must be the first character on the line with no whitespace before it.\n>it looks like this\n" - "and the paragraph doesnt have to break on either side. The formatter is smart enough to " - "differentiate between >>greentext with multiple arrows and numeric quotes (outlined below) " - "given that the text doesn't start with any numbers.", - - "When using numeric quotes, they are highlighted and the author's name will show " - "next to them in the thread. You can press enter when focused on a message to view " - "the parent posts. You may insert these directives manually or use the function " - "on post menus.", - - "Quoting directives cannot be escaped." + "Recordatorio rápido: \[rainbow: las expresiones se ven así]. Puedes " + "desplazar este mensaje, o presionar Q o Escape para cerrarlo.\n\n" + +# "Quick reminder: \[rainbow: expressions work like this]. You may scroll " +# "this message, or press Q or escape to close it.\n\n" + + "BBJ soporta texto en **negrita**, __subrayado__ y [rainbow: coloreado] " + "usando símbolos a lo Markdown al igual que expresiones de " + "tipo tag. Markdown **NO** está implementado por completo, sin embargo " + "se adoptaron varios conceptos clave de allí. Adicionalmente, trajimos " + "de los chanes el texto verde y referencias numéricas, ej. >>3 para la " + "tercera respuesta.", + +# "BBJ supports **bolding**, __underlining__, and [rainbow: coloring] text " +# "using markdown-style symbols as well as tag-like expressions. Markdown " +# "is **NOT** fully implemented, but several of the more obvious concepts " +# "have been brought over. Additionally, we have chan-style greentext and " +# "numeric post referencing, ala >>3 for the third reply.", + + "[red: Espaciado]", + +# "[red: Whitespace]", + + "Cuando estás escribiendo, se desea no incluír tus propios saltos de " + "línea en los párrafos de tu post, porque los clientes manejan las " + "líneas de texto por su cuenta. Añadirlas tú mismo puede causar que tus " + "posts se vean muy extraños. Siempre puedes editar tus posts después de " + "publicarlos si haces esto por accidente, siempre y cuando no seas " + "anónimo.", + +# "When you're composing, it is desirable to not include your own linebreaks " +# "into paragraphs of your post, because clients handle text wrapping on their " +# "own. Adding them yourself can cause your posts to look very strange. You can " +# "always edit your posts after submitting them if you do this by accident, as " +# "long as you are not anonymous.", + + "En versiones anteriores de BBJ, los saltos de línea se unían en " + "oraciones si estaban en el mismo párrafo, sin embargo esto confundió a " + "varios usuarios y ha sido revertido a publicar lo que sea que se haya " + "escrito, tal y como es.", + +# "In previous versions of BBJ, linebreaks were joined into sentences if they " +# "occured in the same paragraph, however this confused many users and has been " +# "reverted to just use whatever was submitted, as-is.", + + "[red: Colores, Negrita, Subrayado y Expresiones]", + +# "[red: Colors, Bold, Underline & Expressions]", + + "Puedes usar [rainbow: rainbow], [red: red], [yellow: " + "yellow], [green: green], [blue: blue], [cyan: " + "cyan] [magenta: y magenta], [dim: dim], **bold** y " + "__underline__ dentro de tus posts. \**bold se usa así\* " + "\__y underline así\__. Puedes escapar estas expresiones " + "\\\**así\\\**. Pueden abarcar hasta todo el ancho de la misma línea. " + "Funcionan mejor para frases más cortas. " + "Sin embargo, puedes usar una sintáxis distinta, que se utiliza también " + "para usar colores: estas expresiones \[bold: se ven así] y tienen menos " + "restricciones.", + +# "You can use [rainbow: rainbow], [red: red], [yellow: yellow], [green: green], " +# "[blue: blue], [cyan: cyan], [magenta: and magenta], [dim: dim], **bold**, and __underline__ " +# "inside of your posts. \**bold works like this\**, \__and underlines like this\__. " +# "You can escape these expressions \\\**like this\\\**. They can span up to the full width " +# "of the same line. They are best used on shorter phrases. " +# "However, you can use a different syntax for it, which is also required to use " +# "colors: these expressions \[bold: look like this] and have less restrictions.", + + "Los dos puntos y el espacio siguiéndole son importantes. Cuando usas " + "estas expresiones, el __primer__ espacio no forma parte del contenido, " + "sino cualquier caracter, incluyendo espacios, que lo siguen, se " + "incluyen en el cuerpo. El formateo se aplicará hasta el ] final. Puedes " + "escaparla \\\[cyan: así], y también \\[blue: escapar \\\] otros " + "corchetes finales dentro de ella. Solo los corchetes finales se " + "necesitan escapar en una expresión. Cualquier barra diagonal inversa " + "que se use para escapar no se mostrará en el cuerpo a menos que uses " + "dos barras.", + +# "The colon and the space following it are important. When you use these " +# "expressions, the __first__ space is not part of the content, but any characters, " +# "including spaces, that follow it are included in the body. The formatting will " +# "apply until the closing ]. You can escape such an expression \\\[cyan: like this] " +# "and can also \\[blue: escape \\\] other closing brackets] inside of it. Only " +# "closing brackets need to be escaped within an expression. Any backslashes used " +# "for escaping will not show in the body unless you use two slashes.", + + "Esta sintáxis peculiar elimina falsos positivos. Nunca tienes que " + "escapar corchetes [normales] cuando se usa el tablón. Solo las " + "expresiones con directivas **válidas y definidas** se ven afectadas. " + "[entonces: esto es totalmente válido y no requiere escapes] porque " + "'entonces' no es una directiva. [red esto también pasa de largo] porque faltan " + "los dos puntos.", + +# "This peculiar syntax elimiates false positives. You never have to escape [normal] " +# "brackets when using the board. Only expressions with **valid and defined** directives " +# "will be affected. [so: this is totally valid and requires no escapes] because 'so' is " +# "not a directive. [red this will pass too] because the colon is missing.", + + "Las siguientes directivas se pueden usar de esta forma: red, yellow, " + "green, blue, cyan, magenta, bold, underline, dim y rainbow. Las " + "expresiones que se anidan una adentro de la otra van a anular la " + "directiva padre hasta que la expresión de más adentro se cierre. Por " + "tanto, anidar es válido pero no produce resultados combinados en el " + "cliente de la línea de comandos.", + +# "The following directives may be used in this form: red, yellow, green, blue, cyan, " +# "magenta, bold, underline, dim, and rainbow. Nesting expressions into eachother will " +# "override the parent directives until the innermost expression closes. Thus, nesting " +# "is valid but doesn't produce layered results on the command line client.", + + "[red: Citas y Texto verde]", + +# "[red: Quotes & Greentext]", + + "Puedes referirte al número de un post usando dos flechas 'mayor que' " + "apuntando a un número. >>432 como esto. Puedes colorear una línea " + "entera de verde precediéndola con un '>'. Nótese que esto viola la " + "estructura de oración en la sección **Espaciado** mencionada " + "anteriormente, por lo que podrías introducir >texto verde sin " + "escribirlo en párrafos separados. El '>' debe ser el primer caracter en " + "la línea, sin espacios antes de él.\n>se ve como esto\n" + "y el párrafo no tiene que romperse en ningún lado. El formateador es " + "suficientemente inteligente para diferenciar entre >>texto verde con " + "múltiples flechas y citas numéricas (mencionadas más abajo) dado que el " + "texto no comienza con ningún número.", + +# "You can refer to a post number using two angle brackets pointing into a number. >>432 " +# "like this. You can color a whole line green by proceeding it with a '>'. Note that " +# "this violates the sentence structure outlined in the **Whitespace** section above, " +# "so you may introduce >greentext without splicing into seperate paragraphs. The '>' " +# "must be the first character on the line with no whitespace before it.\n>it looks like this\n" +# "and the paragraph doesnt have to break on either side. The formatter is smart enough to " +# "differentiate between >>greentext with multiple arrows and numeric quotes (outlined below) " +# "given that the text doesn't start with any numbers.", + + "Cuando se usan citas numéricas, éstas se resaltan y el nombre del autor " + "se mostrará al lado de ellas en el hilo. Puedes presionar Enter cuando " + "se está enfocado en un mensaje para ver los posts padre. Puedes " + "insertar estas directivas manualmente o usar la función en " + "los menúes del post.", + +# "When using numeric quotes, they are highlighted and the author's name will show " +# "next to them in the thread. You can press enter when focused on a message to view " +# "the parent posts. You may insert these directives manually or use the function " +# "on post menus.", + + "Las directivas de citado no se pueden escapar." +# "Quoting directives cannot be escaped." ] general_help = [ - ("bold", "use the arrow keys, j/k, or n/p to scroll down this menu\n\n"), - ("bold", "use q or escape to close dialogs and menus (including this one)\n\n"), - ("10", "use q, escape, or a left directional key to go back at any point" - " from just about anywhere.\n\n"), - ("20", "use the o key to change your settings when this dialog is closed\n\n"), - - "You may use the arrow keys, or use ", ("button", "jk/np/Control-n|p"), - " to move up and down by " - "an element. If an element is overflowing the screen, it will scroll only one line. " - "To make scrolling faster, ", ("button", "hold shift"), " when using a control: it " - "will repeat 5 times by default, and you can change this number in your settings.\n\n" - - "In threads, The ", ("button", "<"), " and ", ("button", ">"), " keys will jump by " - "a chosen number of post headers. You can see the count inside of the footer line at " - "the far right side: press ", ("button", "x"), " to cycle it upwards or ", - ("button", "X"), " to cycle it downwards.\n\n" - - "In the thread index and any open thread, the ", ("button", "b"), " and ", ("button", "t "), - "keys may be used to go to very top or bottom.\n\n" - - "To go back and forth between threads, you may also use the left/right arrow keys, " - "or ", ("button", "h"), "/", ("button", "l"), " to do it vi-style.\n\n" - - "Aside from those, primary controls are shown on the very bottom of the screen " - "in the footer line, or may be placed in window titles for other actions like " - "dialogs or composers." + ("bold", "usa las flechas, j/k o n/p para desplazar este menú\n\n"), + ("bold", "usa q o escape para cerrar diálogos y menúes (incluyendo éste)\n\n"), + ("10", "usa q, escape o una flecha izquierda para volver a cualquier punto" + " desde cualquier lado.\n\n"), + ("20", "usa la tecla o para cambiar tus opciones cuando este diálogo esté cerrado\n\n"), + + "Puedes usar las flechas, o usar ", ("button", "jk/np/Control-n|p"), + " para moverte arriba y abajo por " + "cada elemento. Si un elemento excede la pantalla, se moverá solo una línea. " + + "Para moverte más rápido, ", ("button", "mantén presionado shift "), + "cuando uses un control: ", + + "por defecto se repetirá 5 veces, y puedes cambiar este número en tus opciones.\n\n" + + "En hilos, las teclas ", ("button", "<"), " y ", ("button", ">"), " saltan un " + "elegido número de cabeceras de post. Puedes ver la cuenta dentro del pie de pantalla en " + "la línea de abajo: presiona ", ("button", "x"), " para aumentarlo o ", + ("button", "X"), " para bajarlo.\n\n" + + "En el índice de hilos y en cualquier hilo abierto, las teclas ", ("button", "t"), " y ", ("button", "b "), + "se pueden usar para ir al inicio o al fin del contenido.\n\n" + + "Para ir y volver entre hilos, también puedes usar las teclas izquierda/derecha, " + "o ", ("button", "h"), "/", ("button", "l"), " para hacerlo al estilo vi.\n\n" + + "Fuera de ellos, los controles primarios se muestran en la parte baja en " + "el pie de la pantalla, o también se colocan en títulos de ventana para " + "otras acciones como diálogos o compositores." ] colors = [ @@ -221,11 +305,11 @@ default_prefs = { "integrate_external_editor": True, "index_spacing": False, "dramatic_exit": True, - "date": "%Y/%m/%d", + "date": "%d/%m/%Y", "time": "%H:%M", "frame_theme": "tilde", "custom_divider_char": False, - "frame_title": "BBJ", + "frame_title": "BBJ - Texto-Plano", "use_custom_frame_title": False, "max_text_width": 80, "confirm_anon": True, @@ -237,9 +321,10 @@ default_prefs = { } bars = { - "index": "[RET]Open [/]Search [C]ompose [R]efresh [*]Bookmark [O]ptions [?]Help [Q]uit", - "thread": "[Q]Back [RET]Menu [C]ompose [^R]eply [R]efresh [0-9]Goto [B/T]End []Jump[X]%d [/]Search", - "edit_window": "[{}]Abort [{}]Swap [{}]Formatting Help [save/quit to send] {}" + + "index": "[RET]Abrir [/]Buscar Es[C]ribir [R]efres. [*]Marc. [O]pciones [?]Ayuda [Q]uitar", + "thread": "[Q]Atrás [RET]Menú Es[C]ribir [^R]esponder [R]efrescar [0-9]Ir [T/B]Inicio/Fin [<>]Saltar[X]%d [/]Buscar", + "edit_window": "[{}]Abortar [{}]Cambiar [{}]Ayuda formato [guardar/quitar para enviar] {}" } colormap = [ @@ -343,8 +428,8 @@ class App(object): if isinstance(self.prefs["custom_divider_char"], str): self.theme["divider"] = self.prefs["custom_divider_char"] except KeyError: - exit("Selected theme does not exist. Please check " - "the `frame_theme` value in ~/.bbjrc") + exit("El tema elegido no existe. Por favor revisa " + "el valor `frame_theme` en ~/.bbjrc") self.mode = None self.thread = None @@ -414,7 +499,7 @@ class App(object): name = self.usermap[self.thread["author"]]["user_name"] self.set_header("~{}: {}", name, self.thread["title"]) else: - self.set_header("{} threads", len(self.walker)) + self.set_header("{} hilos", len(self.walker)) def set_default_footer(self, clobber_composer=False): @@ -427,7 +512,7 @@ class App(object): elif self.mode == "thread": footer = bars["thread"] % self.prefs["jump_count"] if self.match_data["matches"]: - footer += " [@#] Search Control" + footer += " [@#] Control Búsq." else: footer = bars["index"] @@ -489,11 +574,11 @@ class App(object): elif pos == "body": self.loop.widget.focus_position = "footer" - focus = "[focused on editor]" + focus = "[enfocado en editor]" else: self.loop.widget.focus_position = "body" - focus = "[focused on thread]" + focus = "[enfocado en hilo]" attr.reverse() self.loop.widget.footer[0].set_text( @@ -522,13 +607,13 @@ class App(object): if hours > 48: return self.timestring(modified) elif hours > 1: - return "%d hours ago" % hours + return "hace %d horas" % hours elif hours == 1: - return "about an hour ago" + return "hace una hora" minutes, remainder = divmod(remainder, 60) if minutes > 1: - return "%d minutes ago" % minutes - return "less than a minute ago" + return "hace %d minutos" % minutes + return "hace menos de un minuto" def quote_view_action(self, button, message): @@ -575,7 +660,7 @@ class App(object): widget = OptionsMenu( urwid.ListBox(urwid.SimpleFocusListWalker(buttons)), - **self.frame_theme("View a Quote") + **self.frame_theme("Ver una Cita") ) self.loop.widget = urwid.Overlay( @@ -613,9 +698,9 @@ class App(object): """ op = message["post_id"] == 0 buttons = [ - urwid.Text(("bold", "Delete this %s?" % ("whole thread" if op else "post"))), + urwid.Text(("bold", "¿Borrar %s?" % ("hilo entero" if op else "post"))), urwid.Divider(), - cute_button(("10" , ">> Yes"), lambda _: [ + cute_button(("10" , ">> Sí"), lambda _: [ network.message_delete(message["thread_id"], message["post_id"]), self.remove_overlays(), self.index() if op else self.refresh() @@ -648,28 +733,28 @@ class App(object): buttons = [] if not self.window_split: - buttons.append(urwid.Button("Reply", self.reply, message)) + buttons.append(urwid.Button("Responder", self.reply, message)) if quotes and message["post_id"] != 0: buttons.append(urwid.Button( - "View %sQuote" % ("a " if len(quotes) != 1 else ""), + "Ver %sCita" % ("a " if len(quotes) != 1 else ""), self.quote_view_menu, quotes)) if network.can_edit(message["thread_id"], message["post_id"]) \ and not self.window_split: if message["post_id"] == 0: - msg = "Thread" + msg = "Hilo" else: msg = "Post" raw = message["send_raw"] - buttons.insert(0, urwid.Button("Delete %s" % msg, self.deletion_dialog, message)) + buttons.insert(0, urwid.Button("Borrar %s" % msg, self.deletion_dialog, message)) buttons.insert(0, urwid.Button( - "Enable Formatting" if raw else "Disable Formatting", + "Activar formateado" if raw else "Desactivar formateado", self.toggle_formatting, message)) - buttons.insert(0, urwid.Button("Edit Post", self.edit_post, message)) + buttons.insert(0, urwid.Button("Editar Post", self.edit_post, message)) if network.user["is_admin"]: - buttons.insert(0, urwid.Text(("20", "Reminder: You're an admin!"))) + buttons.insert(0, urwid.Text(("20", "Recordatorio: ¡eres admin!"))) if not buttons: return @@ -711,19 +796,19 @@ class App(object): """ button = cute_button(">>", self.thread_load, thread["thread_id"]) if pinned == "server": - title = urwid.AttrWrap(urwid.Text("[STICKY] " + thread["title"]), "20") + title = urwid.AttrWrap(urwid.Text("[FIJADO] " + thread["title"]), "20") elif pinned == "client": title = urwid.AttrWrap(urwid.Text("[*] " + thread["title"]), "50") else: title = urwid.Text(thread["title"]) user = self.usermap[thread["author"]] dateline = [ - ("default", "by "), + ("default", "por "), (str(user["color"]), "~%s " % user["user_name"]), ("dim", "@ %s" % self.timestring(thread["created"])) ] - infoline = "%d replies; active %s" % ( + infoline = "%d respuestas; activo %s" % ( thread["reply_count"], self.timestring(thread["last_mod"], "delta")) @@ -733,7 +818,7 @@ class App(object): urwid.Text(dateline), urwid.Text(("dim", infoline)), urwid.Text([ - ("dim", "last post by "), + ("dim", "último post por "), (str(last_author["color"]), "~" + last_author["user_name"]) ]), urwid.AttrMap(urwid.Divider(self.theme["divider"]), "dim") @@ -760,7 +845,7 @@ class App(object): if no_action: callback = ignore - name = urwid_rainbows("~SYSTEM", True) + name = urwid_rainbows("~SISTEMA", True) color = "0" else: callback = self.on_post @@ -906,9 +991,9 @@ class App(object): if results: self.index(threads=results) if query: - self.set_header("Searching for '{}'", query) + self.set_header("Buscando '{}'", query) else: - self.temp_footer_message("No results for '{}'".format(query)) + self.temp_footer_message("No se encontró nada para '{}'".format(query)) def search_thread_callback(self, query): @@ -925,7 +1010,7 @@ class App(object): # self.highlight_query() self.do_search_result() else: - self.temp_footer_message("No results for '{}'".format(query)) + self.temp_footer_message("No se encontró nada para '{}'".format(query)) def do_search_result(self, forward=True): @@ -941,7 +1026,7 @@ class App(object): self.match_data["position"] = length - 1 self.goto_post(self.match_data["matches"][self.match_data["position"]]["post_id"]) self.temp_footer_message( - "({}/{}) Searching for {} [#]Next [@]Previous".format( + "({}/{}) Buscando para {} [#]Siguiente [@]Anterior".format( self.match_data["position"] + 1, length, self.match_data["query"] ), 5) @@ -979,9 +1064,9 @@ class App(object): popup = OptionsMenu( urwid.ListBox( urwid.SimpleFocusListWalker([ - urwid.Text(("button", "Enter a query:")), + urwid.Text(("button", "Ingresa pedido:")), urwid.AttrMap(StringPrompt(callback), "opt_prompt"), - urwid.Text("Use a blank query to reset the {}.".format(self.mode)) + urwid.Text("Pon un pedido en blanco para reiniciar el {}.".format(self.mode)) ])), **self.frame_theme()) @@ -1004,7 +1089,7 @@ class App(object): thread = self.thread["thread_id"] self.thread_load(None, thread) self.goto_post(mark(thread)) - self.temp_footer_message("Refreshed content!", 1) + self.temp_footer_message("¡Fresco como una lechuga!", 1) def back(self, terminate=False): @@ -1017,9 +1102,9 @@ class App(object): elif self.window_split: # display a confirmation dialog before killing off an in-progress post buttons = [ - urwid.Text(("bold", "Discard current post?")), + urwid.Text(("bold", "¿Descartar post actual?")), urwid.Divider(), - cute_button(("10" , ">> Yes"), lambda _: [ + cute_button(("10" , ">> Sí"), lambda _: [ self.remove_overlays(), self.index() ]), @@ -1082,7 +1167,7 @@ class App(object): size, new_pos, coming_from= "below" if (cur_pos < new_pos) else "above") except IndexError: - self.temp_footer_message("OUT OF BOUNDS") + self.temp_footer_message("FUERA DE LÍMITES") def goto_post_prompt(self, init): @@ -1093,9 +1178,9 @@ class App(object): live_display = urwid.Text("") edit = JumpPrompt(count, lambda x: self.goto_post(x)) items = [ - urwid.Text(("button", " Jump to post")), + urwid.Text(("button", " Ir al post")), urwid.AttrMap(edit, "opt_prompt"), - urwid.Text(("bold", ("(max %d)" % count).center(18, " "))), + urwid.Text(("bold", ("(máx. %d)" % count).center(18, " "))), live_display ] @@ -1205,11 +1290,11 @@ class App(object): urwid.ListBox( urwid.SimpleFocusListWalker([ urwid_rainbows( - "This is BBJ, a client/server textboard made for tildes!", + "Esto es BBJ, ¡un tablón de texto cliente/servidor para tildes!", True), urwid.Text(("dim", "...by ~desvox")), urwid.Divider(self.theme["divider"]), - urwid.Button("Post Formatting Help", self.formatting_help), + urwid.Button("Ayuda de Formateo de Post", self.formatting_help), urwid.Divider(self.theme["divider"]), urwid.Text(general_help) ])), @@ -1236,7 +1321,7 @@ class App(object): widget = OptionsMenu( urwid.ListBox(urwid.SimpleFocusListWalker(app.make_message_body(message, True))), - **self.frame_theme("Formatting Help") + **self.frame_theme("Ayuda de Formateo") ) va = 5 if self.window_split else 50 @@ -1282,9 +1367,9 @@ class App(object): self.loop.stop() call("clear", shell=True) try: - name = nameloop("Choose a new username", True) + name = nameloop("Elige un nuevo nombre de usuario", True) network.user_update(user_name=name) - motherfucking_rainbows("~~hello there %s~~" % name) + motherfucking_rainbows("~~qué tal, %s~~" % name) sleep(0.8) self.loop.start() self.loop.widget = self.loop.widget[0] @@ -1298,9 +1383,9 @@ class App(object): self.loop.stop() call("clear", shell=True) try: - password = password_loop("Choose a new password. Can be empty", True) + password = password_loop("Elige una nueva clave. Puede estar vacía", True) network.user_update(auth_hash=network._hash(password)) - motherfucking_rainbows("SET NEW PASSWORD") + motherfucking_rainbows("ELIGE NUEVA CLAVE") sleep(0.8) self.loop.start() self.loop.widget = self.loop.widget[0] @@ -1317,7 +1402,7 @@ class App(object): self.prefs[key] = text bbjrc("update", **self.prefs) except: - rendered = ("1", "Invalid Input") + rendered = ("1", "Entrada Inválida") widget.set_text(rendered) @@ -1343,13 +1428,13 @@ class App(object): mode = args[0] widget = OptionsMenu( urwid.ListBox(urwid.SimpleFocusListWalker([ - urwid.Text("Press Enter when done"), + urwid.Text("Presiona Enter cuando termines"), urwid.AttrMap(KeyPrompt( self.prefs["edit_escapes"][mode], self.save_escape_key, [mode] ), "opt_prompt")])), - **self.frame_theme("Set key for " + mode) + **self.frame_theme("Elige tecla para " + mode) ) app.loop.widget = urwid.Overlay( @@ -1396,16 +1481,16 @@ class App(object): edit_mode = [] if network.user_auth: - account_message = "Logged in as %s." % network.user_name + account_message = "Sesión iniciada como %s." % network.user_name account_stuff = [ - urwid.Button("Relog", on_press=self.relog), - urwid.Button("Go anonymous", on_press=self.unlog), - urwid.Button("Change username", on_press=self.change_username), - urwid.Button("Change password", on_press=self.change_password), + urwid.Button("Cerrar sesión", on_press=self.relog), + urwid.Button("Volverse anónimo", on_press=self.unlog), + urwid.Button("Editar nombre de usuario", on_press=self.change_username), + urwid.Button("Editar clave", on_press=self.change_password), urwid.Divider(), - urwid.Text(("button", "Your color:")), - urwid.Text(("default", "This color will show on your " - "post headers and when people quote you.")), + urwid.Text(("button", "Tu color:")), + urwid.Text(("default", "Este color se mostrará en tus " + "cabeceras de post y cuando te citen.")), urwid.Divider() ] @@ -1420,8 +1505,8 @@ class App(object): account_stuff.append(item) else: - account_message = "You're browsing anonymously, and cannot set account preferences." - account_stuff = [urwid.Button("Login/Register", on_press=self.relog)] + account_message = "Estás navegando anónimamente, no puedes cambiar opciones de cuenta." + account_stuff = [urwid.Button("Ingresar/Registrarse", on_press=self.relog)] theme_buttons = [] for name, theme in themes.items(): @@ -1440,10 +1525,10 @@ class App(object): urwid.connect_signal(date_edit, "change", self.live_time_render, (date_box, "date")) time_stuff = [ - urwid.Text(("button", "Time Format")), + urwid.Text(("button", "Formato de Tiempo")), time_box, urwid.AttrMap(time_edit, "opt_prompt"), urwid.Divider(), - urwid.Text(("button", "Date Format")), + urwid.Text(("button", "Formato de Fecha")), date_box, urwid.AttrMap(date_edit, "opt_prompt"), ] @@ -1463,17 +1548,17 @@ class App(object): user_data=(editor, editor_display)) urwid.RadioButton( - edit_mode, "Integrate", + edit_mode, "Integrar", state=self.prefs["integrate_external_editor"], on_state_change=self.set_editor_mode) urwid.RadioButton( - edit_mode, "Overthrow", + edit_mode, "Sobreponer", state=not self.prefs["integrate_external_editor"]) content = [] - for item in [urwid.Text(("opt_header", "Account"), 'center'), + for item in [urwid.Text(("opt_header", "Cuenta"), 'center'), urwid.Text(account_message), urwid.Divider()]: content.append(item) @@ -1482,33 +1567,33 @@ class App(object): content.append(item) for item in [urwid.Divider(self.theme["divider"]), - urwid.Text(("opt_header", "App"), 'center'), + urwid.Text(("opt_header", "Aplicación"), 'center'), urwid.Divider(), urwid.CheckBox( - "Dump rainbows on exit", + "Tirar arcoiris al salir", state=self.prefs["dramatic_exit"], on_state_change=self.toggle_exit ), urwid.CheckBox( - "Warn when posting anonymously", + "Advertir cuando se postea anónimamente", state=self.prefs["confirm_anon"], on_state_change=self.toggle_anon_warn ), urwid.CheckBox( - "Increase index padding", + "Aumentar espaciado del índice", state=self.prefs["index_spacing"], on_state_change=self.toggle_spacing ), urwid.CheckBox( - "Handle mouse (disrupts URL clicking)", + "Usar ratón (perturba cliquear URLs)", state=self.prefs["mouse_integration"], on_state_change=self.toggle_mouse ), urwid.Divider()]: content.append(item) - for item in [urwid.Text(("button", "Border Theme")), - urwid.Text("Restart to fully apply.")]: + for item in [urwid.Text(("button", "Tema de Borde")), + urwid.Text("Reinicia para aplicar completamente.")]: content.append(item) for item in theme_buttons: @@ -1520,14 +1605,14 @@ class App(object): content.append(item) for item in [urwid.Divider(), - urwid.Text(("button", "Max message width:")), + urwid.Text(("button", "Ancho máximo de mensaje:")), urwid.AttrMap(width_edit, "opt_prompt"), urwid.Divider(), - urwid.Text(("button", "Scroll multiplier when holding shift or scrolling with the mouse:")), + urwid.Text(("button", "Multiplicador de despl. cuando se aprieta shift o se mueve con mouse:")), urwid.AttrMap(shift_edit, "opt_prompt"), urwid.Divider(), - urwid.Text(("button", "Text editor:")), - urwid.Text("You can type in your own command or use one of these presets."), + urwid.Text(("button", "Editor de texto:")), + urwid.Text("Puedes poner tu propio comando o usar alguno de éstos predefinidos."), urwid.Divider(), urwid.AttrMap(editor_display, "opt_prompt")]: content.append(item) @@ -1536,20 +1621,20 @@ class App(object): content.append(item) for item in [urwid.Divider(), - urwid.Text(("button", "Internal Editor Escape Keys:")), - urwid.Text("You can change these keybinds to whatever " - "you want. Just remember that these will " - "shadow over the text editor itself."), + urwid.Text(("button", "Teclas de escape del Editor Interno:")), + urwid.Text("Puedes cambiarlas a cualquiera que " + "prefieras. Solo recuerda que se aplicarán " + "encima del programa de edición de texto."), urwid.Divider(), - urwid.Button("Abort", self.set_escape_key, ["abort"]), - urwid.Button("Change Focus", self.set_escape_key, ["focus"]), - urwid.Button("Formatting Help", self.set_escape_key, ["fhelp"])]: + urwid.Button("Abortar", self.set_escape_key, ["abort"]), + urwid.Button("Cambiar Foco", self.set_escape_key, ["focus"]), + urwid.Button("Ayuda de Formateo", self.set_escape_key, ["fhelp"])]: content.append(item) for item in [urwid.Divider(), - urwid.Text(("button", "External text editor mode:")), - urwid.Text("If you have problems using an external text editor, " - "set this to Overthrow."), + urwid.Text(("button", "Modo de editor de texto externo:")), + urwid.Text("Si tienes problemas usando un editor de texto externo, " + "elige Sobreponer."), urwid.Divider()]: content.append(item) @@ -1560,7 +1645,7 @@ class App(object): widget = OptionsMenu( urwid.ListBox(urwid.SimpleFocusListWalker(content)), - **self.frame_theme("Options")) + **self.frame_theme("Opciones")) self.loop.widget = urwid.Overlay( widget, self.loop.widget, @@ -1618,7 +1703,7 @@ class App(object): descriptor, path = tempfile.mkstemp() with open(path, "w") as _: _.write(init_body) - call("export LANG=en_US.UTF-8; %s %s" % (self.prefs["editor"], path), shell=True) + call("export LANG=es_ES.UTF-8; %s %s" % (self.prefs["editor"], path), shell=True) with open(path) as _: body = _.read() os.remove(path) @@ -1632,18 +1717,18 @@ class App(object): context and user preferences. """ if self.mode == "index" and not title: - return self.footer_prompt("Title", self.compose) + return self.footer_prompt("Título", self.compose) elif title: try: network.validate("title", title) except AssertionError as e: return self.footer_prompt( - "Title", self.compose, extra_text=e.description) + "Título", self.compose, extra_text=e.description) if not self.prefs["integrate_external_editor"]: body = self.overthrow_ext_edit(init_body) if not body or re.search("^>>[0-9]+$", body): - return self.temp_footer_message("EMPTY POST DISCARDED") + return self.temp_footer_message("POST VACÍO DESCARTADO") params = {"body": body} if self.mode == "thread" and not edit: @@ -1674,8 +1759,8 @@ class App(object): return if self.mode == "index": - self.set_header('Composing "{}"', title) - self.set_footer("[{}]Abort [{}]Formatting Help [Save and quit to submit your thread]".format( + self.set_header('Escribiendo "{}"', title) + self.set_footer("[{}]Abortar [{}]Ayuda de Formateo [Guarda y sal para publicar el hilo]".format( self.prefs["edit_escapes"]["abort"].upper(), self.prefs["edit_escapes"]["fhelp"].upper() )) self.loop.widget = urwid.Overlay( @@ -1977,7 +2062,7 @@ class ExternalEditor(urwid.Terminal): # behalf. Users who take issue to programs trying to supress unicode # should use the options menu to switch to Overthrow mode. env.update({"LANG": "POSIX"}) - command = ["bash", "-c", "{} {}; echo Press any key to kill this window...".format( + command = ["bash", "-c", "{} {}; echo Presione cualquier tecla para matar esta ventana...".format( app.prefs["editor"], self.path)] super(ExternalEditor, self).__init__(command, env, app.loop, app.prefs["edit_escapes"]["abort"]) urwid.connect_signal(self, "closed", self.exterminate) @@ -2027,7 +2112,7 @@ class ExternalEditor(urwid.Terminal): call("clear", shell=True) print(anon_warn) choice = paren_prompt( - "Publicar anónimamente?", default="si", choices=["Sí", "no"] + "¿Publicar anónimamente?", default="s", choices=["s", "n"] ) if choice == "n": log_in(True) @@ -2464,9 +2549,9 @@ def log_in(relog=False): elif response == "n": raise InterruptedError - password = password_loop("Enter a password. It can be empty if you want") + password = password_loop("Ingresa una clave. Puede estar vacía si quieres") network.user_register(name, password) - motherfucking_rainbows("~~welcome to the party, %s!~~" % network.user_name) + motherfucking_rainbows("~~¡bienvenido a la fiesta, %s!~~" % network.user_name) sleep(0.5) # let that confirmation message shine diff --git a/python.patch b/python.patch new file mode 100644 index 0000000..1ca451b --- /dev/null +++ b/python.patch @@ -0,0 +1,893 @@ +--- + clients/urwid/main.py | 473 +++++++++++++++++++++++++----------------- + 1 file changed, 279 insertions(+), 194 deletions(-) + +diff --git a/clients/urwid/main.py b/clients/urwid/main.py +index 3adeeff..a8a5e57 100644 +--- a/clients/urwid/main.py ++++ b/clients/urwid/main.py +@@ -87,7 +87,7 @@ obnoxious_logo = """ + 8 888888888P 8 888888888P `Y888888 ' . + % %""" + +-welcome = """>>> Bienvenido al BBS de Texto-Plano! ------------------@ ++welcome = """>>> -------- Bienvenido al BBS de Texto-Plano! -----------@ + | BBJ es un muro de discusión persistente y ordenado | + | temporalmente para tildes. Puedes ingresar | + | registrar un usuario nuevo, or participar anónimamente | +@@ -97,7 +97,7 @@ welcome = """>>> Bienvenido al BBS de Texto-Plano! ------------------@ + @_________________________________________________________@ + """ + +-anon_warn = """>>> \033[1;31mSolo un recordatorio!\033[0m ----------------------------------@ ++anon_warn = """>>> \033[1;31m¡Solo un recordatorio!\033[0m ----------------------------@ + | No estás logueado en BBJ, y estás posteando | + | tu mensaje anónimamente. Si no ingresas con usuario | + | no podrás borrar o editar este mensaje | +@@ -106,102 +106,186 @@ anon_warn = """>>> \033[1;31mSolo un recordatorio!\033[0m ---------------------- + """ + + format_help = [ +- "Quick reminder: \[rainbow: expressions work like this]. You may scroll " +- "this message, or press Q or escape to close it.\n\n" +- +- "BBJ supports **bolding**, __underlining__, and [rainbow: coloring] text " +- "using markdown-style symbols as well as tag-like expressions. Markdown " +- "is **NOT** fully implemented, but several of the more obvious concepts " +- "have been brought over. Additionally, we have chan-style greentext and " +- "numeric post referencing, ala >>3 for the third reply.", +- +- "[red: Whitespace]", +- +- "When you're composing, it is desirable to not include your own linebreaks " +- "into paragraphs of your post, because clients handle text wrapping on their " +- "own. Adding them yourself can cause your posts to look very strange. You can " +- "always edit your posts after submitting them if you do this by accident, as " +- "long as you are not anonymous.", +- +- "In previous versions of BBJ, linebreaks were joined into sentences if they " +- "occured in the same paragraph, however this confused many users and has been " +- "reverted to just use whatever was submitted, as-is.", +- +- +- "[red: Colors, Bold, Underline & Expressions]", +- +- "You can use [rainbow: rainbow], [red: red], [yellow: yellow], [green: green], " +- "[blue: blue], [cyan: cyan], [magenta: and magenta], [dim: dim], **bold**, and __underline__ " +- "inside of your posts. \**bold works like this\**, \__and underlines like this\__. " +- "You can escape these expressions \\\**like this\\\**. They can span up to the full width " +- "of the same line. They are best used on shorter phrases. " +- "However, you can use a different syntax for it, which is also required to use " +- "colors: these expressions \[bold: look like this] and have less restrictions.", +- +- "The colon and the space following it are important. When you use these " +- "expressions, the __first__ space is not part of the content, but any characters, " +- "including spaces, that follow it are included in the body. The formatting will " +- "apply until the closing ]. You can escape such an expression \\\[cyan: like this] " +- "and can also \\[blue: escape \\\] other closing brackets] inside of it. Only " +- "closing brackets need to be escaped within an expression. Any backslashes used " +- "for escaping will not show in the body unless you use two slashes.", +- +- "This peculiar syntax elimiates false positives. You never have to escape [normal] " +- "brackets when using the board. Only expressions with **valid and defined** directives " +- "will be affected. [so: this is totally valid and requires no escapes] because 'so' is " +- "not a directive. [red this will pass too] because the colon is missing.", +- +- "The following directives may be used in this form: red, yellow, green, blue, cyan, " +- "magenta, bold, underline, dim, and rainbow. Nesting expressions into eachother will " +- "override the parent directives until the innermost expression closes. Thus, nesting " +- "is valid but doesn't produce layered results on the command line client.", +- +- "[red: Quotes & Greentext]", +- +- "You can refer to a post number using two angle brackets pointing into a number. >>432 " +- "like this. You can color a whole line green by proceeding it with a '>'. Note that " +- "this violates the sentence structure outlined in the **Whitespace** section above, " +- "so you may introduce >greentext without splicing into seperate paragraphs. The '>' " +- "must be the first character on the line with no whitespace before it.\n>it looks like this\n" +- "and the paragraph doesnt have to break on either side. The formatter is smart enough to " +- "differentiate between >>greentext with multiple arrows and numeric quotes (outlined below) " +- "given that the text doesn't start with any numbers.", +- +- "When using numeric quotes, they are highlighted and the author's name will show " +- "next to them in the thread. You can press enter when focused on a message to view " +- "the parent posts. You may insert these directives manually or use the function " +- "on post menus.", +- +- "Quoting directives cannot be escaped." ++ "Recordatorio rápido: \[rainbow: las expresiones se ven así]. Puedes " ++ "desplazar este mensaje, o presionar Q o Escape para cerrarlo.\n\n" ++ ++# "Quick reminder: \[rainbow: expressions work like this]. You may scroll " ++# "this message, or press Q or escape to close it.\n\n" ++ ++ "BBJ soporta texto en **negrita**, __subrayado__ y [rainbow: coloreado] " ++ "usando símbolos a lo Markdown al igual que expresiones de " ++ "tipo tag. Markdown **NO** está implementado por completo, sin embargo " ++ "se adoptaron varios conceptos clave de allí. Adicionalmente, trajimos " ++ "de los chanes el texto verde y referencias numéricas, ej. >>3 para la " ++ "tercera respuesta.", ++ ++# "BBJ supports **bolding**, __underlining__, and [rainbow: coloring] text " ++# "using markdown-style symbols as well as tag-like expressions. Markdown " ++# "is **NOT** fully implemented, but several of the more obvious concepts " ++# "have been brought over. Additionally, we have chan-style greentext and " ++# "numeric post referencing, ala >>3 for the third reply.", ++ ++ "[red: Espaciado]", ++ ++# "[red: Whitespace]", ++ ++ "Cuando estás escribiendo, se desea no incluír tus propios saltos de " ++ "línea en los párrafos de tu post, porque los clientes manejan las " ++ "líneas de texto por su cuenta. Añadirlas tú mismo puede causar que tus " ++ "posts se vean muy extraños. Siempre puedes editar tus posts después de " ++ "publicarlos si haces esto por accidente, siempre y cuando no seas " ++ "anónimo.", ++ ++# "When you're composing, it is desirable to not include your own linebreaks " ++# "into paragraphs of your post, because clients handle text wrapping on their " ++# "own. Adding them yourself can cause your posts to look very strange. You can " ++# "always edit your posts after submitting them if you do this by accident, as " ++# "long as you are not anonymous.", ++ ++ "En versiones anteriores de BBJ, los saltos de línea se unían en " ++ "oraciones si estaban en el mismo párrafo, sin embargo esto confundió a " ++ "varios usuarios y ha sido revertido a publicar lo que sea que se haya " ++ "escrito, tal y como es.", ++ ++# "In previous versions of BBJ, linebreaks were joined into sentences if they " ++# "occured in the same paragraph, however this confused many users and has been " ++# "reverted to just use whatever was submitted, as-is.", ++ ++ "[red: Colores, Negrita, Subrayado y Expresiones]", ++ ++# "[red: Colors, Bold, Underline & Expressions]", ++ ++ "Puedes usar [rainbow: rainbow], [red: red], [yellow: " ++ "yellow], [green: green], [blue: blue], [cyan: " ++ "cyan] [magenta: y magenta], [dim: dim], **bold** y " ++ "__underline__ dentro de tus posts. \**bold se usa así\* " ++ "\__y underline así\__. Puedes escapar estas expresiones " ++ "\\\**así\\\**. Pueden abarcar hasta todo el ancho de la misma línea. " ++ "Funcionan mejor para frases más cortas. " ++ "Sin embargo, puedes usar una sintáxis distinta, que se utiliza también " ++ "para usar colores: estas expresiones \[bold: se ven así] y tienen menos " ++ "restricciones.", ++ ++# "You can use [rainbow: rainbow], [red: red], [yellow: yellow], [green: green], " ++# "[blue: blue], [cyan: cyan], [magenta: and magenta], [dim: dim], **bold**, and __underline__ " ++# "inside of your posts. \**bold works like this\**, \__and underlines like this\__. " ++# "You can escape these expressions \\\**like this\\\**. They can span up to the full width " ++# "of the same line. They are best used on shorter phrases. " ++# "However, you can use a different syntax for it, which is also required to use " ++# "colors: these expressions \[bold: look like this] and have less restrictions.", ++ ++ "Los dos puntos y el espacio siguiéndole son importantes. Cuando usas " ++ "estas expresiones, el __primer__ espacio no forma parte del contenido, " ++ "sino cualquier caracter, incluyendo espacios, que lo siguen, se " ++ "incluyen en el cuerpo. El formateo se aplicará hasta el ] final. Puedes " ++ "escaparla \\\[cyan: así], y también \\[blue: escapar \\\] otros " ++ "corchetes finales dentro de ella. Solo los corchetes finales se " ++ "necesitan escapar en una expresión. Cualquier barra diagonal inversa " ++ "que se use para escapar no se mostrará en el cuerpo a menos que uses " ++ "dos barras.", ++ ++# "The colon and the space following it are important. When you use these " ++# "expressions, the __first__ space is not part of the content, but any characters, " ++# "including spaces, that follow it are included in the body. The formatting will " ++# "apply until the closing ]. You can escape such an expression \\\[cyan: like this] " ++# "and can also \\[blue: escape \\\] other closing brackets] inside of it. Only " ++# "closing brackets need to be escaped within an expression. Any backslashes used " ++# "for escaping will not show in the body unless you use two slashes.", ++ ++ "Esta sintáxis peculiar elimina falsos positivos. Nunca tienes que " ++ "escapar corchetes [normales] cuando se usa el tablón. Solo las " ++ "expresiones con directivas **válidas y definidas** se ven afectadas. " ++ "[entonces: esto es totalmente válido y no requiere escapes] porque " ++ "'entonces' no es una directiva. [red esto también pasa de largo] porque faltan " ++ "los dos puntos.", ++ ++# "This peculiar syntax elimiates false positives. You never have to escape [normal] " ++# "brackets when using the board. Only expressions with **valid and defined** directives " ++# "will be affected. [so: this is totally valid and requires no escapes] because 'so' is " ++# "not a directive. [red this will pass too] because the colon is missing.", ++ ++ "Las siguientes directivas se pueden usar de esta forma: red, yellow, " ++ "green, blue, cyan, magenta, bold, underline, dim y rainbow. Las " ++ "expresiones que se anidan una adentro de la otra van a anular la " ++ "directiva padre hasta que la expresión de más adentro se cierre. Por " ++ "tanto, anidar es válido pero no produce resultados combinados en el " ++ "cliente de la línea de comandos.", ++ ++# "The following directives may be used in this form: red, yellow, green, blue, cyan, " ++# "magenta, bold, underline, dim, and rainbow. Nesting expressions into eachother will " ++# "override the parent directives until the innermost expression closes. Thus, nesting " ++# "is valid but doesn't produce layered results on the command line client.", ++ ++ "[red: Citas y Texto verde]", ++ ++# "[red: Quotes & Greentext]", ++ ++ "Puedes referirte al número de un post usando dos flechas 'mayor que' " ++ "apuntando a un número. >>432 como esto. Puedes colorear una línea " ++ "entera de verde precediéndola con un '>'. Nótese que esto viola la " ++ "estructura de oración en la sección **Espaciado** mencionada " ++ "anteriormente, por lo que podrías introducir >texto verde sin " ++ "escribirlo en párrafos separados. El '>' debe ser el primer caracter en " ++ "la línea, sin espacios antes de él.\n>se ve como esto\n" ++ "y el párrafo no tiene que romperse en ningún lado. El formateador es " ++ "suficientemente inteligente para diferenciar entre >>texto verde con " ++ "múltiples flechas y citas numéricas (mencionadas más abajo) dado que el " ++ "texto no comienza con ningún número.", ++ ++# "You can refer to a post number using two angle brackets pointing into a number. >>432 " ++# "like this. You can color a whole line green by proceeding it with a '>'. Note that " ++# "this violates the sentence structure outlined in the **Whitespace** section above, " ++# "so you may introduce >greentext without splicing into seperate paragraphs. The '>' " ++# "must be the first character on the line with no whitespace before it.\n>it looks like this\n" ++# "and the paragraph doesnt have to break on either side. The formatter is smart enough to " ++# "differentiate between >>greentext with multiple arrows and numeric quotes (outlined below) " ++# "given that the text doesn't start with any numbers.", ++ ++ "Cuando se usan citas numéricas, éstas se resaltan y el nombre del autor " ++ "se mostrará al lado de ellas en el hilo. Puedes presionar Enter cuando " ++ "se está enfocado en un mensaje para ver los posts padre. Puedes " ++ "insertar estas directivas manualmente o usar la función en " ++ "los menúes del post.", ++ ++# "When using numeric quotes, they are highlighted and the author's name will show " ++# "next to them in the thread. You can press enter when focused on a message to view " ++# "the parent posts. You may insert these directives manually or use the function " ++# "on post menus.", ++ ++ "Las directivas de citado no se pueden escapar." ++# "Quoting directives cannot be escaped." + ] + + general_help = [ +- ("bold", "use the arrow keys, j/k, or n/p to scroll down this menu\n\n"), +- ("bold", "use q or escape to close dialogs and menus (including this one)\n\n"), +- ("10", "use q, escape, or a left directional key to go back at any point" +- " from just about anywhere.\n\n"), +- ("20", "use the o key to change your settings when this dialog is closed\n\n"), +- +- "You may use the arrow keys, or use ", ("button", "jk/np/Control-n|p"), +- " to move up and down by " +- "an element. If an element is overflowing the screen, it will scroll only one line. " +- "To make scrolling faster, ", ("button", "hold shift"), " when using a control: it " +- "will repeat 5 times by default, and you can change this number in your settings.\n\n" +- +- "In threads, The ", ("button", "<"), " and ", ("button", ">"), " keys will jump by " +- "a chosen number of post headers. You can see the count inside of the footer line at " +- "the far right side: press ", ("button", "x"), " to cycle it upwards or ", +- ("button", "X"), " to cycle it downwards.\n\n" +- +- "In the thread index and any open thread, the ", ("button", "b"), " and ", ("button", "t "), +- "keys may be used to go to very top or bottom.\n\n" +- +- "To go back and forth between threads, you may also use the left/right arrow keys, " +- "or ", ("button", "h"), "/", ("button", "l"), " to do it vi-style.\n\n" +- +- "Aside from those, primary controls are shown on the very bottom of the screen " +- "in the footer line, or may be placed in window titles for other actions like " +- "dialogs or composers." ++ ("bold", "usa las flechas, j/k o n/p para desplazar este menú\n\n"), ++ ("bold", "usa q o escape para cerrar diálogos y menúes (incluyendo éste)\n\n"), ++ ("10", "usa q, escape o una flecha izquierda para volver a cualquier punto" ++ " desde cualquier lado.\n\n"), ++ ("20", "usa la tecla o para cambiar tus opciones cuando este diálogo esté cerrado\n\n"), ++ ++ "Puedes usar las flechas, o usar ", ("button", "jk/np/Control-n|p"), ++ " para moverte arriba y abajo por " ++ "cada elemento. Si un elemento excede la pantalla, se moverá solo una línea. " ++ ++ "Para moverte más rápido, ", ("button", "mantén presionado shift "), ++ "cuando uses un control: ", ++ ++ "por defecto se repetirá 5 veces, y puedes cambiar este número en tus opciones.\n\n" ++ ++ "En hilos, las teclas ", ("button", "<"), " y ", ("button", ">"), " saltan un " ++ "elegido número de cabeceras de post. Puedes ver la cuenta dentro del pie de pantalla en " ++ "la línea de abajo: presiona ", ("button", "x"), " para aumentarlo o ", ++ ("button", "X"), " para bajarlo.\n\n" ++ ++ "En el índice de hilos y en cualquier hilo abierto, las teclas ", ("button", "t"), " y ", ("button", "b "), ++ "se pueden usar para ir al inicio o al fin del contenido.\n\n" ++ ++ "Para ir y volver entre hilos, también puedes usar las teclas izquierda/derecha, " ++ "o ", ("button", "h"), "/", ("button", "l"), " para hacerlo al estilo vi.\n\n" ++ ++ "Fuera de ellos, los controles primarios se muestran en la parte baja en " ++ "el pie de la pantalla, o también se colocan en títulos de ventana para " ++ "otras acciones como diálogos o compositores." + ] + + colors = [ +@@ -221,11 +305,11 @@ default_prefs = { + "integrate_external_editor": True, + "index_spacing": False, + "dramatic_exit": True, +- "date": "%Y/%m/%d", ++ "date": "%d/%m/%Y", + "time": "%H:%M", + "frame_theme": "tilde", + "custom_divider_char": False, +- "frame_title": "BBJ", ++ "frame_title": "BBJ - Texto-Plano", + "use_custom_frame_title": False, + "max_text_width": 80, + "confirm_anon": True, +@@ -237,9 +321,10 @@ default_prefs = { + } + + bars = { +- "index": "[RET]Open [/]Search [C]ompose [R]efresh [*]Bookmark [O]ptions [?]Help [Q]uit", +- "thread": "[Q]Back [RET]Menu [C]ompose [^R]eply [R]efresh [0-9]Goto [B/T]End []Jump[X]%d [/]Search", +- "edit_window": "[{}]Abort [{}]Swap [{}]Formatting Help [save/quit to send] {}" ++ ++ "index": "[RET]Abrir [/]Buscar Es[C]ribir [R]efres. [*]Marc. [O]pciones [?]Ayuda [Q]uitar", ++ "thread": "[Q]Atrás [RET]Menú Es[C]ribir [^R]esponder [R]efrescar [0-9]Ir [T/B]Inicio/Fin [<>]Saltar[X]%d [/]Buscar", ++ "edit_window": "[{}]Abortar [{}]Cambiar [{}]Ayuda formato [guardar/quitar para enviar] {}" + } + + colormap = [ +@@ -343,8 +428,8 @@ class App(object): + if isinstance(self.prefs["custom_divider_char"], str): + self.theme["divider"] = self.prefs["custom_divider_char"] + except KeyError: +- exit("Selected theme does not exist. Please check " +- "the `frame_theme` value in ~/.bbjrc") ++ exit("El tema elegido no existe. Por favor revisa " ++ "el valor `frame_theme` en ~/.bbjrc") + + self.mode = None + self.thread = None +@@ -414,7 +499,7 @@ class App(object): + name = self.usermap[self.thread["author"]]["user_name"] + self.set_header("~{}: {}", name, self.thread["title"]) + else: +- self.set_header("{} threads", len(self.walker)) ++ self.set_header("{} hilos", len(self.walker)) + + + def set_default_footer(self, clobber_composer=False): +@@ -427,7 +512,7 @@ class App(object): + elif self.mode == "thread": + footer = bars["thread"] % self.prefs["jump_count"] + if self.match_data["matches"]: +- footer += " [@#] Search Control" ++ footer += " [@#] Control Búsq." + + else: + footer = bars["index"] +@@ -489,11 +574,11 @@ class App(object): + + elif pos == "body": + self.loop.widget.focus_position = "footer" +- focus = "[focused on editor]" ++ focus = "[enfocado en editor]" + + else: + self.loop.widget.focus_position = "body" +- focus = "[focused on thread]" ++ focus = "[enfocado en hilo]" + attr.reverse() + + self.loop.widget.footer[0].set_text( +@@ -522,13 +607,13 @@ class App(object): + if hours > 48: + return self.timestring(modified) + elif hours > 1: +- return "%d hours ago" % hours ++ return "hace %d horas" % hours + elif hours == 1: +- return "about an hour ago" ++ return "hace una hora" + minutes, remainder = divmod(remainder, 60) + if minutes > 1: +- return "%d minutes ago" % minutes +- return "less than a minute ago" ++ return "hace %d minutos" % minutes ++ return "hace menos de un minuto" + + + def quote_view_action(self, button, message): +@@ -575,7 +660,7 @@ class App(object): + + widget = OptionsMenu( + urwid.ListBox(urwid.SimpleFocusListWalker(buttons)), +- **self.frame_theme("View a Quote") ++ **self.frame_theme("Ver una Cita") + ) + + self.loop.widget = urwid.Overlay( +@@ -613,9 +698,9 @@ class App(object): + """ + op = message["post_id"] == 0 + buttons = [ +- urwid.Text(("bold", "Delete this %s?" % ("whole thread" if op else "post"))), ++ urwid.Text(("bold", "¿Borrar %s?" % ("hilo entero" if op else "post"))), + urwid.Divider(), +- cute_button(("10" , ">> Yes"), lambda _: [ ++ cute_button(("10" , ">> Sí"), lambda _: [ + network.message_delete(message["thread_id"], message["post_id"]), + self.remove_overlays(), + self.index() if op else self.refresh() +@@ -648,28 +733,28 @@ class App(object): + buttons = [] + + if not self.window_split: +- buttons.append(urwid.Button("Reply", self.reply, message)) ++ buttons.append(urwid.Button("Responder", self.reply, message)) + + if quotes and message["post_id"] != 0: + buttons.append(urwid.Button( +- "View %sQuote" % ("a " if len(quotes) != 1 else ""), ++ "Ver %sCita" % ("a " if len(quotes) != 1 else ""), + self.quote_view_menu, quotes)) + + if network.can_edit(message["thread_id"], message["post_id"]) \ + and not self.window_split: + + if message["post_id"] == 0: +- msg = "Thread" ++ msg = "Hilo" + else: msg = "Post" + + raw = message["send_raw"] +- buttons.insert(0, urwid.Button("Delete %s" % msg, self.deletion_dialog, message)) ++ buttons.insert(0, urwid.Button("Borrar %s" % msg, self.deletion_dialog, message)) + buttons.insert(0, urwid.Button( +- "Enable Formatting" if raw else "Disable Formatting", ++ "Activar formateado" if raw else "Desactivar formateado", + self.toggle_formatting, message)) +- buttons.insert(0, urwid.Button("Edit Post", self.edit_post, message)) ++ buttons.insert(0, urwid.Button("Editar Post", self.edit_post, message)) + if network.user["is_admin"]: +- buttons.insert(0, urwid.Text(("20", "Reminder: You're an admin!"))) ++ buttons.insert(0, urwid.Text(("20", "Recordatorio: ¡eres admin!"))) + + if not buttons: + return +@@ -711,19 +796,19 @@ class App(object): + """ + button = cute_button(">>", self.thread_load, thread["thread_id"]) + if pinned == "server": +- title = urwid.AttrWrap(urwid.Text("[STICKY] " + thread["title"]), "20") ++ title = urwid.AttrWrap(urwid.Text("[FIJADO] " + thread["title"]), "20") + elif pinned == "client": + title = urwid.AttrWrap(urwid.Text("[*] " + thread["title"]), "50") + else: + title = urwid.Text(thread["title"]) + user = self.usermap[thread["author"]] + dateline = [ +- ("default", "by "), ++ ("default", "por "), + (str(user["color"]), "~%s " % user["user_name"]), + ("dim", "@ %s" % self.timestring(thread["created"])) + ] + +- infoline = "%d replies; active %s" % ( ++ infoline = "%d respuestas; activo %s" % ( + thread["reply_count"], + self.timestring(thread["last_mod"], "delta")) + +@@ -733,7 +818,7 @@ class App(object): + urwid.Text(dateline), + urwid.Text(("dim", infoline)), + urwid.Text([ +- ("dim", "last post by "), ++ ("dim", "último post por "), + (str(last_author["color"]), "~" + last_author["user_name"]) + ]), + urwid.AttrMap(urwid.Divider(self.theme["divider"]), "dim") +@@ -760,7 +845,7 @@ class App(object): + + if no_action: + callback = ignore +- name = urwid_rainbows("~SYSTEM", True) ++ name = urwid_rainbows("~SISTEMA", True) + color = "0" + else: + callback = self.on_post +@@ -906,9 +991,9 @@ class App(object): + if results: + self.index(threads=results) + if query: +- self.set_header("Searching for '{}'", query) ++ self.set_header("Buscando '{}'", query) + else: +- self.temp_footer_message("No results for '{}'".format(query)) ++ self.temp_footer_message("No se encontró nada para '{}'".format(query)) + + + def search_thread_callback(self, query): +@@ -925,7 +1010,7 @@ class App(object): + # self.highlight_query() + self.do_search_result() + else: +- self.temp_footer_message("No results for '{}'".format(query)) ++ self.temp_footer_message("No se encontró nada para '{}'".format(query)) + + + def do_search_result(self, forward=True): +@@ -941,7 +1026,7 @@ class App(object): + self.match_data["position"] = length - 1 + self.goto_post(self.match_data["matches"][self.match_data["position"]]["post_id"]) + self.temp_footer_message( +- "({}/{}) Searching for {} [#]Next [@]Previous".format( ++ "({}/{}) Buscando para {} [#]Siguiente [@]Anterior".format( + self.match_data["position"] + 1, length, self.match_data["query"] + ), 5) + +@@ -979,9 +1064,9 @@ class App(object): + popup = OptionsMenu( + urwid.ListBox( + urwid.SimpleFocusListWalker([ +- urwid.Text(("button", "Enter a query:")), ++ urwid.Text(("button", "Ingresa pedido:")), + urwid.AttrMap(StringPrompt(callback), "opt_prompt"), +- urwid.Text("Use a blank query to reset the {}.".format(self.mode)) ++ urwid.Text("Pon un pedido en blanco para reiniciar el {}.".format(self.mode)) + ])), + **self.frame_theme()) + +@@ -1004,7 +1089,7 @@ class App(object): + thread = self.thread["thread_id"] + self.thread_load(None, thread) + self.goto_post(mark(thread)) +- self.temp_footer_message("Refreshed content!", 1) ++ self.temp_footer_message("¡Fresco como una lechuga!", 1) + + + def back(self, terminate=False): +@@ -1017,9 +1102,9 @@ class App(object): + elif self.window_split: + # display a confirmation dialog before killing off an in-progress post + buttons = [ +- urwid.Text(("bold", "Discard current post?")), ++ urwid.Text(("bold", "¿Descartar post actual?")), + urwid.Divider(), +- cute_button(("10" , ">> Yes"), lambda _: [ ++ cute_button(("10" , ">> Sí"), lambda _: [ + self.remove_overlays(), + self.index() + ]), +@@ -1082,7 +1167,7 @@ class App(object): + size, new_pos, coming_from= + "below" if (cur_pos < new_pos) else "above") + except IndexError: +- self.temp_footer_message("OUT OF BOUNDS") ++ self.temp_footer_message("FUERA DE LÍMITES") + + + def goto_post_prompt(self, init): +@@ -1093,9 +1178,9 @@ class App(object): + live_display = urwid.Text("") + edit = JumpPrompt(count, lambda x: self.goto_post(x)) + items = [ +- urwid.Text(("button", " Jump to post")), ++ urwid.Text(("button", " Ir al post")), + urwid.AttrMap(edit, "opt_prompt"), +- urwid.Text(("bold", ("(max %d)" % count).center(18, " "))), ++ urwid.Text(("bold", ("(máx. %d)" % count).center(18, " "))), + live_display + ] + +@@ -1205,11 +1290,11 @@ class App(object): + urwid.ListBox( + urwid.SimpleFocusListWalker([ + urwid_rainbows( +- "This is BBJ, a client/server textboard made for tildes!", ++ "Esto es BBJ, ¡un tablón de texto cliente/servidor para tildes!", + True), + urwid.Text(("dim", "...by ~desvox")), + urwid.Divider(self.theme["divider"]), +- urwid.Button("Post Formatting Help", self.formatting_help), ++ urwid.Button("Ayuda de Formateo de Post", self.formatting_help), + urwid.Divider(self.theme["divider"]), + urwid.Text(general_help) + ])), +@@ -1236,7 +1321,7 @@ class App(object): + + widget = OptionsMenu( + urwid.ListBox(urwid.SimpleFocusListWalker(app.make_message_body(message, True))), +- **self.frame_theme("Formatting Help") ++ **self.frame_theme("Ayuda de Formateo") + ) + + va = 5 if self.window_split else 50 +@@ -1282,9 +1367,9 @@ class App(object): + self.loop.stop() + call("clear", shell=True) + try: +- name = nameloop("Choose a new username", True) ++ name = nameloop("Elige un nuevo nombre de usuario", True) + network.user_update(user_name=name) +- motherfucking_rainbows("~~hello there %s~~" % name) ++ motherfucking_rainbows("~~qué tal, %s~~" % name) + sleep(0.8) + self.loop.start() + self.loop.widget = self.loop.widget[0] +@@ -1298,9 +1383,9 @@ class App(object): + self.loop.stop() + call("clear", shell=True) + try: +- password = password_loop("Choose a new password. Can be empty", True) ++ password = password_loop("Elige una nueva clave. Puede estar vacía", True) + network.user_update(auth_hash=network._hash(password)) +- motherfucking_rainbows("SET NEW PASSWORD") ++ motherfucking_rainbows("ELIGE NUEVA CLAVE") + sleep(0.8) + self.loop.start() + self.loop.widget = self.loop.widget[0] +@@ -1317,7 +1402,7 @@ class App(object): + self.prefs[key] = text + bbjrc("update", **self.prefs) + except: +- rendered = ("1", "Invalid Input") ++ rendered = ("1", "Entrada Inválida") + widget.set_text(rendered) + + +@@ -1343,13 +1428,13 @@ class App(object): + mode = args[0] + widget = OptionsMenu( + urwid.ListBox(urwid.SimpleFocusListWalker([ +- urwid.Text("Press Enter when done"), ++ urwid.Text("Presiona Enter cuando termines"), + urwid.AttrMap(KeyPrompt( + self.prefs["edit_escapes"][mode], + self.save_escape_key, + [mode] + ), "opt_prompt")])), +- **self.frame_theme("Set key for " + mode) ++ **self.frame_theme("Elige tecla para " + mode) + ) + + app.loop.widget = urwid.Overlay( +@@ -1396,16 +1481,16 @@ class App(object): + edit_mode = [] + + if network.user_auth: +- account_message = "Logged in as %s." % network.user_name ++ account_message = "Sesión iniciada como %s." % network.user_name + account_stuff = [ +- urwid.Button("Relog", on_press=self.relog), +- urwid.Button("Go anonymous", on_press=self.unlog), +- urwid.Button("Change username", on_press=self.change_username), +- urwid.Button("Change password", on_press=self.change_password), ++ urwid.Button("Cerrar sesión", on_press=self.relog), ++ urwid.Button("Volverse anónimo", on_press=self.unlog), ++ urwid.Button("Editar nombre de usuario", on_press=self.change_username), ++ urwid.Button("Editar clave", on_press=self.change_password), + urwid.Divider(), +- urwid.Text(("button", "Your color:")), +- urwid.Text(("default", "This color will show on your " +- "post headers and when people quote you.")), ++ urwid.Text(("button", "Tu color:")), ++ urwid.Text(("default", "Este color se mostrará en tus " ++ "cabeceras de post y cuando te citen.")), + urwid.Divider() + ] + +@@ -1420,8 +1505,8 @@ class App(object): + account_stuff.append(item) + + else: +- account_message = "You're browsing anonymously, and cannot set account preferences." +- account_stuff = [urwid.Button("Login/Register", on_press=self.relog)] ++ account_message = "Estás navegando anónimamente, no puedes cambiar opciones de cuenta." ++ account_stuff = [urwid.Button("Ingresar/Registrarse", on_press=self.relog)] + + theme_buttons = [] + for name, theme in themes.items(): +@@ -1440,10 +1525,10 @@ class App(object): + urwid.connect_signal(date_edit, "change", self.live_time_render, (date_box, "date")) + + time_stuff = [ +- urwid.Text(("button", "Time Format")), ++ urwid.Text(("button", "Formato de Tiempo")), + time_box, urwid.AttrMap(time_edit, "opt_prompt"), + urwid.Divider(), +- urwid.Text(("button", "Date Format")), ++ urwid.Text(("button", "Formato de Fecha")), + date_box, urwid.AttrMap(date_edit, "opt_prompt"), + ] + +@@ -1463,17 +1548,17 @@ class App(object): + user_data=(editor, editor_display)) + + urwid.RadioButton( +- edit_mode, "Integrate", ++ edit_mode, "Integrar", + state=self.prefs["integrate_external_editor"], + on_state_change=self.set_editor_mode) + + urwid.RadioButton( +- edit_mode, "Overthrow", ++ edit_mode, "Sobreponer", + state=not self.prefs["integrate_external_editor"]) + + content = [] + +- for item in [urwid.Text(("opt_header", "Account"), 'center'), ++ for item in [urwid.Text(("opt_header", "Cuenta"), 'center'), + urwid.Text(account_message), + urwid.Divider()]: + content.append(item) +@@ -1482,33 +1567,33 @@ class App(object): + content.append(item) + + for item in [urwid.Divider(self.theme["divider"]), +- urwid.Text(("opt_header", "App"), 'center'), ++ urwid.Text(("opt_header", "Aplicación"), 'center'), + urwid.Divider(), + urwid.CheckBox( +- "Dump rainbows on exit", ++ "Tirar arcoiris al salir", + state=self.prefs["dramatic_exit"], + on_state_change=self.toggle_exit + ), + urwid.CheckBox( +- "Warn when posting anonymously", ++ "Advertir cuando se postea anónimamente", + state=self.prefs["confirm_anon"], + on_state_change=self.toggle_anon_warn + ), + urwid.CheckBox( +- "Increase index padding", ++ "Aumentar espaciado del índice", + state=self.prefs["index_spacing"], + on_state_change=self.toggle_spacing + ), + urwid.CheckBox( +- "Handle mouse (disrupts URL clicking)", ++ "Usar ratón (perturba cliquear URLs)", + state=self.prefs["mouse_integration"], + on_state_change=self.toggle_mouse + ), + urwid.Divider()]: + content.append(item) + +- for item in [urwid.Text(("button", "Border Theme")), +- urwid.Text("Restart to fully apply.")]: ++ for item in [urwid.Text(("button", "Tema de Borde")), ++ urwid.Text("Reinicia para aplicar completamente.")]: + content.append(item) + + for item in theme_buttons: +@@ -1520,14 +1605,14 @@ class App(object): + content.append(item) + + for item in [urwid.Divider(), +- urwid.Text(("button", "Max message width:")), ++ urwid.Text(("button", "Ancho máximo de mensaje:")), + urwid.AttrMap(width_edit, "opt_prompt"), + urwid.Divider(), +- urwid.Text(("button", "Scroll multiplier when holding shift or scrolling with the mouse:")), ++ urwid.Text(("button", "Multiplicador de despl. cuando se aprieta shift o se mueve con mouse:")), + urwid.AttrMap(shift_edit, "opt_prompt"), + urwid.Divider(), +- urwid.Text(("button", "Text editor:")), +- urwid.Text("You can type in your own command or use one of these presets."), ++ urwid.Text(("button", "Editor de texto:")), ++ urwid.Text("Puedes poner tu propio comando o usar alguno de éstos predefinidos."), + urwid.Divider(), + urwid.AttrMap(editor_display, "opt_prompt")]: + content.append(item) +@@ -1536,20 +1621,20 @@ class App(object): + content.append(item) + + for item in [urwid.Divider(), +- urwid.Text(("button", "Internal Editor Escape Keys:")), +- urwid.Text("You can change these keybinds to whatever " +- "you want. Just remember that these will " +- "shadow over the text editor itself."), ++ urwid.Text(("button", "Teclas de escape del Editor Interno:")), ++ urwid.Text("Puedes cambiarlas a cualquiera que " ++ "prefieras. Solo recuerda que se aplicarán " ++ "encima del programa de edición de texto."), + urwid.Divider(), +- urwid.Button("Abort", self.set_escape_key, ["abort"]), +- urwid.Button("Change Focus", self.set_escape_key, ["focus"]), +- urwid.Button("Formatting Help", self.set_escape_key, ["fhelp"])]: ++ urwid.Button("Abortar", self.set_escape_key, ["abort"]), ++ urwid.Button("Cambiar Foco", self.set_escape_key, ["focus"]), ++ urwid.Button("Ayuda de Formateo", self.set_escape_key, ["fhelp"])]: + content.append(item) + + for item in [urwid.Divider(), +- urwid.Text(("button", "External text editor mode:")), +- urwid.Text("If you have problems using an external text editor, " +- "set this to Overthrow."), ++ urwid.Text(("button", "Modo de editor de texto externo:")), ++ urwid.Text("Si tienes problemas usando un editor de texto externo, " ++ "elige Sobreponer."), + urwid.Divider()]: + content.append(item) + +@@ -1560,7 +1645,7 @@ class App(object): + + widget = OptionsMenu( + urwid.ListBox(urwid.SimpleFocusListWalker(content)), +- **self.frame_theme("Options")) ++ **self.frame_theme("Opciones")) + + self.loop.widget = urwid.Overlay( + widget, self.loop.widget, +@@ -1618,7 +1703,7 @@ class App(object): + descriptor, path = tempfile.mkstemp() + with open(path, "w") as _: + _.write(init_body) +- call("export LANG=en_US.UTF-8; %s %s" % (self.prefs["editor"], path), shell=True) ++ call("export LANG=es_ES.UTF-8; %s %s" % (self.prefs["editor"], path), shell=True) + with open(path) as _: + body = _.read() + os.remove(path) +@@ -1632,18 +1717,18 @@ class App(object): + context and user preferences. + """ + if self.mode == "index" and not title: +- return self.footer_prompt("Title", self.compose) ++ return self.footer_prompt("Título", self.compose) + + elif title: + try: network.validate("title", title) + except AssertionError as e: + return self.footer_prompt( +- "Title", self.compose, extra_text=e.description) ++ "Título", self.compose, extra_text=e.description) + + if not self.prefs["integrate_external_editor"]: + body = self.overthrow_ext_edit(init_body) + if not body or re.search("^>>[0-9]+$", body): +- return self.temp_footer_message("EMPTY POST DISCARDED") ++ return self.temp_footer_message("POST VACÍO DESCARTADO") + params = {"body": body} + + if self.mode == "thread" and not edit: +@@ -1674,8 +1759,8 @@ class App(object): + return + + if self.mode == "index": +- self.set_header('Composing "{}"', title) +- self.set_footer("[{}]Abort [{}]Formatting Help [Save and quit to submit your thread]".format( ++ self.set_header('Escribiendo "{}"', title) ++ self.set_footer("[{}]Abortar [{}]Ayuda de Formateo [Guarda y sal para publicar el hilo]".format( + self.prefs["edit_escapes"]["abort"].upper(), self.prefs["edit_escapes"]["fhelp"].upper() + )) + self.loop.widget = urwid.Overlay( +@@ -1977,7 +2062,7 @@ class ExternalEditor(urwid.Terminal): + # behalf. Users who take issue to programs trying to supress unicode + # should use the options menu to switch to Overthrow mode. + env.update({"LANG": "POSIX"}) +- command = ["bash", "-c", "{} {}; echo Press any key to kill this window...".format( ++ command = ["bash", "-c", "{} {}; echo Presione cualquier tecla para matar esta ventana...".format( + app.prefs["editor"], self.path)] + super(ExternalEditor, self).__init__(command, env, app.loop, app.prefs["edit_escapes"]["abort"]) + urwid.connect_signal(self, "closed", self.exterminate) +@@ -2027,7 +2112,7 @@ class ExternalEditor(urwid.Terminal): + call("clear", shell=True) + print(anon_warn) + choice = paren_prompt( +- "Publicar anónimamente?", default="si", choices=["Sí", "no"] ++ "¿Publicar anónimamente?", default="s", choices=["s", "n"] + ) + if choice == "n": + log_in(True) +@@ -2464,9 +2549,9 @@ def log_in(relog=False): + elif response == "n": + raise InterruptedError + +- password = password_loop("Enter a password. It can be empty if you want") ++ password = password_loop("Ingresa una clave. Puede estar vacía si quieres") + network.user_register(name, password) +- motherfucking_rainbows("~~welcome to the party, %s!~~" % network.user_name) ++ motherfucking_rainbows("~~¡bienvenido a la fiesta, %s!~~" % network.user_name) + sleep(0.5) # let that confirmation message shine + + + + -- cgit v1.2.3