diff --git a/CHANGELOG.md b/CHANGELOG.md
index d881fac6..e27cea34 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 3115aa08..60391fa6 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 00000000..42857ef8
--- /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 2b3ceb37..6b04012b 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 19ac55ce..6efaf464 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 1ced8622..c7c66835 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 db8d0267..63390dd3 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 e7c6f000..021439ba 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 e4b0b51f..e8704ea4 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 bb65a751..fb595c13 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 c3968e39..011c0502 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 77cfac57..564d1600 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 c4bc51a8..06f13603 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'] = '*';