diff --git a/CHANGELOG.md b/CHANGELOG.md index d881fac..e27cea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # PrivateBin version history + * **next (not yet released)** + * ADDED: Translations for Spanish * **1.1 (2016-12-26)** * ADDED: Translations for Italian and Russian * ADDED: Loading message displayed until decryption succeeded for slower (in terms of CPU or network) systems diff --git a/CREDITS.md b/CREDITS.md index 3115aa0..60391fa 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -32,3 +32,4 @@ Sébastien Sauvage - original idea and main developer * Jiawei Zhou - Chinese * Stefano Marty - Italian * R4SAS - Russian +* Alfredo Fabián Altamirano Tena - Spanish diff --git a/i18n/es.json b/i18n/es.json new file mode 100644 index 0000000..42857ef --- /dev/null +++ b/i18n/es.json @@ -0,0 +1,151 @@ +{ + "en": "es", + "Paste does not exist, has expired or has been deleted.": + "El texto no existe, ha caducado o ha sido eliminado.", + "PrivateBin requires php 5.3.0 or above to work. Sorry.": + "PrivateBin requiere php 5.3.0 o superior para funcionar. Lo siento.", + "PrivateBin requires configuration section [%s] to be present in configuration file.": + "PrivateBin requiere que la sección de configuración [% s] esté presente en el archivo de configuración.", + "Please wait %d seconds between each post.": + "Por favor espere %d segundos entre cada publicación.", + "Paste is limited to %s of encrypted data.": + "El texto está limitado a %s de datos cifrados.", + "Invalid data.": + "Datos inválidos.", + "You are unlucky. Try again.": + "Tienes mala suerte. Inténtalo de nuevo", + "Error saving comment. Sorry.": + "Error al guardar el comentario. Lo siento.", + "Error saving paste. Sorry.": + "Error al guardar el texto. Lo siento", + "Invalid paste ID.": + "ID del texto inválido.", + "Paste is not of burn-after-reading type.": + "El texto no es del tipo \"destruir despues de leer\".", + "Wrong deletion token. Paste was not deleted.": + "Token de eliminación erróneo. El texto no fue eliminado.", + "Paste was properly deleted.": + "El texto se ha eliminado correctamente.", + "PrivateBin": "PrivateBin", + "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES. More information on the project page.": + "PrivateBin es un servicio de tipo \"Pastebin\" minimalista de código abierto, donde el servidor no tiene ningún conocimiento de los datos guardados. Los datos son cifrados/descifrados en el navegador usando 256 bits AES. Más información en la página del proyecto.", + "Because ignorance is bliss": + "Porque la ignorancia es dicha", + "JavaScript is required for PrivateBin to work.
Sorry for the inconvenience.": + "JavaScript es necesario para que PrivateBin funcione.
Sentimos los inconvenientes ocasionados.", + "PrivateBin requires a modern browser to work.": + "PrivateBin requiere un navegador moderno para funcionar.", + "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": + "¿Sigues usando Internet Explorer? Hazte un favor, cambia a un navegador moderno:", + "New": + "Nuevo", + "Send": + "Enviar", + "Clone": + "Clonar", + "Raw text": + "Texto sin formato", + "Expires": + "Caducar en", + "Burn after reading": + "Destruir después de leer", + "Open discussion": + "Discusión abierta", + "Password (recommended)": + "Contraseña (recomendado)", + "Discussion": + "Discusión", + "Toggle navigation": + "Cambiar navegación", + "%d seconds": ["%d segundo", "%d segundos"], + "%d minutes": ["%d minuto", "%d minutos"], + "%d hours": ["%d hora", "%d horas"], + "%d days": ["%d día", "%d días"], + "%d weeks": ["%d semana", "%d semanas"], + "%d months": ["%d mes", "%d meses"], + "%d years": ["%d año", "%d años"], + "Never": + "Nunca", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": + "Nota: Este es un servicio de prueba. Los datos pueden ser eliminados en cualquier momento. Gatitos morirán si se abusa de este servicio.", + "This document will expire in %d seconds.": + ["Este documento caducará en un segundo.", "Este documento caducará en %d segundos."], + "This document will expire in %d minutes.": + ["Este documento caducará en un minuto.", "Este documento caducará en %d minutos."], + "This document will expire in %d hours.": + ["Este documento caducará en una hora.", "Este documento caducará en %d horas."], + "This document will expire in %d days.": + ["Este documento caducará en un día.", "Este documento caducará en %d días."], + "This document will expire in %d months.": + ["Este documento caducará en un mes.", "Este documento caducará en %d meses."], + "Please enter the password for this paste:": + "Por favor ingrese la contraseña para este documento:", + "Could not decrypt data (Wrong key?)": + "No fue posible descifrar los datos (¿Clave errónea?)", + "Could not delete the paste, it was not stored in burn after reading mode.": + "No fue posible eliminar el documento, no fue guardado en modo \"destruir despues de leer\".", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": + "SÓLO PARA TUS OJOS. No cierre esta ventana, este mensaje no se puede volver a mostrar.", + "Could not decrypt comment; Wrong key?": + "No se pudo descifrar el comentario; ¿Llave incorrecta?", + "Reply": + "Responder", + "Anonymous": + "Anónimo", + "Anonymous avatar (Vizhash of the IP address)": + "Avatar anónimo (Vizhash de la dirección IP)", + "Add comment": + "Añadir comentario", + "Optional nickname...": + "Seudónimo opcional...", + "Post comment": + "Publicar comentario", + "Sending comment...": + "Enviando comentario...", + "Comment posted.": + "Comentario publicado.", + "Could not refresh display: %s": + "No se pudo actualizar la vista: %s", + "unknown status": + "Estado desconocido", + "server error or not responding": + "Error del servidor o el servidor no responde", + "Could not post comment: %s": + "No fue posible publicar comentario: %s", + "Sending paste (Please move your mouse for more entropy)...": + "Enviando texto (Por favor, mueva el ratón para mayor entropía)...", + "Sending paste...": + "Enviando texto...", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": + "Su texto está en %s (Presione [Ctrl]+[c] para copiar)", + "Delete data": + "Eliminar datos", + "Could not create paste: %s": + "No fue posible crear el archivo: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": + "No es posible descifrar el documento: Falta la clave de descifrado en la URL (¿Utilizó un redirector o un acortador de URL que quite parte de la URL?)", + "Format": "Formato", + "Plain Text": "Texto sin formato", + "Source Code": "Código fuente", + "Markdown": "Markdown", + "Download attachment": "Descargar adjunto", + "Cloned file attached.": "Archivo clonado adjunto.", + "Attach a file": "Adjuntar archivo", + "Remove attachment": "Remover adjunto", + "Your browser does not support uploading encrypted files. Please use a newer browser.": + "Tu navegador no admite la carga de archivos cifrados. Utilice un navegador más reciente.", + "Invalid attachment.": "Adjunto inválido.", + "Options": "Opciones", + "Shorten URL": "Acortar URL", + "Editor": "Editor", + "Preview": "Previsualización", + "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": + "PrivateBin requiere que el PATH termine en \"%s\". Por favor, actualice el PATH en su index.php.", + "Decrypt": + "Descifrar", + "Enter password": + "Ingrese contraseña", + "Loading…": "Cargando…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": + "En caso de que este mensaje nunca desaparezca por favor revise este FAQ para obtener información para solucionar problemas." +} diff --git a/index.php b/index.php index 2b3ceb3..6b04012 100644 --- a/index.php +++ b/index.php @@ -7,7 +7,7 @@ * @link https://github.com/PrivateBin/PrivateBin * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License - * @version 1.0 + * @version 1.1 */ // change this, if your php files and data is outside of your webservers document root diff --git a/js/privatebin.js b/js/privatebin.js index 19ac55c..6efaf46 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -329,7 +329,7 @@ $(function() { /** * supported languages, minus the built in 'en' */ - supportedLanguages: ['de', 'fr', 'it', 'pl', 'ru', 'sl', 'zh'], + supportedLanguages: ['de', 'es', 'fr', 'it', 'pl', 'ru', 'sl', 'zh'], /** * translate a string, alias for translate() @@ -414,10 +414,12 @@ $(function() { case 'zh': return (n > 1 ? 1 : 0); case 'pl': - return (n === 1 ? 0 : (n%10 >= 2 && n %10 <=4 && (n%100 < 10 || n%100 >= 20) ? 1 : 2)); + return (n === 1 ? 0 : (n % 10 >= 2 && n %10 <=4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)); case 'ru': return (n % 10 === 1 && n % 100 !== 11 ? 0 : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)); - // en, de + case 'sl': + return (n % 100 === 1 ? 1 : (n % 100 === 2 ? 2 : (n % 100 === 3 || n % 100 === 4 ? 3 : 0))); + // de, en, es, it default: return (n !== 1 ? 1 : 0); } diff --git a/lib/I18n.php b/lib/I18n.php index 1ced862..c7c6683 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -301,7 +301,9 @@ class I18n return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); case 'ru': return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); - // en, de + case 'sl': + return $n % 100 == 1 ? 1 : ($n % 100 == 2 ? 2 : ($n % 100 == 3 || $n % 100 == 4 ? 3 : 0)); + // de, en, es, it default: return $n != 1 ? 1 : 0; } diff --git a/tpl/bootstrap-compact.php b/tpl/bootstrap-compact.php index db8d026..63390dd 100644 --- a/tpl/bootstrap-compact.php +++ b/tpl/bootstrap-compact.php @@ -52,7 +52,7 @@ if ($MARKDOWN): - + diff --git a/tpl/bootstrap-dark-page.php b/tpl/bootstrap-dark-page.php index e7c6f00..021439b 100644 --- a/tpl/bootstrap-dark-page.php +++ b/tpl/bootstrap-dark-page.php @@ -52,7 +52,7 @@ if ($MARKDOWN): - + diff --git a/tpl/bootstrap-dark.php b/tpl/bootstrap-dark.php index e4b0b51..e8704ea 100644 --- a/tpl/bootstrap-dark.php +++ b/tpl/bootstrap-dark.php @@ -53,7 +53,7 @@ if ($MARKDOWN): - + diff --git a/tpl/bootstrap-page.php b/tpl/bootstrap-page.php index bb65a75..fb595c1 100644 --- a/tpl/bootstrap-page.php +++ b/tpl/bootstrap-page.php @@ -52,7 +52,7 @@ if ($MARKDOWN): - + diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index c3968e3..011c050 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -53,7 +53,7 @@ if ($MARKDOWN): - + diff --git a/tpl/page.php b/tpl/page.php index 77cfac5..564d160 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -47,7 +47,7 @@ if ($MARKDOWN): - + diff --git a/tst/I18nTest.php b/tst/I18nTest.php index c4bc51a..06f1360 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -84,6 +84,21 @@ class I18nTest extends PHPUnit_Framework_TestCase $this->assertEquals('21 минуту', I18n::_('%d minutes', 21), '21 minutes in russian'); } + public function testBrowserLanguageSlDetection() + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'sl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2'; + I18n::loadTranslations(); + $this->assertEquals('sl', I18n::_('en'), 'browser language sl'); + $this->assertEquals('0 ura', I18n::_('%d hours', 0), '0 hours in slowene'); + $this->assertEquals('1 uri', I18n::_('%d hours', 1), '1 hour in slowene'); + $this->assertEquals('2 ure', I18n::_('%d hours', 2), '2 hours in slowene'); + $this->assertEquals('3 ur', I18n::_('%d hours', 3), '3 hours in slowene'); + $this->assertEquals('11 ura', I18n::_('%d hours', 11), '11 hours in slowene'); + $this->assertEquals('101 uri', I18n::_('%d hours', 101), '101 hours in slowene'); + $this->assertEquals('102 ure', I18n::_('%d hours', 102), '102 hours in slowene'); + $this->assertEquals('104 ur', I18n::_('%d hours', 104), '104 hours in slowene'); + } + public function testBrowserLanguageAnyDetection() { $_SERVER['HTTP_ACCEPT_LANGUAGE'] = '*';