diff --git a/i18n/pl.json b/i18n/pl.json
index b5fce72b..8c34f606 100644
--- a/i18n/pl.json
+++ b/i18n/pl.json
@@ -59,11 +59,11 @@
"Przełącz nawigację",
"%d seconds": ["%d second", "%d second", "%d second"],
"%d minutes": ["%d minut", "%d minut", "%d minut"],
- "%d hours": ["%d godzina", "%d godzina", "godzinę"],
+ "%d hours": ["%d godzina", "%d godzina", "%d godzinę"],
"%d days": ["%d dzień", "%d dzień", "%d dzień"],
- "%d weeks": ["%d tydzień", "%d tydzień", "tydzień"],
- "%d months": ["%d miesiąc", "%d miesiąc", "miesiąc"],
- "%d years": ["%d rok", "%d rok", "rok"],
+ "%d weeks": ["%d tydzień", "%d tydzień", "%d tydzień"],
+ "%d months": ["%d miesiąc", "%d miesiąc", "%d miesiąc"],
+ "%d years": ["%d rok", "%d rok", "%d rok"],
"Never":
"nigdy",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
diff --git a/i18n/ru.json b/i18n/ru.json
new file mode 100644
index 00000000..954263e9
--- /dev/null
+++ b/i18n/ru.json
@@ -0,0 +1,157 @@
+{
+ "en": "ru",
+ "Paste does not exist, has expired or has been deleted.":
+ "Запись не существует, просрочена или была удалена.",
+ "PrivateBin requires php 5.3.0 or above to work. Sorry.":
+ "Для работы PrivateBin требуется PHP 5.3.0 или выше. Извините.",
+ "PrivateBin requires configuration section [%s] to be present in configuration file.":
+ "PrivateBin необходимо наличие секции [%s] в конфигурационном файле.",
+ "Please wait %d seconds between each post.":
+ ["Пожалуйста ожидайте %d секунду между каждыми записями.", "Пожалуйста ожидайте %d секунды между каждыми записями.", "Пожалуйста ожидайте %d секунд между каждыми записями."],
+ "Paste is limited to %s of encrypted data.":
+ "Размер записи ограничен %s зашифрованных данных.",
+ "Invalid data.":
+ "Неверные данные.",
+ "You are unlucky. Try again.":
+ "Вам не повезло. Попробуйте еще раз.",
+ "Error saving comment. Sorry.":
+ "Ошибка при сохранении комментария. Извините.",
+ "Error saving paste. Sorry.":
+ "Ошибка при сохранении записи. Извините.",
+ "Invalid paste ID.":
+ "Неверный ID записи.",
+ "Paste is not of burn-after-reading type.":
+ "Тип записи не \"Удалить после прочтения\".",
+ "Wrong deletion token. Paste was not deleted.":
+ "Неверный ключ удаления записи. Запись не удалена",
+ "Paste was properly deleted.":
+ "Запись была успешно удалена.",
+ "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 это минималистичный Open Source проект для создания заметок, где сервер не знает ничего о сохраняемых данных. Данные шифруются/расшифровываются в браузере с использованием 256 битного шифрования AES. Подробнее можно узнать на сайте проекта.",
+ "Because ignorance is bliss":
+ "Потому что неведение - благо",
+ "JavaScript is required for PrivateBin to work.
Sorry for the inconvenience.":
+ "Для работы PrivateBin требуется включенный JavaScript.
Приносим извинения за неудобства..",
+ "PrivateBin requires a modern browser to work.":
+ "Для работы PrivateBin требуется более современный браузер.",
+ "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
+ "До сих пор используете Internet Explorer? Пожалейте себя, перейдите на более современный браузер:",
+ "New":
+ "Новая запись",
+ "Send":
+ "Отправить",
+ "Clone":
+ "Дублировать",
+ "Raw text":
+ "Исходный текст",
+ "Expires":
+ "Удалить через",
+ "Burn after reading":
+ "Удалить после прочтения",
+ "Open discussion":
+ "Открыть обсуждение",
+ "Password (recommended)":
+ "Пароль (рекомендуется)",
+ "Discussion":
+ "Обсуждение",
+ "Toggle navigation":
+ "Переключить навигацию",
+ "%d seconds": ["%d секунду", "%d секунды", "%d секунд"],
+ "%d minutes": ["%d минуту", "%d минуты", "%d минут"],
+ "%d hours": ["%d час", "%d часа", "%d часов"],
+ "%d days": ["%d день", "%d дня", "%d дней"],
+ "%d weeks": ["%d неделю", "%d недели", "%d недель"],
+ "%d months": ["%d месяц", "%d месяца", "%d месяцев"],
+ "%d years": ["%d год", "%d года", "%d лет"],
+ "Never":
+ "Никогда",
+ "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.":
+ ["Документ будет удален через %d секунду.", "Документ будет удален через %d секунды.", "Документ будет удален через %d секунд."],
+ "This document will expire in %d minutes.":
+ ["Документ будет удален через %d минуту.", "Документ будет удален через %d минуты.", "Документ будет удален через %d минут."],
+ "This document will expire in %d hours.":
+ ["Документ будет удален через %d час.", "Документ будет удален через %d часа.", "Документ будет удален через %d часов."],
+ "This document will expire in %d days.":
+ ["Документ будет удален через %d день.", "Документ будет удален через %d дня.", "Документ будет удален через %d дней."],
+ "This document will expire in %d months.":
+ ["Документ будет удален через %d месяц.", "Документ будет удален через %d месяца.", "Документ будет удален через %d месяцев."],
+ "Please enter the password for this paste:":
+ "Пожалуйста введите пароль от записи:",
+ "Could not decrypt data (Wrong key?)":
+ "Невозможно расшифровать данные (Неверный ключ?)",
+ "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.":
+ "ТОЛЬКО ДЛЯ ВАШИХ ГЛАЗ. Не закрывайте это окно, это сообщение не может быть показано снова.",
+ "Could not decrypt comment; Wrong key?":
+ "Невозможно расшифровать комментарий; Неверный ключ?",
+ "Reply":
+ "Ответить",
+ "Anonymous":
+ "Аноним",
+ "Anonymous avatar (Vizhash of the IP address)":
+ "Анонимный аватар (Vizhash IP адреса)",
+ "Add comment":
+ "Добавить комментарий",
+ "Optional nickname...":
+ "Опциональный никнейм...",
+ "Post comment":
+ "Отправить комментарий",
+ "Sending comment...":
+ "Отправка комментария...",
+ "Comment posted.":
+ "Комментарий опубликован.",
+ "Could not refresh display: %s":
+ "Невозможно обновить данные: %s",
+ "unknown status":
+ "неизвестная причина",
+ "server error or not responding":
+ "ошибка сервера или нет ответа",
+ "Could not post comment: %s":
+ "Не удалось опубликовать комментарий: %s",
+ "Sending paste (Please move your mouse for more entropy)...":
+ "Отправка записи (Пожалуйста двигайте мышкой для большей энтропии)...",
+ "Sending paste...":
+ "Отправка записи...",
+ "Your paste is %s (Hit [Ctrl]+[c] to copy)":
+ "Ссылка на запись %s (Нажмите [Ctrl]+[c] чтобы скопировать ссылку)",
+ "Delete data":
+ "Удалить запись",
+ "Could not create paste: %s":
+ "Не удалось опубликовать запись: %s",
+ "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
+ "Невозможно расшифровать запись: Ключ расшифровки отсутствует в ссылке (Может быть вы используете сокращатель ссылок, который удаляет часть ссылки?)",
+ "B": "байт",
+ "KiB": "Кбайт",
+ "MiB": "Мбайт",
+ "GiB": "Гбайт",
+ "TiB": "Тбайт",
+ "PiB": "Пбайт",
+ "EiB": "Эбайт",
+ "ZiB": "Збайт",
+ "YiB": "Йбайт",
+ "Format": "Формат",
+ "Plain Text": "Обычный текст",
+ "Source Code": "Исходный код",
+ "Markdown": "Язык разметки",
+ "Download attachment": "Скачать прикрепленный файл",
+ "Cloned file attached.": "Дубль файла прикреплен.",
+ "Attach a file": "Прикрепить файл",
+ "Remove attachment": "Удалить вложение",
+ "Your browser does not support uploading encrypted files. Please use a newer browser.":
+ "Ваш браузер не поддерживает отправку зашифрованных файлов. Используйте более новый браузер.",
+ "Invalid attachment.": "Неизвестное вложение.",
+ "Options": "Опции",
+ "Shorten URL": "Короткая ссылка",
+ "Editor": "Редактор",
+ "Preview": "Предпросмотр",
+ "PrivateBin requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
+ "Переменная PATH необходима PrivateBin в конце \"%s\". Пожалуйста обновите переменную PATH в вашем index.php.",
+ "Decrypt":
+ "Расшифровать",
+ "Enter password":
+ "Введите пароль"
+}
diff --git a/js/privatebin.js b/js/privatebin.js
index 2cd135c5..9971fcb7 100644
--- a/js/privatebin.js
+++ b/js/privatebin.js
@@ -328,7 +328,7 @@ $(function() {
/**
* supported languages, minus the built in 'en'
*/
- supportedLanguages: ['de', 'fr', 'it', 'pl', 'sl', 'zh'],
+ supportedLanguages: ['de', 'fr', 'it', 'pl', 'ru', 'sl', 'zh'],
/**
* translate a string, alias for translate()
@@ -413,7 +413,9 @@ $(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
default:
return (n !== 1 ? 1 : 0);
diff --git a/lib/I18n.php b/lib/I18n.php
index df9f734b..d60f1090 100644
--- a/lib/I18n.php
+++ b/lib/I18n.php
@@ -298,7 +298,9 @@ class I18n
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
default:
return $n != 1 ? 1 : 0;
diff --git a/tpl/bootstrap-compact.php b/tpl/bootstrap-compact.php
index 2289293e..04afad3e 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 ad7d025f..fc86d65d 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 1a827d3e..0036e2b1 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 7e5b9cf8..9e38b2cc 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 47738e83..dea9d015 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 a171fca0..f98abe50 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 f2f4eadc..c4bc51a8 100644
--- a/tst/I18nTest.php
+++ b/tst/I18nTest.php
@@ -63,7 +63,25 @@ class I18nTest extends PHPUnit_Framework_TestCase
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'pl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
I18n::loadTranslations();
$this->assertEquals('pl', I18n::_('en'), 'browser language pl');
- $this->assertEquals('2 godzina', I18n::_('%d hours', 2), 'hours in polish');
+ $this->assertEquals('1 godzina', I18n::_('%d hours', 1), '1 hour in polish');
+ $this->assertEquals('2 godzina', I18n::_('%d hours', 2), '2 hours in polish');
+ $this->assertEquals('12 godzinę', I18n::_('%d hours', 12), '12 hours in polish');
+ $this->assertEquals('22 godzina', I18n::_('%d hours', 22), '22 hours in polish');
+ $this->assertEquals('1 minut', I18n::_('%d minutes', 1), '1 minute in polish');
+ $this->assertEquals('3 minut', I18n::_('%d minutes', 3), '3 minutes in polish');
+ $this->assertEquals('13 minut', I18n::_('%d minutes', 13), '13 minutes in polish');
+ $this->assertEquals('23 minut', I18n::_('%d minutes', 23), '23 minutes in polish');
+ }
+
+ public function testBrowserLanguageRuDetection()
+ {
+ $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'ru;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
+ I18n::loadTranslations();
+ $this->assertEquals('ru', I18n::_('en'), 'browser language ru');
+ $this->assertEquals('1 минуту', I18n::_('%d minutes', 1), '1 minute in russian');
+ $this->assertEquals('3 минуты', I18n::_('%d minutes', 3), '3 minutes in russian');
+ $this->assertEquals('10 минут', I18n::_('%d minutes', 10), '10 minutes in russian');
+ $this->assertEquals('21 минуту', I18n::_('%d minutes', 21), '21 minutes in russian');
}
public function testBrowserLanguageAnyDetection()