From 8dc9db90c9f97fe2f2f1288abef7964e40deb4a0 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 23 Jun 2019 12:06:36 +0200 Subject: [PATCH] added translation for Czech, provided by @info-path, fixes #424 --- CHANGELOG.md | 1 + CREDITS.md | 1 + i18n/cs.json | 165 ++++++++++++++++++++++++++++++++++++++++++++++ js/privatebin.js | 4 +- lib/I18n.php | 2 + tpl/bootstrap.php | 2 +- tpl/page.php | 2 +- tst/I18nTest.php | 11 ++++ 8 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 i18n/cs.json diff --git a/CHANGELOG.md b/CHANGELOG.md index b1159b3..6225f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # PrivateBin version history * **1.3 (not yet released)** + * ADDED: Translation for Czech (#424) * ADDED: Threat modeled the application (#177) * CHANGED: Minimum required PHP version is 5.5, due to a change in the identicon library * CHANGED: Minimum required browser versions are Firefox 54, Chrome 57, Opera 44, Safari 11, Edge 16, due to use of WebCrypto API, async/await, ES6 & WebAssembly features - all Internet Explorer versions are incompatible diff --git a/CREDITS.md b/CREDITS.md index 688dcc3..0f1b45f 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -41,3 +41,4 @@ Sébastien Sauvage - original idea and main developer * Tulio Leao - Portuguese * Michael van Schaik - Dutch * Péter Tabajdi - Hungarian +* info-path - Czech \ No newline at end of file diff --git a/i18n/cs.json b/i18n/cs.json new file mode 100644 index 0000000..a36ef8b --- /dev/null +++ b/i18n/cs.json @@ -0,0 +1,165 @@ +{ + "PrivateBin": "PrivateBin", + "%s 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.": + "%s je minimalistický open source 'pastebin' server, který neanalyzuje vložená data. Data jsou šifrována v prohlížeči pomocí 256 bitů AES. Více informací na stránce projetu.", + "Because ignorance is bliss": + "Protože nevědomost je sladká", + "en": "cs", + "Paste does not exist, has expired or has been deleted.": + "Vložený text neexistuje, expiroval nebo byl odstraněn.", + "%s requires php %s or above to work. Sorry.": + "%s vyžaduje php %s nebo vyšší. Lituji.", + "%s requires configuration section [%s] to be present in configuration file.": + "%s requires configuration section [%s] to be present in configuration file.", + "Please wait %d seconds between each post.": + "Počet sekund do dalšího příspěvku: %d.", + "Paste is limited to %s of encrypted data.": + "Příspěvek je limitován na %s šífrovaných dat", + "Invalid data.": + "Chybná data.", + "You are unlucky. Try again.": + "Lituji, zkuste to znovu.", + "Error saving comment. Sorry.": + "Chyba při ukládání komentáře.", + "Error saving paste. Sorry.": + "Chyba při ukládání příspěvku.", + "Invalid paste ID.": + "Chybně vložené ID.", + "Paste is not of burn-after-reading type.": + "Paste is not of burn-after-reading type.", + "Wrong deletion token. Paste was not deleted.": + "Wrong deletion token. Paste was not deleted.", + "Paste was properly deleted.": + "Paste was properly deleted.", + "JavaScript is required for %s to work.
Sorry for the inconvenience.": + "JavaScript is required for %s to work.
Sorry for the inconvenience.", + "%s requires a modern browser to work.": + "%%s requires a modern browser to work.", + "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": + "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:", + "New": + "Nový", + "Send": + "Odeslat", + "Clone": + "Klonovat", + "Raw text": + "Pouze Text", + "Expires": + "Expirace", + "Burn after reading": + "Po přečtení smazat", + "Open discussion": + "Povolit komentáře", + "Password (recommended)": + "Heslo (doporučeno)", + "Discussion": + "Komentáře", + "Toggle navigation": + "Toggle navigation", + "%d seconds": ["%d sekuda", "%d sekundy", "%d sekund"], + "%d minutes": ["%d minuta", "%d minuty", "%d minut"], + "%d hours": ["%d hodin", "%d hodiny", "%d hodin"], + "%d days": ["%d den", "%d dny", "%d dní"], + "%d weeks": ["%d týden", "%d týdeny", "%d týdnů"], + "%d months": ["%d měsíc", "%d měsíce", "%d měsíců"], + "%d years": ["%d rok", "%d roky", "%d roků"], + "Never": + "Nikdy", + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": + "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.", + "This document will expire in %d seconds.": + ["Tento dokument expiruje za %d sekundu.", "Tento dokument expiruje za %d sekundy.", "Tento dokument expiruje za %d sekund."], + "This document will expire in %d minutes.": + ["Tento dokument expiruje za %d minutu.", "Tento dokument expiruje za %d minuty.", "Tento dokument expiruje za %d minut."], + "This document will expire in %d hours.": + ["Tento dokument expiruje za %d hodinu.", "Tento dokument expiruje za %d hodiny.", "Tento dokument expiruje za %d hodin."], + "This document will expire in %d days.": + ["Tento dokument expiruje za %d den.", "Tento dokument expiruje za %d dny.", "Tento dokument expiruje za %d dny."], + "This document will expire in %d months.": + ["Tento dokument expiruje za %d měsíc.", "Tento dokument expiruje za %d měsíce.", "Tento dokument expiruje za %d měsíců."], + "Please enter the password for this paste:": + "Zadejte prosím heslo:", + "Could not decrypt data (Wrong key?)": + "Could not decrypt data (Wrong key?)", + "Could not delete the paste, it was not stored in burn after reading mode.": + "Could not delete the paste, it was not stored in burn after reading mode.", + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.": + "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.", + "Could not decrypt comment; Wrong key?": + "Could not decrypt comment; Wrong key?", + "Reply": + "Reply", + "Anonymous": + "Anonym", + "Avatar generated from IP address": + "Avatar generated from IP address", + "Add comment": + "Přidat komentář", + "Optional nickname…": + "Volitelný nickname…", + "Post comment": + "Odeslat komentář", + "Sending comment…": + "Odesílání komentáře…", + "Comment posted.": + "Komentář odeslán.", + "Could not refresh display: %s": + "Could not refresh display: %s", + "unknown status": + "neznámý stav", + "server error or not responding": + "Chyba na serveru nebo server neodpovídá", + "Could not post comment: %s": + "Nelze odeslat komentář: %s", + "Sending paste…": + "Odesílání příspěvku…", + "Your paste is %s (Hit [Ctrl]+[c] to copy)": + "Váš link je %s (Stiskněte [Ctrl]+[c] pro zkopírování)", + "Delete data": + "Odstranit data", + "Could not create paste: %s": + "Nelze vytvořit příspěvek: %s", + "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": + "Nepodařilo se dešifrovat příspěvek: V adrese chybí dešifrovací klíč (Možnou příčinou může být URL shortener?)", + "Format": "Formát", + "Plain Text": "Prostý Text", + "Source Code": "Zdrojový kód", + "Markdown": "Markdown", + "Download attachment": "Stáhnout přílohu", + "Cloned: '%s'": "Klonováno: '%s'", + "The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.", + "Attach a file": "Připojit soubor", + "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard", + "File too large, to display a preview. Please download the attachment.": "Soubor je příliš velký pro zobrazení náhledu. Stáhněte si přílohu.", + "Remove attachment": "Odstranit přílohu", + "Your browser does not support uploading encrypted files. Please use a newer browser.": + "Váš prohlížeč nepodporuje nahrávání šifrovaných souborů. Použijte modernější verzi prohlížeče.", + "Invalid attachment.": "Chybná příloha.", + "Options": "Volby", + "Shorten URL": "Shorten URL", + "Editor": "Editor", + "Preview": "Náhled", + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": + "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.", + "Decrypt": + "Decrypt", + "Enter password": + "Zadejte heslo", + "Loading…": "Loading…", + "Decrypting paste…": "Decrypting paste…", + "Preparing new paste…": "Preparing new paste…", + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.": + "In case this message never disappears please have a look at this FAQ for information to troubleshoot.", + "+++ no paste text +++": "+++ žádný vložený text +++", + "Could not get paste data: %s": + "Could not get paste data: %s", + "QR code": "QR code", + "I love you too, bot…": "I love you too, bot…", + "This website is using an insecure HTTP connection! Please use it only for testing.": + "This website is using an insecure HTTP connection! Please use it only for testing.", + "For more information see this FAQ entry.": + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." +} diff --git a/js/privatebin.js b/js/privatebin.js index 51ffbee..831d813 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -420,7 +420,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @prop {string[]} * @readonly */ - const supportedLanguages = ['de', 'es', 'fr', 'it', 'hu', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh']; + const supportedLanguages = ['cs', 'de', 'es', 'fr', 'it', 'hu', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh']; /** * built in language @@ -571,6 +571,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.getPluralForm = function(n) { switch (language) { + case 'cs': + return n === 1 ? 0 : (n >= 2 && n <=4 ? 1 : 2); case 'fr': case 'oc': case 'zh': diff --git a/lib/I18n.php b/lib/I18n.php index b85b29d..12fadd2 100644 --- a/lib/I18n.php +++ b/lib/I18n.php @@ -294,6 +294,8 @@ class I18n protected static function _getPluralForm($n) { switch (self::$_language) { + case 'cs': + return $n == 1 ? 0 : ($n >= 2 && $n <=4 ? 1 : 2); case 'fr': case 'oc': case 'zh': diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 5f231d5..6e2e212 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -72,7 +72,7 @@ if ($MARKDOWN): endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index e535f6f..82fa016 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -50,7 +50,7 @@ if ($MARKDOWN): endif; ?> - + diff --git a/tst/I18nTest.php b/tst/I18nTest.php index 8be09fa..f366720 100644 --- a/tst/I18nTest.php +++ b/tst/I18nTest.php @@ -130,6 +130,17 @@ class I18nTest extends PHPUnit_Framework_TestCase $this->assertEquals('104 ur', I18n::_('%d hours', 104), '104 hours in Slowene'); } + public function testBrowserLanguageCsDetection() + { + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'cs;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2'; + I18n::loadTranslations(); + $this->assertEquals('cs', I18n::_('en'), 'browser language cs'); + $this->assertEquals('1 hodin', I18n::_('%d hours', 1), '1 hour in Czech'); + $this->assertEquals('2 hodiny', I18n::_('%d hours', 2), '2 hours in Czech'); + $this->assertEquals('5 minut', I18n::_('%d minutes', 5), '5 minutes in Czech'); + $this->assertEquals('14 minut', I18n::_('%d minutes', 14), '14 minutes in Czech'); + } + public function testBrowserLanguageAnyDetection() { $_SERVER['HTTP_ACCEPT_LANGUAGE'] = '*';