Merge branch 'develop' into feature/create_interval_date

This commit is contained in:
Olivier PEREZ 2016-04-26 21:53:47 +02:00
commit c493de7cbe
38 changed files with 1390 additions and 695 deletions

View File

@ -1,6 +1,6 @@
# Changelog de framadate # Changelog de framadate
## Version 1.0 (Olivier - Antonin - Luc) ## Version 1.0 (Antonin - Julien - Luc - Olivier - Pierre)
- Technique : Travail sur le service des notifications - Technique : Travail sur le service des notifications
- Technique : Prise en compte de l'entête X-Forwarded-Proto - Technique : Prise en compte de l'entête X-Forwarded-Proto
- Technique : Utilisation de PHPMailer pour l'envoi de mails - Technique : Utilisation de PHPMailer pour l'envoi de mails
@ -9,7 +9,37 @@
- Amélioration : Masquer l'encart au dessus du tableau des votes, maintenant visible grâce à un bouton - Amélioration : Masquer l'encart au dessus du tableau des votes, maintenant visible grâce à un bouton
- Amélioration : Les commentaires sont horodatés - Amélioration : Les commentaires sont horodatés
- Amélioration : Auto wrapping de la description du sondage - Amélioration : Auto wrapping de la description du sondage
- Amélioration : Possibilité de choisir l'URL du sondage
- Amélioration : Protection de sondages par mots de passe
- Amélioration : Un click dans les champs URL sélectionne le contenu
## Version 0.9.6 (goofy-bz - Olivier - Quentin - Vincent)
- Fix : Corrections mineures de langues
- Amélioration : Nouvelle langue - Occitan
- Amélioration : Blocage d'un vote si l'admin a changé les possibilités entre temps
## Version 0.9.5 (Olivier)
- Fix : Corrections mineures de langues
- Fix : Correction de la suppresion de votes
- Amélioration : Possibilité d'ajouter plus de "moments" à une date
## Version 0.9.4 (JosephK - Olivier - Nikos)
- Fix : Correction de l'échappement des tables Vote et Slot
- Fix : Encodage des "actions" en base64 pour fonctionner avec l'UrlRewriting
- Fix : Correction d'attributs "title"
- Fix : Un seul jour est requis pour faire un sondage
- Fix : Correction de l'UrlRewriting
- Amélioration : Traduction en Italien
## Version 0.9.3 (Antonin - Olivier - Nikos)
- Fix : Traduction de textes en Italien
- Fix : Empêchement de la suppression de la dernière colonne
- Fix : Possiblité de supprimer des colonnes contenant des caractères spéciaux (par exemple "&")
- Fix : Correction de l'exemple d'URL rewriting (des efforts restent à faire)
- Amélioration : (Mode chacun son vote) Possiblité d'éditer son vote directement après un vote
- Amélioration : Message plus parlant lors de la création d'une colonne
## Version 0.9.2 (Olivier)
- Fix : Completion d'un manque de contrôle sur les ID
## Version 0.9.1 (JosephK - Olivier - Antonin - Michael - Paul) ## Version 0.9.1 (JosephK - Olivier - Antonin - Michael - Paul)
- Fix : Correction des lenteurs de défilement - Fix : Correction des lenteurs de défilement
- Fix : Arrêt du défilement auto à gauche qu'on clique sur un choix - Fix : Arrêt du défilement auto à gauche qu'on clique sur un choix

View File

@ -52,9 +52,7 @@ $securityService = new SecurityService();
if (!empty($_POST['poll'])) { if (!empty($_POST['poll'])) {
$poll_id = filter_input(INPUT_POST, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); $poll_id = filter_input(INPUT_POST, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
if (strlen($poll_id) === 16) {
$poll = $pollService->findById($poll_id); $poll = $pollService->findById($poll_id);
}
} }
if (!$poll) { if (!$poll) {

View File

@ -26,6 +26,7 @@ use Framadate\Migration\Alter_Comment_table_for_name_length;
use Framadate\Migration\Alter_Comment_table_adding_date; use Framadate\Migration\Alter_Comment_table_adding_date;
use Framadate\Migration\Generate_uniqId_for_old_votes; use Framadate\Migration\Generate_uniqId_for_old_votes;
use Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9; use Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9;
use Framadate\Migration\Increase_pollId_size;
use Framadate\Migration\Migration; use Framadate\Migration\Migration;
use Framadate\Migration\RPadVotes_from_0_8; use Framadate\Migration\RPadVotes_from_0_8;
use Framadate\Utils; use Framadate\Utils;
@ -46,6 +47,7 @@ $migrations = [
new Alter_Comment_table_for_name_length(), new Alter_Comment_table_for_name_length(),
new Alter_Comment_table_adding_date(), new Alter_Comment_table_adding_date(),
new AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9(), new AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9(),
new Increase_pollId_size()
]; ];
// --------------------------------------- // ---------------------------------------

View File

@ -17,6 +17,9 @@
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/ */
use Framadate\Editable; use Framadate\Editable;
use Framadate\Exception\AlreadyExistsException;
use Framadate\Exception\ConcurrentEditionException;
use Framadate\Exception\MomentAlreadyExistsException;
use Framadate\Message; use Framadate\Message;
use Framadate\Services\AdminPollService; use Framadate\Services\AdminPollService;
use Framadate\Services\InputService; use Framadate\Services\InputService;
@ -25,6 +28,7 @@ use Framadate\Services\MailService;
use Framadate\Services\PollService; use Framadate\Services\PollService;
use Framadate\Services\NotificationService; use Framadate\Services\NotificationService;
use Framadate\Security\PasswordHasher; use Framadate\Security\PasswordHasher;
use Framadate\Utils;
include_once __DIR__ . '/app/inc/init.php'; include_once __DIR__ . '/app/inc/init.php';
@ -182,6 +186,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
$name = $inputService->filterName($_POST['name']); $name = $inputService->filterName($_POST['name']);
$editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT); $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
if (empty($editedVote)) { if (empty($editedVote)) {
$message = new Message('danger', __('Error', 'Something is going wrong...')); $message = new Message('danger', __('Error', 'Something is going wrong...'));
@ -192,16 +197,21 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
if ($message == null) { if ($message == null) {
// Update vote // Update vote
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); try {
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash);
if ($result) { if ($result) {
$message = new Message('success', __('adminstuds', 'Vote updated')); $message = new Message('success', __('adminstuds', 'Vote updated'));
} else { } else {
$message = new Message('danger', __('Error', 'Update vote failed')); $message = new Message('danger', __('Error', 'Update vote failed'));
} }
} catch (ConcurrentEditionException $cee) {
$message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
}
} }
} elseif (isset($_POST['save'])) { // Add a new vote } elseif (isset($_POST['save'])) { // Add a new vote
$name = $inputService->filterName($_POST['name']); $name = $inputService->filterName($_POST['name']);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
if ($name == null) { if ($name == null) {
$message = new Message('danger', __('Error', 'The name is invalid.')); $message = new Message('danger', __('Error', 'The name is invalid.'));
@ -212,12 +222,18 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
if ($message == null) { if ($message == null) {
// Add vote // Add vote
$result = $pollService->addVote($poll_id, $name, $choices); try {
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash);
if ($result) { if ($result) {
$message = new Message('success', __('adminstuds', 'Vote added')); $message = new Message('success', __('adminstuds', 'Vote added'));
} else { } else {
$message = new Message('danger', __('Error', 'Adding vote failed')); $message = new Message('danger', __('Error', 'Adding vote failed'));
} }
} catch (AlreadyExistsException $aee) {
$message = new Message('danger', __('Error', 'You already voted'));
} catch (ConcurrentEditionException $cee) {
$message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
}
} }
} }
@ -226,11 +242,12 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
// ------------------------------- // -------------------------------
if (!empty($_GET['delete_vote'])) { if (!empty($_GET['delete_vote'])) {
$vote_id = filter_input(INPUT_GET, 'delete_vote', FILTER_VALIDATE_INT); $vote_id = filter_input(INPUT_GET, 'delete_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BASE64_REGEX]]);
if ($adminPollService->deleteVote($poll_id, $vote_id)) { $vote_id = Utils::base64url_decode($vote_id);
if ($vote_id && $adminPollService->deleteVote($poll_id, $vote_id)) {
$message = new Message('success', __('adminstuds', 'Vote deleted')); $message = new Message('success', __('adminstuds', 'Vote deleted'));
} else { } else {
$message = new Message('danger', __('Error', 'Failed to delete the vote')); $message = new Message('danger', __('Error', 'Failed to delete the vote!'));
} }
} }
@ -318,6 +335,7 @@ if (isset($_POST['confirm_delete_poll'])) {
if (!empty($_GET['delete_column'])) { if (!empty($_GET['delete_column'])) {
$column = filter_input(INPUT_GET, 'delete_column', FILTER_DEFAULT); $column = filter_input(INPUT_GET, 'delete_column', FILTER_DEFAULT);
$column = Utils::base64url_decode($column);
if ($poll->format === 'D') { if ($poll->format === 'D') {
$ex = explode('@', $column); $ex = explode('@', $column);
@ -342,30 +360,30 @@ if (!empty($_GET['delete_column'])) {
// Add a slot // Add a slot
// ------------------------------- // -------------------------------
if (isset($_GET['add_slot'])) { if (isset($_GET['add_column'])) {
$smarty->assign('poll_id', $poll_id); $smarty->assign('poll_id', $poll_id);
$smarty->assign('admin_poll_id', $admin_poll_id); $smarty->assign('admin_poll_id', $admin_poll_id);
$smarty->assign('format', $poll->format); $smarty->assign('format', $poll->format);
$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title); $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
$smarty->display('add_slot.tpl'); $smarty->display('add_column.tpl');
exit; exit;
} }
if (isset($_POST['confirm_add_slot'])) { if (isset($_POST['confirm_add_column'])) {
try {
if ($poll->format === 'D') { if ($poll->format === 'D') {
$newdate = strip_tags($_POST['newdate']); $newdate = strip_tags($_POST['newdate']);
$newmoment = str_replace(',', '-', strip_tags($_POST['newmoment'])); $newmoment = str_replace(',', '-', strip_tags($_POST['newmoment']));
$ex = explode('/', $newdate); $ex = explode('/', $newdate);
$result = $adminPollService->addDateSlot($poll_id, mktime(0, 0, 0, $ex[1], $ex[0], $ex[2]), $newmoment); $adminPollService->addDateSlot($poll_id, mktime(0, 0, 0, $ex[1], $ex[0], $ex[2]), $newmoment);
} else { } else {
$newslot = str_replace(',', '-', strip_tags($_POST['choice'])); $newslot = str_replace(',', '-', strip_tags($_POST['choice']));
$result = $adminPollService->addClassicSlot($poll_id, $newslot); $adminPollService->addClassicSlot($poll_id, $newslot);
} }
if ($result) {
$message = new Message('success', __('adminstuds', 'Choice added')); $message = new Message('success', __('adminstuds', 'Choice added'));
} else { } catch (MomentAlreadyExistsException $e) {
$message = new Message('danger', __('Error', 'Failed to add the column')); $message = new Message('danger', __('Error', 'The column already exists'));
} }
} }
@ -383,6 +401,7 @@ $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
$smarty->assign('expired', strtotime($poll->end_date) < time()); $smarty->assign('expired', strtotime($poll->end_date) < time());
$smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400); $smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400);
$smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots); $smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots);
$smarty->assign('slots_hash', $pollService->hashSlots($slots));
$smarty->assign('votes', $pollService->splitVotes($votes)); $smarty->assign('votes', $pollService->splitVotes($votes));
$smarty->assign('best_choices', $pollService->computeBestChoices($votes)); $smarty->assign('best_choices', $pollService->computeBestChoices($votes));
$smarty->assign('comments', $comments); $smarty->assign('comments', $comments);
@ -392,5 +411,6 @@ $smarty->assign('admin', true);
$smarty->assign('hidden', false); $smarty->assign('hidden', false);
$smarty->assign('accessGranted', true); $smarty->assign('accessGranted', true);
$smarty->assign('resultPubliclyVisible', true); $smarty->assign('resultPubliclyVisible', true);
$smarty->assign('editedVoteUniqueId', '');
$smarty->display('studs.tpl'); $smarty->display('studs.tpl');

View File

@ -0,0 +1,9 @@
<?php
namespace Framadate\Exception;
class AlreadyExistsException extends \Exception {
function __construct() {
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace Framadate\Exception;
class ConcurrentEditionException extends \Exception {
function __construct() {
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace Framadate\Exception;
class MomentAlreadyExistsException extends \Exception {
function __construct() {
}
}

View File

@ -22,6 +22,7 @@ class Form
{ {
public $title; public $title;
public $id;
public $description; public $description;
public $admin_name; public $admin_name;
public $admin_mail; public $admin_mail;

View File

@ -0,0 +1,46 @@
<?php
namespace Framadate\Migration;
use Framadate\Utils;
class Increase_pollId_size implements Migration {
function __construct() {
}
/**
* This method should describe in english what is the purpose of the migration class.
*
* @return string The description of the migration class
*/
function description() {
return 'Increase the size of id column in poll table';
}
/**
* This method could check if the execute method should be called.
* It is called before the execute method.
*
* @param \PDO $pdo The connection to database
* @return bool true if the Migration should be executed
*/
function preCondition(\PDO $pdo) {
return true;
}
/**
* This methode is called only one time in the migration page.
*
* @param \PDO $pdo The connection to database
* @return bool true if the execution succeeded
*/
function execute(\PDO $pdo) {
$this->alterPollTable($pdo);
}
private function alterPollTable(\PDO $pdo) {
$pdo->exec('
ALTER TABLE `' . Utils::table('poll') . '`
CHANGE `id` `id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
}
}

View File

@ -52,13 +52,13 @@ class RPadVotes_from_0_8 implements Migration {
} }
private function rpadVotes($pdo) { private function rpadVotes($pdo) {
$pdo->exec('UPDATE fd_vote fv $pdo->exec('UPDATE '. Utils::table('vote') .' fv
INNER JOIN ( INNER JOIN (
SELECT v.id, RPAD(v.choices, inn.slots_count, \'0\') new_choices SELECT v.id, RPAD(v.choices, inn.slots_count, \'0\') new_choices
FROM fd_vote v FROM '. Utils::table('vote') .' v
INNER JOIN INNER JOIN
(SELECT s.poll_id, SUM(IFNULL(LENGTH(s.moments) - LENGTH(REPLACE(s.moments, \',\', \'\')) + 1, 1)) slots_count (SELECT s.poll_id, SUM(IFNULL(LENGTH(s.moments) - LENGTH(REPLACE(s.moments, \',\', \'\')) + 1, 1)) slots_count
FROM fd_slot s FROM '. Utils::table('slot') .' s
GROUP BY s.poll_id GROUP BY s.poll_id
ORDER BY s.poll_id) inn ON inn.poll_id = v.poll_id ORDER BY s.poll_id) inn ON inn.poll_id = v.poll_id
WHERE LENGTH(v.choices) != inn.slots_count WHERE LENGTH(v.choices) != inn.slots_count

View File

@ -47,6 +47,14 @@ class PollRepository extends AbstractRepository {
return $prepared->rowCount() > 0; return $prepared->rowCount() > 0;
} }
public function existsByAdminId($admin_poll_id) {
$prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('poll') . '` WHERE admin_id = ?');
$prepared->execute(array($admin_poll_id));
return $prepared->rowCount() > 0;
}
function update($poll) { function update($poll) {
$prepared = $this->prepare('UPDATE `' . Utils::table('poll') . '` SET title=?, admin_name=?, admin_mail=?, description=?, end_date=?, active=?, editable=?, hidden=?, password_hash=?, results_publicly_visible=? WHERE id = ?'); $prepared = $this->prepare('UPDATE `' . Utils::table('poll') . '` SET title=?, admin_name=?, admin_mail=?, description=?, end_date=?, active=?, editable=?, hidden=?, password_hash=?, results_publicly_visible=? WHERE id = ?');

View File

@ -1,6 +1,7 @@
<?php <?php
namespace Framadate\Services; namespace Framadate\Services;
use Framadate\Exception\MomentAlreadyExistsException;
use Framadate\FramaDB; use Framadate\FramaDB;
use Framadate\Repositories\RepositoryFactory; use Framadate\Repositories\RepositoryFactory;
@ -118,7 +119,7 @@ class AdminPollService {
$slots = $this->pollService->allSlotsByPoll($poll); $slots = $this->pollService->allSlotsByPoll($poll);
// We can't delete the last slot // We can't delete the last slot
if ($poll->format == 'D' && count($slots) === 1 && strpos($slots[0]->moments, ',') === -1) { if ($poll->format == 'D' && count($slots) === 1 && strpos($slots[0]->moments, ',') === false) {
return false; return false;
} elseif ($poll->format == 'A' && count($slots) === 1) { } elseif ($poll->format == 'A' && count($slots) === 1) {
return false; return false;
@ -196,10 +197,10 @@ class AdminPollService {
* @param $poll_id int The ID of the poll * @param $poll_id int The ID of the poll
* @param $datetime int The datetime * @param $datetime int The datetime
* @param $new_moment string The moment's name * @param $new_moment string The moment's name
* @return bool true if added * @throws MomentAlreadyExistsException When the moment to add already exists in database
*/ */
public function addDateSlot($poll_id, $datetime, $new_moment) { public function addDateSlot($poll_id, $datetime, $new_moment) {
$this->logService->log('ADD_SLOT', 'id:' . $poll_id . ', datetime:' . $datetime . ', moment:' . $new_moment); $this->logService->log('ADD_COLUMN', 'id:' . $poll_id . ', datetime:' . $datetime . ', moment:' . $new_moment);
$slots = $this->slotRepository->listByPollId($poll_id); $slots = $this->slotRepository->listByPollId($poll_id);
$result = $this->findInsertPosition($slots, $datetime); $result = $this->findInsertPosition($slots, $datetime);
@ -207,16 +208,13 @@ class AdminPollService {
// Begin transaction // Begin transaction
$this->connect->beginTransaction(); $this->connect->beginTransaction();
if ($result == null) { if ($result->slot != null) {
// The moment already exists
return false;
} elseif ($result->slot != null) {
$slot = $result->slot; $slot = $result->slot;
$moments = explode(',', $slot->moments); $moments = explode(',', $slot->moments);
// Check if moment already exists (maybe not necessary) // Check if moment already exists (maybe not necessary)
if (in_array($new_moment, $moments)) { if (in_array($new_moment, $moments)) {
return false; throw new MomentAlreadyExistsException();
} }
// Update found slot // Update found slot
@ -232,8 +230,6 @@ class AdminPollService {
// Commit transaction // Commit transaction
$this->connect->commit(); $this->connect->commit();
return true;
} }
/** /**
@ -244,10 +240,10 @@ class AdminPollService {
* *
* @param $poll_id int The ID of the poll * @param $poll_id int The ID of the poll
* @param $title int The title * @param $title int The title
* @return bool true if added * @throws MomentAlreadyExistsException When the moment to add already exists in database
*/ */
public function addClassicSlot($poll_id, $title) { public function addClassicSlot($poll_id, $title) {
$this->logService->log('ADD_SLOT', 'id:' . $poll_id . ', title:' . $title); $this->logService->log('ADD_COLUMN', 'id:' . $poll_id . ', title:' . $title);
$slots = $this->slotRepository->listByPollId($poll_id); $slots = $this->slotRepository->listByPollId($poll_id);
@ -257,7 +253,7 @@ class AdminPollService {
}, $slots); }, $slots);
if (in_array($title, $titles)) { if (in_array($title, $titles)) {
// The moment already exists // The moment already exists
return false; throw new MomentAlreadyExistsException();
} }
@ -272,8 +268,6 @@ class AdminPollService {
// Commit transaction // Commit transaction
$this->connect->commit(); $this->connect->commit();
return true;
} }
/** /**
@ -283,34 +277,33 @@ class AdminPollService {
* *
* @param $slots array All the slots of the poll * @param $slots array All the slots of the poll
* @param $datetime int The datetime of the new slot * @param $datetime int The datetime of the new slot
* @return null|\stdClass An object like this one: {insert:X, slot:Y} where Y can be null. * @return \stdClass An object like this one: {insert:X, slot:Y} where Y can be null.
*/ */
private function findInsertPosition($slots, $datetime) { private function findInsertPosition($slots, $datetime) {
$result = new \stdClass(); $result = new \stdClass();
$result->slot = null; $result->slot = null;
$result->insert = -1; $result->insert = 0;
$i = 0; // Sort slots before searching where to insert
$this->pollService->sortSlorts($slots);
foreach ($slots as $slot) { // Search where to insert new column
foreach ($slots as $k=>$slot) {
$rowDatetime = $slot->title; $rowDatetime = $slot->title;
$moments = explode(',', $slot->moments); $moments = explode(',', $slot->moments);
if ($datetime == $rowDatetime) { if ($datetime == $rowDatetime) {
$i += count($moments);
// Here we have to insert at the end of a slot // Here we have to insert at the end of a slot
$result->insert += count($moments);
$result->slot = $slot; $result->slot = $slot;
$result->insert = $i;
break; break;
} elseif ($datetime < $rowDatetime) { } elseif ($datetime < $rowDatetime) {
// Here we have to insert a new slot // We have to insert before this slot
break; break;
} else { } else {
$i += count($moments); $result->insert += count($moments);
} }
} }
$result->insert = $i;
return $result; return $result;
} }

View File

@ -54,6 +54,11 @@ class InputService {
return $this->returnIfNotBlank($title); return $this->returnIfNotBlank($title);
} }
public function filterId($id) {
$filtered = filter_var($id, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
return $filtered ? substr($filtered, 0, 64) : false;
}
public function filterName($name) { public function filterName($name) {
$filtered = trim($name); $filtered = trim($name);
return $this->returnIfNotBlank($filtered); return $this->returnIfNotBlank($filtered);
@ -68,6 +73,10 @@ class InputService {
return $description; return $description;
} }
public function filterMD5($control) {
return filter_var($control, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => MD5_REGEX]]);
}
public function filterBoolean($boolean) { public function filterBoolean($boolean) {
return !!filter_var($boolean, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_TRUE_REGEX]]); return !!filter_var($boolean, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_TRUE_REGEX]]);
} }

View File

@ -18,11 +18,13 @@
*/ */
namespace Framadate\Services; namespace Framadate\Services;
use Framadate\Exception\AlreadyExistsException;
use Framadate\Exception\ConcurrentEditionException;
use Framadate\Form; use Framadate\Form;
use Framadate\FramaDB; use Framadate\FramaDB;
use Framadate\Utils;
use Framadate\Security\Token;
use Framadate\Repositories\RepositoryFactory; use Framadate\Repositories\RepositoryFactory;
use Framadate\Security\Token;
use Framadate\Utils;
class PollService { class PollService {
@ -50,7 +52,7 @@ class PollService {
* @return \stdClass|null The found poll, or null * @return \stdClass|null The found poll, or null
*/ */
function findById($poll_id) { function findById($poll_id) {
if (preg_match('/^[\w\d]{16}$/i', $poll_id)) { if (preg_match(POLL_REGEX, $poll_id)) {
return $this->pollRepository->findById($poll_id); return $this->pollRepository->findById($poll_id);
} }
@ -58,7 +60,7 @@ class PollService {
} }
public function findByAdminId($admin_poll_id) { public function findByAdminId($admin_poll_id) {
if (preg_match('/^[\w\d]{24}$/i', $admin_poll_id)) { if (preg_match(ADMIN_POLL_REGEX, $admin_poll_id)) {
return $this->pollRepository->findByAdminId($admin_poll_id); return $this->pollRepository->findByAdminId($admin_poll_id);
} }
@ -76,24 +78,34 @@ class PollService {
function allSlotsByPoll($poll) { function allSlotsByPoll($poll) {
$slots = $this->slotRepository->listByPollId($poll->id); $slots = $this->slotRepository->listByPollId($poll->id);
if ($poll->format == 'D') { if ($poll->format == 'D') {
uasort($slots, function ($a, $b) { $this->sortSlorts($slots);
return $a->title > $b->title;
});
} }
return $slots; return $slots;
} }
public function updateVote($poll_id, $vote_id, $name, $choices) { public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash) {
$choices = implode($choices); $poll = $this->findById($poll_id);
// Check if slots are still the same
$this->checkThatSlotsDidntChanged($poll, $slots_hash);
// Update vote
$choices = implode($choices);
return $this->voteRepository->update($poll_id, $vote_id, $name, $choices); return $this->voteRepository->update($poll_id, $vote_id, $name, $choices);
} }
function addVote($poll_id, $name, $choices) { function addVote($poll_id, $name, $choices, $slots_hash) {
$poll = $this->findById($poll_id);
// Check if slots are still the same
$this->checkThatSlotsDidntChanged($poll, $slots_hash);
// Check if vote already exists
if ($this->voteRepository->existsByPollIdAndName($poll_id, $name)) { if ($this->voteRepository->existsByPollIdAndName($poll_id, $name)) {
return false; throw new AlreadyExistsException();
} }
// Insert new vote
$choices = implode($choices); $choices = implode($choices);
$token = $this->random(16); $token = $this->random(16);
return $this->voteRepository->insert($poll_id, $name, $choices, $token); return $this->voteRepository->insert($poll_id, $name, $choices, $token);
@ -112,13 +124,22 @@ class PollService {
* @return string * @return string
*/ */
function createPoll(Form $form) { function createPoll(Form $form) {
// Generate poll IDs, loop while poll ID already exists // Generate poll IDs, loop while poll ID already exists
if (empty($form->id)) { // User want us to generate an id for him
do { do {
$poll_id = $this->random(16); $poll_id = $this->random(16);
} while ($this->pollRepository->existsById($poll_id)); } while ($this->pollRepository->existsById($poll_id));
$admin_poll_id = $poll_id . $this->random(8); $admin_poll_id = $poll_id . $this->random(8);
} else { // User have choosen the poll id
$poll_id = $form->id;
do {
$admin_poll_id = $this->random(24);
} while ($this->pollRepository->existsByAdminId($admin_poll_id));
}
// Insert poll + slots // Insert poll + slots
$this->pollRepository->beginTransaction(); $this->pollRepository->beginTransaction();
$this->pollRepository->insertPoll($poll_id, $admin_poll_id, $form); $this->pollRepository->insertPoll($poll_id, $admin_poll_id, $form);
@ -168,6 +189,16 @@ class PollService {
return $splitted; return $splitted;
} }
/**
* @param $slots array The slots to hash
* @return string The hash
*/
public function hashSlots($slots) {
return md5(array_reduce($slots, function($carry, $item) {
return $carry . $item->id . '@' . $item->moments . ';';
}));
}
function splitVotes($votes) { function splitVotes($votes) {
$splitted = array(); $splitted = array();
foreach ($votes as $vote) { foreach ($votes as $vote) {
@ -202,4 +233,28 @@ class PollService {
return time() + 86400; return time() + 86400;
} }
/**
* This method checks if the hash send by the user is the same as the computed hash.
*
* @param $poll /stdClass The poll
* @param $slots_hash string The hash sent by the user
* @throws ConcurrentEditionException Thrown when hashes are differents
*/
private function checkThatSlotsDidntChanged($poll, $slots_hash) {
$slots = $this->allSlotsByPoll($poll);
if ($slots_hash !== $this->hashSlots($slots)) {
throw new ConcurrentEditionException();
}
}
/**
* @return mixed
*/
public function sortSlorts(&$slots) {
uasort($slots, function ($a, $b) {
return $a->title > $b->title;
});
return $slots;
}
} }

View File

@ -0,0 +1,53 @@
<?php
namespace Framadate\Services;
class SessionService {
/**
* Get value of $key in $section, or $defaultValue
*
* @param $section
* @param $key
* @param null $defaultValue
* @return mixed
*/
public function get($section, $key, $defaultValue=null) {
assert(!empty($key));
assert(!empty($section));
$this->initSectionIfNeeded($section);
$returnValue = $defaultValue;
if (isset($_SESSION[$section][$key])) {
$returnValue = $_SESSION[$section][$key];
}
return $returnValue;
}
/**
* Set a $value for $key in $section
*
* @param $section
* @param $key
* @param $value
*/
public function set($section, $key, $value) {
assert(!empty($key));
assert(!empty($section));
$this->initSectionIfNeeded($section);
$_SESSION[$section][$key] = $value;
}
private function initSectionIfNeeded($section) {
if (!isset($_SESSION[$section])) {
$_SESSION[$section] = array();
}
}
}

View File

@ -104,6 +104,9 @@ class Utils {
* @return string The poll's URL. * @return string The poll's URL.
*/ */
public static function getUrlSondage($id, $admin = false, $vote_id = '', $action = null, $action_value = null) { public static function getUrlSondage($id, $admin = false, $vote_id = '', $action = null, $action_value = null) {
// URL-Encode $action_value
$action_value = $action_value == null ? null : Utils::base64url_encode($action_value);
if (URL_PROPRE) { if (URL_PROPRE) {
if ($admin === true) { if ($admin === true) {
$url = self::get_server_name() . $id . '/admin'; $url = self::get_server_name() . $id . '/admin';
@ -112,8 +115,12 @@ class Utils {
} }
if ($vote_id != '') { if ($vote_id != '') {
$url .= '/vote/' . $vote_id . "#edit"; $url .= '/vote/' . $vote_id . "#edit";
} elseif ($action != null && $action_value != null) { } elseif ($action != null) {
if ($action_value != null) {
$url .= '/action/' . $action . '/' . $action_value; $url .= '/action/' . $action . '/' . $action_value;
} else {
$url .= '/action/' . $action;
}
} }
} else { } else {
if ($admin === true) { if ($admin === true) {
@ -123,8 +130,12 @@ class Utils {
} }
if ($vote_id != '') { if ($vote_id != '') {
$url .= '&vote=' . $vote_id . "#edit"; $url .= '&vote=' . $vote_id . "#edit";
} elseif ($action != null && $action_value != null) { } elseif ($action != null) {
if ($action_value != null) {
$url .= '&' . $action . "=" . $action_value; $url .= '&' . $action . "=" . $action_value;
} else {
$url .= '&' . $action . "=";
}
} }
} }
@ -197,4 +208,12 @@ class Utils {
public static function fromPostOrDefault($postKey, $default = '') { public static function fromPostOrDefault($postKey, $default = '') {
return !empty($_POST[$postKey]) ? Utils::htmlEscape($_POST[$postKey]) : $default; return !empty($_POST[$postKey]) ? Utils::htmlEscape($_POST[$postKey]) : $default;
} }
public static function base64url_encode($input) {
return rtrim(strtr(base64_encode($input), '+/', '-_'), '=');
}
public static function base64url_decode($input) {
return base64_decode(str_pad(strtr($input, '-_', '+/'), strlen($input) % 4, '=', STR_PAD_RIGHT));
}
} }

View File

@ -1,88 +0,0 @@
<?php
/**
* This software is governed by the CeCILL-B license. If a copy of this license
* is not distributed with this file, you can obtain one at
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt
*
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
* Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft)
*
* =============================
*
* Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence
* ne se trouve pas avec ce fichier vous pouvez l'obtenir sur
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt
*
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
// Fully qualified domain name of your webserver.
// If this is unset or empty, the servername is determined automatically.
// You *have to set this* if you are running Framedate behind a reverse proxy.
// const APP_URL = '<www.mydomain.fr>';
// Application name
const NOMAPPLICATION = 'Développement OPZ';
// Database administrator email
const ADRESSEMAILADMIN = 'framadate-dev@olivierperez.fr';
// Email for automatic responses (you should set it to "no-reply")
const ADRESSEMAILREPONSEAUTO = 'no-reply@olivierperez.fr';
// Database user
const DB_USER= 'dev_framadate';
// Database password
const DB_PASSWORD = 'dev_framadate';
// Database server name, leave empty to use a socket
const DB_CONNECTION_STRING = 'mysql:host=localhost;dbname=framadate_dev;port=3306';
// Name of the table that store migration script already executed
const MIGRATION_TABLE = 'framadate_migration';
// Table name prefix
const TABLENAME_PREFIX = 'fd_';
// Default Language using POSIX variant of BC P47 standard (choose in $ALLOWED_LANGUAGES)
const DEFAULT_LANGUAGE = 'fr';
// List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6
$ALLOWED_LANGUAGES = [
'fr' => 'Français',
'en' => 'English',
'es' => 'Español',
'de' => 'Deutsch',
'it' => 'Italiano',
];
// Nom et emplacement du fichier image contenant le titre
const IMAGE_TITRE = 'images/logo-framadate.png';
// Clean URLs, boolean
const URL_PROPRE = false;
// Use REMOTE_USER data provided by web server
const USE_REMOTE_USER = true;
// Path to the log file
const LOG_FILE = 'admin/stdout.log';
// Days (after expiration date) before purge a poll
const PURGE_DELAY = 60;
// Config
$config = [
/* general config */
'use_smtp' => false, // use email for polls creation/modification/responses notification
/* home */
'show_what_is_that' => true, // display "how to use" section
'show_the_software' => true, // display technical information about the software
'show_cultivate_your_garden' => true, // display "developpement and administration" information
/* create_classic_poll.php / create_date_poll.php */
'default_poll_duration' => 180, // default values for the new poll duration (number of days).
/* create_classic_poll.php */
'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll.
];

View File

@ -53,6 +53,7 @@ const DEFAULT_LANGUAGE = 'fr';
$ALLOWED_LANGUAGES = [ $ALLOWED_LANGUAGES = [
'fr' => 'Français', 'fr' => 'Français',
'en' => 'English', 'en' => 'English',
'oc' => 'Occitan',
'es' => 'Español', 'es' => 'Español',
'de' => 'Deutsch', 'de' => 'Deutsch',
'it' => 'Italiano', 'it' => 'Italiano',
@ -86,4 +87,3 @@ $config = [
/* create_classic_poll.php */ /* create_classic_poll.php */
'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll.
]; ];

View File

@ -18,14 +18,17 @@
*/ */
// FRAMADATE version // FRAMADATE version
const VERSION = '0.9'; const VERSION = '1.0';
// Regex // Regex
const POLL_REGEX = '/^[a-z0-9]+$/i'; const POLL_REGEX = '/^[a-z0-9-]*$/i';
const ADMIN_POLL_REGEX = '/^[a-z0-9]{24}$/i';
const CHOICE_REGEX = '/^[012]$/'; const CHOICE_REGEX = '/^[012]$/';
const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i';
const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i';
const EDITABLE_CHOICE_REGEX = '/^[0-2]$/'; const EDITABLE_CHOICE_REGEX = '/^[0-2]$/';
const BASE64_REGEX = '/^[A-Za-z0-9]+$/';
const MD5_REGEX = '/^[A-Fa-f0-9]{32}$/';
// CSRF (300s = 5min) // CSRF (300s = 5min)
const TOKEN_TIME = 300; const TOKEN_TIME = 300;

View File

@ -49,7 +49,7 @@ function smarty_function_poll_url($params, Smarty_Internal_Template $template) {
$poll_id = filter_var($params['id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); $poll_id = filter_var($params['id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
$admin = (isset($params['admin']) && $params['admin']) ? true : false; $admin = (isset($params['admin']) && $params['admin']) ? true : false;
$action = (isset($params['action']) && !empty($params['action'])) ? Utils::htmlEscape($params['action']) : false; $action = (isset($params['action']) && !empty($params['action'])) ? Utils::htmlEscape($params['action']) : false;
$action_value = (isset($params['action_value']) && !empty($params['action_value'])) ? Utils::htmlEscape($params['action_value']) : false; $action_value = (isset($params['action_value']) && !empty($params['action_value'])) ? $params['action_value'] : false;
$vote_unique_id = isset($params['vote_id']) ? filter_var($params['vote_id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]) : ''; $vote_unique_id = isset($params['vote_id']) ? filter_var($params['vote_id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]) : '';
// If filter_var fails (i.e.: hack tentative), it will return false. At least no leak is possible from this. // If filter_var fails (i.e.: hack tentative), it will return false. At least no leak is possible from this.

View File

@ -18,10 +18,10 @@
*/ */
use Framadate\Form; use Framadate\Form;
use Framadate\Services\InputService; use Framadate\Repositories\RepositoryFactory;
use Framadate\Editable;
use Framadate\Utils;
use Framadate\Security\PasswordHasher; use Framadate\Security\PasswordHasher;
use Framadate\Services\InputService;
use Framadate\Utils;
include_once __DIR__ . '/app/inc/init.php'; include_once __DIR__ . '/app/inc/init.php';
@ -32,6 +32,7 @@ const GO_TO_STEP_2 = 'gotostep2';
/*----------*/ /*----------*/
$inputService = new InputService(); $inputService = new InputService();
$pollRepository = RepositoryFactory::pollRepository();
/* PAGE */ /* PAGE */
/* ---- */ /* ---- */
@ -55,16 +56,18 @@ if (isset($_GET['type']) && $_GET['type'] == 'date' ||
$goToStep2 = filter_input(INPUT_POST, GO_TO_STEP_2, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(date|classic)$/']]); $goToStep2 = filter_input(INPUT_POST, GO_TO_STEP_2, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(date|classic)$/']]);
if ($goToStep2) { if ($goToStep2) {
$title = $inputService->filterTitle($_POST['title']); $title = $inputService->filterTitle($_POST['title']);
$customizeId = $inputService->filterBoolean($_POST['customize_id']);
$id = $customizeId == true ? $inputService->filterId($_POST['id']) : null;
$name = $inputService->filterName($_POST['name']); $name = $inputService->filterName($_POST['name']);
$mail = $inputService->filterMail($_POST['mail']); $mail = $config['use_smtp'] == true ? $inputService->filterMail($_POST['mail']) : null;
$description = $inputService->filterDescription($_POST['description']); $description = $inputService->filterDescription($_POST['description']);
$editable = $inputService->filterEditable($_POST['editable']); $editable = $inputService->filterEditable($_POST['editable']);
$receiveNewVotes = isset($_POST['receiveNewVotes']) ? $inputService->filterBoolean($_POST['receiveNewVotes']) : false; $receiveNewVotes = isset($_POST['receiveNewVotes']) ? $inputService->filterBoolean($_POST['receiveNewVotes']) : false;
$receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false; $receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false;
$hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false; $hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
$use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]); $use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
$password = isset($_POST['password'])?$_POST['password']:null; $password = isset($_POST['password']) ? $_POST['password'] : null;
$password_repeat = isset($_POST['password_repeat'])?$_POST['password_repeat']:null; $password_repeat = isset($_POST['password_repeat']) ? $_POST['password_repeat'] : null;
$results_publicly_visible = filter_input(INPUT_POST, 'results_publicly_visible', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]); $results_publicly_visible = filter_input(INPUT_POST, 'results_publicly_visible', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
// On initialise également les autres variables // On initialise également les autres variables
@ -76,6 +79,7 @@ if ($goToStep2) {
$error_on_password_repeat = false; $error_on_password_repeat = false;
$_SESSION['form']->title = $title; $_SESSION['form']->title = $title;
$_SESSION['form']->id = $id;
$_SESSION['form']->admin_name = $name; $_SESSION['form']->admin_name = $name;
$_SESSION['form']->admin_mail = $mail; $_SESSION['form']->admin_mail = $mail;
$_SESSION['form']->description = $description; $_SESSION['form']->description = $description;
@ -97,6 +101,15 @@ if ($goToStep2) {
$error_on_title = true; $error_on_title = true;
} }
if ($customizeId) {
if ($id === false) {
$error_on_id = true;
} else if ($pollRepository->existsById($id)) {
$error_on_id = true;
$error_on_id_msg = __('Error', 'Poll id already used');
}
}
if ($name !== $_POST['name']) { if ($name !== $_POST['name']) {
$error_on_name = true; $error_on_name = true;
} }
@ -120,8 +133,9 @@ if ($goToStep2) {
} }
} }
if ($title && $name && $email_OK && !$error_on_title && !$error_on_description && !$error_on_name if ($title && $name && $email_OK && !$error_on_title && !$error_on_id && !$error_on_description && !$error_on_name
&& !$error_on_password && !$error_on_password_repeat) { && !$error_on_password && !$error_on_password_repeat
) {
// If no errors, we hash the password if needed // If no errors, we hash the password if needed
if ($_SESSION['form']->use_password) { if ($_SESSION['form']->use_password) {
@ -157,6 +171,11 @@ $errors = array(
'aria' => '', 'aria' => '',
'class' => '' 'class' => ''
), ),
'id' => array(
'msg' => '',
'aria' => '',
'class' => ''
),
'description' => array( 'description' => array(
'msg' => '', 'msg' => '',
'aria' => '', 'aria' => '',
@ -195,6 +214,12 @@ if (!empty($_POST[GO_TO_STEP_2])) {
$errors['title']['msg'] = __('Error', 'Something is wrong with the format'); $errors['title']['msg'] = __('Error', 'Something is wrong with the format');
} }
if ($error_on_id) {
$errors['id']['aria'] = 'aria-describeby="poll_comment_error" ';
$errors['id']['class'] = ' has-error';
$errors['id']['msg'] = isset($error_on_id_msg) ? $error_on_id_msg : __('Error', 'Something is wrong with the format');
}
if ($error_on_description) { if ($error_on_description) {
$errors['description']['aria'] = 'aria-describeby="poll_comment_error" '; $errors['description']['aria'] = 'aria-describeby="poll_comment_error" ';
$errors['description']['class'] = ' has-error'; $errors['description']['class'] = ' has-error';
@ -243,6 +268,7 @@ $smarty->assign('goToStep2', GO_TO_STEP_2);
$smarty->assign('poll_type', $poll_type); $smarty->assign('poll_type', $poll_type);
$smarty->assign('poll_title', Utils::fromPostOrDefault('title', $_SESSION['form']->title)); $smarty->assign('poll_title', Utils::fromPostOrDefault('title', $_SESSION['form']->title));
$smarty->assign('poll_id', Utils::fromPostOrDefault('id', $_SESSION['form']->id));
$smarty->assign('poll_description', Utils::fromPostOrDefault('description', $_SESSION['form']->description)); $smarty->assign('poll_description', Utils::fromPostOrDefault('description', $_SESSION['form']->description));
$smarty->assign('poll_name', Utils::fromPostOrDefault('name', $_SESSION['form']->admin_name)); $smarty->assign('poll_name', Utils::fromPostOrDefault('name', $_SESSION['form']->admin_name));
$smarty->assign('poll_mail', Utils::fromPostOrDefault('mail', $_SESSION['form']->admin_mail)); $smarty->assign('poll_mail', Utils::fromPostOrDefault('mail', $_SESSION['form']->admin_mail));

View File

@ -6,10 +6,12 @@
RewriteEngine On RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]
RewriteRule ^([a-zA-Z0-9]{16})$ studs.php?poll=$1 RewriteRule ^([a-zA-Z0-9-]+)$ studs.php?poll=$1 [L]
RewriteRule ^([a-zA-Z0-9]{16})/action/([a-zA-Z_-]+)/(.+)$ studs.php?poll=$1&$2=$3 RewriteRule ^([a-zA-Z0-9-]+)/action/([a-zA-Z_-]+)/(.+)$ studs.php?poll=$1&$2=$3
RewriteRule ^([a-zA-Z0-9]{16})/vote/([a-zA-Z0-9]{16})$ studs.php?poll=$1&vote_id=$2 RewriteRule ^([a-zA-Z0-9-]+)/vote/([a-zA-Z0-9]{16})$ studs.php?poll=$1&vote=$2
RewriteRule ^([a-zA-Z0-9]{24})/admin$ adminstuds.php?poll=$1 RewriteRule ^([a-zA-Z0-9-]{24})/admin$ adminstuds.php?poll=$1
RewriteRule ^([a-zA-Z0-9]{24})/admin/action/([a-zA-Z_-]+)/(.+)$ adminstuds.php?poll=$1&$2=$3 RewriteRule ^([a-zA-Z0-9-]{24})/admin/vote/([a-zA-Z0-9]{16})$ adminstuds.php?poll=$1&vote=$2
RewriteRule ^([a-zA-Z0-9-]{24})/admin/action/([a-zA-Z_-]+)(/(.+))?$ adminstuds.php?poll=$1&$2=$4
</IfModule> </IfModule>

View File

@ -33,6 +33,31 @@ $(document).ready(function () {
} }
}); });
/**
* Enable/Disable custom id options
*/
var $pollId = $("#poll_id");
var $customizeId = $("#customize_id");
// Init checkbox + input
if (($pollId.val() || $pollId.attr('value') || "").length > 0) {
$customizeId.attr('checked', 'checked');
$pollId.removeAttr("disabled");
}
// Listen for checkbox changes
$customizeId.change(function () {
if ($(this).prop("checked")) {
$pollId
.removeAttr("disabled")
.val($pollId.attr("tmp") || $pollId.attr('value'));
} else {
$pollId
.attr("disabled", "disabled")
.attr("tmp", $pollId.val())
.val("");
}
});
/** /**
* Hide/Show password options * Hide/Show password options
*/ */

View File

@ -149,7 +149,6 @@ $(document).ready(function () {
$(this).find('.hours:eq(' + i + ')').val(first_day_hours[i]); // fill hours $(this).find('.hours:eq(' + i + ')').val(first_day_hours[i]); // fill hours
} }
}); });
$('#d0-h0').focus();
}); });
// Buttons "Add an hour" // Buttons "Add an hour"
@ -179,11 +178,11 @@ $(document).ready(function () {
'</div>'; '</div>';
// After 11 + button is disable // After 11 + button is disable
if (hj < 10) { if (hj < 99) {
last_hour.after(new_hour_html); last_hour.after(new_hour_html);
$('#d' + di + '-h' + (hj + 1)).focus(); $('#d' + di + '-h' + (hj + 1)).focus();
$(this).prev('.remove-an-hour').removeClass('disabled'); $(this).prev('.remove-an-hour').removeClass('disabled');
if (hj == 9) { if (hj == 98) {
$(this).addClass('disabled'); $(this).addClass('disabled');
} }
} }

View File

@ -74,6 +74,7 @@ $(document).ready(function () {
newMessage newMessage
.find('.contents') .find('.contents')
.text(data.message.message); .text(data.message.message);
newMessage.removeClass('hidden');
var commentsAlert = $('#comments_alerts'); var commentsAlert = $('#comments_alerts');
commentsAlert commentsAlert
.empty() .empty()

View File

@ -124,17 +124,14 @@
"Poll rules": "Regeln der Umfrage", "Poll rules": "Regeln der Umfrage",
"Edit the poll rules": "Regeln der Umfrage bearbeiten", "Edit the poll rules": "Regeln der Umfrage bearbeiten",
"Votes and comments are locked": "Wertungen und Kommentare sind gesperrt", "Votes and comments are locked": "Wertungen und Kommentare sind gesperrt",
"Votes and comments are open": "Wertungen und Kommentare sind erlaubt",
"Votes are editable": "Die Wertungen können geändert werden",
"Votes are editable solely by their owner.": "Wertungen können nur vom Urheber geändert werden",
"Save the new rules": "Neue Regeln speichern", "Save the new rules": "Neue Regeln speichern",
"Cancel the rules edit": "Abbruch, Regeln nicht ändern", "Cancel the rules edit": "Abbruch, Regeln nicht ändern",
"Results are hidden.": "Ergebnisse werden ausgeblendet.", "Results are hidden": "Ergebnisse werden ausgeblendet",
"Results are visible.": "Ergebnisse sind sichtbar.", "Results are visible": "Ergebnisse sind sichtbar",
"Password protected.": "DE_Protégé par mot de passe.", "Password protected": "DE_Protégé par mot de passe",
"Votes protected by password.": "DE_Votes protégés par mot de passe.", "Votes protected by password": "DE_Votes protégés par mot de passe",
"No password.": "DE_Pas de mot de passe", "No password": "DE_Pas de mot de passe",
"Remove password.": "DE_Supprimer le mot de passe." "Remove password": "DE_Supprimer le mot de passe"
}, },
"Poll results": { "Poll results": {
"Votes of the poll": "Stimmabgaben zur Umfrage", "Votes of the poll": "Stimmabgaben zur Umfrage",
@ -221,8 +218,11 @@
"You are in the poll creation section.": "Hier erstellen Sie die Umfrage", "You are in the poll creation section.": "Hier erstellen Sie die Umfrage",
"Required fields cannot be left blank.": "Mit * markierte Felder müssen ausgefüllt sein.", "Required fields cannot be left blank.": "Mit * markierte Felder müssen ausgefüllt sein.",
"Poll title": "Titel der Umfrage", "Poll title": "Titel der Umfrage",
"Votes cannot be modified.": "Wertungen können nicht verändert werden.", "Poll id": "DE_Identifiant",
"All voters can modify any vote": "Jeder Teilnehmer kann jede abgegebene Wertung ändern.", "Poll id rules": "DE_L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".",
"Poll id warning": "DE_En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.",
"Votes cannot be modified": "Wertungen können nicht verändert werden",
"All voters can modify any vote": "Jeder Teilnehmer kann jede abgegebene Wertung ändern",
"Voters can modify their vote themselves": "Teilnehmer können ihre Wertungen verändern", "Voters can modify their vote themselves": "Teilnehmer können ihre Wertungen verändern",
"To receive an email for each new vote": "Bei jeder neuen Wertung eine E-Mail erhalten", "To receive an email for each new vote": "Bei jeder neuen Wertung eine E-Mail erhalten",
"To receive an email for each new comment": "Bei jedem neuen Kommentar eine E-Mail erhalten", "To receive an email for each new comment": "Bei jedem neuen Kommentar eine E-Mail erhalten",
@ -274,7 +274,9 @@
"Create the poll": "Umfrage erstellen", "Create the poll": "Umfrage erstellen",
"Your poll will be automatically archived in %d days.": "Ihre Umfrage wird automatisch in %d Tage archiviert werden.", "Your poll will be automatically archived in %d days.": "Ihre Umfrage wird automatisch in %d Tage archiviert werden.",
"You can set a closer archiving date for it.": "Sie können das Datum der Archivierung vorverlegen.", "You can set a closer archiving date for it.": "Sie können das Datum der Archivierung vorverlegen.",
"Archiving date:": "Tag der Archivierung:" "Archiving date:": "Tag der Archivierung:",
"Your poll will automatically be archived": "DE_Your poll will automatically be archived",
"after the last date of your poll.": "DE_after the last date of your poll."
}, },
"Admin": { "Admin": {
"Back to administration": "Zurück zur Verwaltung", "Back to administration": "Zurück zur Verwaltung",
@ -350,17 +352,21 @@
"The name you've chosen already exist in this poll!": "Der von Ihnen eingegebenen Name existiert schon in dieser Umfrage", "The name you've chosen already exist in this poll!": "Der von Ihnen eingegebenen Name existiert schon in dieser Umfrage",
"Enter a name and a comment!": "Geben Sie einen Namen und ein Kommentar ein!", "Enter a name and a comment!": "Geben Sie einen Namen und ein Kommentar ein!",
"Failed to insert the comment!": "Einfügen des Kommentars gescheitert!", "Failed to insert the comment!": "Einfügen des Kommentars gescheitert!",
"Failed to delete the vote!": "DE_Échec de la suppression du vote !",
"Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate ist nicht richtig installiert. Bevor Sie fortfahren, beachten Sie bitte die Angaben zum Aufsetzen der Datenbank in \"INSTALL\".", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate ist nicht richtig installiert. Bevor Sie fortfahren, beachten Sie bitte die Angaben zum Aufsetzen der Datenbank in \"INSTALL\".",
"Failed to save poll": "Speichern der Umfrage fehlgeschlagen", "Failed to save poll": "Speichern der Umfrage fehlgeschlagen",
"Update vote failed": "Aktualisierung der Wertung fehlgeschlagen", "Update vote failed": "Aktualisierung der Wertung fehlgeschlagen",
"Adding vote failed": "Stimmabgabe fehlgeschlagen", "Adding vote failed": "Stimmabgabe fehlgeschlagen",
"You already voted": "DE_Vous avez déjà voté",
"Poll has been updated before you vote": "DE_Le sondage a été mis à jour avant votre vote",
"Comment failed": "Abgabe des Kommentars gescheitert", "Comment failed": "Abgabe des Kommentars gescheitert",
"You can't create a poll with hidden results with the following edition option:": "Sie können mit der folgenden Editier-Option keine Umfrage mit versteckten Ergebnissen erzeugen:", "You can't create a poll with hidden results with the following edition option:": "Sie können mit der folgenden Editier-Option keine Umfrage mit versteckten Ergebnissen erzeugen:",
"Failed to delete column": "Löschen der Spalte fehlgeschlagen", "Failed to delete column": "Löschen der Spalte fehlgeschlagen",
"The column already exists": "DE_La colonne existe déjà",
"MISSING_VALUES": "Fehlende Werte", "MISSING_VALUES": "Fehlende Werte",
"CANT_CONNECT_TO_DATABASE": "Kann nicht mit der Datenbank verbinden", "CANT_CONNECT_TO_DATABASE": "Kann nicht mit der Datenbank verbinden",
"Password is empty": "DE_Le mot de passe est vide.", "Password is empty": "DE_Le mot de passe est vide.",
"Passwords do not match": "DE_Les mot de passes ne correspondent pas." "Passwords do not match": "DE_Les mot de passes ne correspondent pas.",
"Poll id already used": "DE_L'identifiant est déjà utilisé"
} }
} }

View File

@ -66,7 +66,7 @@
}, },
"Homepage": { "Homepage": {
"Schedule an event": "Schedule an event", "Schedule an event": "Schedule an event",
"Make a classic poll": "Make a classic poll", "Make a classic poll": "Make a standard poll",
"Where are my polls": "Where are my polls?" "Where are my polls": "Where are my polls?"
}, },
"1st section": { "1st section": {
@ -83,28 +83,28 @@
"2nd section": { "2nd section": {
"The software": "The software", "The software": "The software",
"Framadate was initially based on ": "Framadate was initially based on ", "Framadate was initially based on ": "Framadate was initially based on ",
"a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "software developed by the University of Strasbourg. These days, it is developed by the Framasoft association.", "a software developed by the University of Strasbourg. Today, it is developed by Framasoft association.": "software developed by the University of Strasbourg. These days, it is developed by the Framasoft association.",
"This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "This software needs JavaScript and cookies enabled. It is compatible with the following web browsers:", "This software needs JavaScript and cookies enabled. It is compatible with the following web browsers:": "This software needs JavaScript and cookies enabled. It is compatible with the following web browsers:",
"It is governed by the": "Framadate is licensed under the", "It is governed by the": "Framadate is licensed under the",
"CeCILL-B license": "CeCILL-B license" "CeCILL-B license": "CeCILL-B license"
}, },
"3rd section": { "3rd section": {
"Cultivate your garden": "Cultivate your garden", "Cultivate your garden": "Grow your own",
"To participate in the software development, suggest improvements or simply download it, please visit ": "To participate in the software development, suggest improvements or simply download it, please visit ", "To participate in the software development, suggest improvements or simply download it, please visit ": "To participate in the software development, suggest improvements or simply download it, please visit ",
"the development site": "the development site", "the development site": "the development site",
"If you want to install the software for your own use and thus increase your independence, we help you on:": "If you want to install the software for your own use and thus increase your independence, we can help you at:" "If you want to install the software for your own use and thus increase your independence, we help you on:": "If you want to install the software for your own use and thus increase your independence, we can help you at:"
}, },
"PollInfo": { "PollInfo": {
"Remove the poll": "Remove the poll", "Remove the poll": "Remove the poll",
"Remove all the comments": "Remove all the comments", "Remove all the comments": "Remove all comments",
"Remove all the votes": "Remove all the votes", "Remove all the votes": "Remove all votes",
"Print": "Print", "Print": "Print",
"Export to CSV": "Export to CSV", "Export to CSV": "Export to CSV",
"Title": "Title of the poll", "Title": "Title of the poll",
"Edit the title": "Edit title", "Edit the title": "Edit title",
"Save the new title": "Save the new title", "Save the new title": "Save the new title",
"Cancel the title edit": "Cancel the title edit", "Cancel the title edit": "Cancel the title edit",
"Initiator of the poll": "Initiator of the poll", "Initiator of the poll": "Creator of the poll",
"Edit the name": "Edit name", "Edit the name": "Edit name",
"Save the new name": "Save the new name", "Save the new name": "Save the new name",
"Cancel the name edit": "Cancel the name edit", "Cancel the name edit": "Cancel the name edit",
@ -124,17 +124,14 @@
"Poll rules": "Poll rules", "Poll rules": "Poll rules",
"Edit the poll rules": "Edit the poll rules", "Edit the poll rules": "Edit the poll rules",
"Votes and comments are locked": "Votes and comments are locked", "Votes and comments are locked": "Votes and comments are locked",
"Votes and comments are open": "Votes and comments are open",
"Votes are editable": "Votes are modifiable",
"Votes are editable solely by their owner.": "Votes can only be edited by their owner",
"Save the new rules": "Save the new rules", "Save the new rules": "Save the new rules",
"Cancel the rules edit": "Cancel the rules edit", "Cancel the rules edit": "Cancel the rules edit",
"Results are hidden.": "Results are hidden.", "Results are hidden": "Results are hidden",
"Results are visible.": "Results are visible.", "Results are visible": "Results are visible",
"Password protected.": "Password protected.", "Password protected": "Password protected",
"Votes protected by password.": "Votes protected by password.", "Votes protected by password": "Votes protected by password",
"No password.": "No password.", "No password": "No password",
"Remove password.": "Remove password." "Remove password": "Remove password"
}, },
"Poll results": { "Poll results": {
"Votes of the poll": "Votes", "Votes of the poll": "Votes",
@ -221,7 +218,10 @@
"You are in the poll creation section.": "You are in the poll creation section.", "You are in the poll creation section.": "You are in the poll creation section.",
"Required fields cannot be left blank.": "Required fields cannot be left blank.", "Required fields cannot be left blank.": "Required fields cannot be left blank.",
"Poll title": "Poll title", "Poll title": "Poll title",
"Votes cannot be modified.": "Votes cannot be modified", "Poll id": "Identifier",
"Poll id rules": "The identifier can contain letters, numbers and dashes \"-\".",
"Poll id warning": "By defining an identifier that can facilitate access to the poll for unwanted people. It is recommended to protect it with a password.",
"Votes cannot be modified": "Votes cannot be modified",
"All voters can modify any vote": "All voters can modify any vote", "All voters can modify any vote": "All voters can modify any vote",
"Voters can modify their vote themselves": "Voters can modify their vote themselves", "Voters can modify their vote themselves": "Voters can modify their vote themselves",
"To receive an email for each new vote": "Receive an email for each new vote", "To receive an email for each new vote": "Receive an email for each new vote",
@ -274,7 +274,9 @@
"Create the poll": "Create the poll", "Create the poll": "Create the poll",
"Your poll will be automatically archived in %d days.": "Your poll will be automatically archived in %d days.", "Your poll will be automatically archived in %d days.": "Your poll will be automatically archived in %d days.",
"You can set a closer archiving date for it.": "You can set a specific expiry date for the poll.", "You can set a closer archiving date for it.": "You can set a specific expiry date for the poll.",
"Archiving date:": "Expiry date:" "Archiving date:": "Expiry date:",
"Your poll will automatically be archived": "Your poll will automatically be archived",
"after the last date of your poll.": "after the last date of your poll."
}, },
"Admin": { "Admin": {
"Back to administration": "Back to administration", "Back to administration": "Back to administration",
@ -350,16 +352,21 @@
"The name you've chosen already exist in this poll!": "The name you've chosen already exists in this poll!", "The name you've chosen already exist in this poll!": "The name you've chosen already exists in this poll!",
"Enter a name and a comment!": "Enter a name and a comment!", "Enter a name and a comment!": "Enter a name and a comment!",
"Failed to insert the comment!": "Failed to insert the comment!", "Failed to insert the comment!": "Failed to insert the comment!",
"Failed to delete the vote!": "Failed to delete the vote!",
"Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate is not properly installed, please see the 'INSTALL' file for instructions on setting up the database before continuing.", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate is not properly installed, please see the 'INSTALL' file for instructions on setting up the database before continuing.",
"Failed to save poll": "Failed to save poll", "Failed to save poll": "Failed to save poll",
"Update vote failed": "Update vote failed", "Update vote failed": "Update vote failed",
"Adding vote failed": "Adding vote failed", "Adding vote failed": "Adding vote failed",
"You already voted": "You already voted",
"Poll has been updated before you vote": "Poll has been updated before you vote",
"Comment failed": "Comment failed", "Comment failed": "Comment failed",
"You can't create a poll with hidden results with the following edition option:": "You can't create a poll with hidden results with the following option: ", "You can't create a poll with hidden results with the following edition option:": "You can't create a poll with hidden results with the following option: ",
"Failed to delete column": "Failed to delete column", "Failed to delete column": "Failed to delete column",
"The column already exists": "The column already exists",
"MISSING_VALUES": "Missing values", "MISSING_VALUES": "Missing values",
"CANT_CONNECT_TO_DATABASE": "Unable to connect to database", "CANT_CONNECT_TO_DATABASE": "Unable to connect to database",
"Password is empty": "Password is empty.", "Password is empty": "Password is empty.",
"Passwords do not match": "Passwords do not match." "Passwords do not match": "Passwords do not match.",
"Poll id already used": "Identifier is already used"
} }
} }

View File

@ -1,169 +1,169 @@
{ {
"Generic": { "Generic": {
"Make your polls": "Encuestas para la universidad", "Make your polls": "Cree sus encuestas",
"Home": "Inicio", "Home": "Inicio",
"Poll": "ES_Sondage", "Poll": "Encuesta",
"Save": "ES_Enregistrer", "Save": "Guardar",
"Cancel": "Cancelar", "Cancel": "Cancelar",
"Add": "Añadir", "Add": "Añadir",
"Remove": "ES_Effacer", "Remove": "Borrar",
"Validate": "ES_Valider", "Validate": "Validar",
"Edit": "Cambio", "Edit": "Cambio",
"Next": "Seguir", "Next": "Seguir",
"Back": "ES_Précédent", "Back": "Volver",
"Close": "ES_Fermer", "Close": "Cerrar",
"Your name": "Su nombre", "Your name": "Su nombre",
"Your email address": "Su dirección electrónica ", "Your email address": "Su dirección electrónica ",
"(in the format name@mail.com)": "ES_(au format nom@mail.com)", "(in the format name@mail.com)": "(en el formato nombre@correo.com)",
"Description": "ES_Description", "Description": "Descripción",
"Back to the homepage of": "Retroceder al inicio de", "Back to the homepage of": "Retroceder al inicio de",
"days": "ES_jours", "days": "días",
"months": "ES_mois", "months": "meses",
"Day": "ES_Jour", "Day": "Día",
"Time": "Horario", "Time": "Hora",
"with": "ES_avec", "with": "con",
"vote": "voto", "vote": "voto",
"votes": "votos", "votes": "votos",
"for": "por", "for": "para",
"Yes": "ES_Oui", "Yes": "Si",
"Ifneedbe": "ES_Si nécessaire", "Ifneedbe": "En caso de ser necesario",
"No": "ES_Non", "No": "No",
"Legend:": "ES_Légende :", "Legend:": "Leyenda:",
"Date": "ES_Date", "Date": "Fecha",
"Classic": "ES_Classique", "Classic": "Clásico",
"Page generated in": "ES_Page générée en", "Page generated in": "Página generada en",
"seconds": "ES_secondes", "seconds": "segundos",
"Choice": "Opciòn", "Choice": "Opción",
"Link": "ES_Lien", "Link": "Enlace",
"Search": "Búsqueda", "Search": "Búsqueda",
"Creation date:": "ES_Date de création :", "Creation date:": "Fecha de creación:",
"Caption": "Leyenda", "Caption": "Leyenda",
"ASTERISK": "*" "ASTERISK": "*"
}, },
"Date": { "Date": {
"dd/mm/yyyy": "ES_jj/mm/aaaa", "dd/mm/yyyy": "dd/mm/aaaa",
"datepicker": "yyyy-mm-dd", "datepicker": "yyyy-mm-dd",
"datetime_parseformat": "Y-m-d", "datetime_parseformat": "Y-m-d",
"%A, den %e. %B %Y": "%A %e de %B %Y", "%A, den %e. %B %Y": "%A %e de %B de %Y",
"FULL": "ES_%A, den %e. %B %Y", "FULL": "%A, %e de %B de %Y",
"SHORT": "ES_%A %e %B %Y", "SHORT": "%A %e %B %Y",
"DAY": "ES_%a %e", "DAY": "%a %e",
"DATE": "ES_%Y-%m-%d", "DATE": "%d-%m-%Y",
"MONTH_YEAR": "ES_%B %Y", "MONTH_YEAR": "%B de %Y",
"DATETIME": "%d/%m/%Y %H:%M", "DATETIME": "%d/%m/%Y %H:%M",
"Add range dates": "ES_Ajout d'un intervalle de dates", "Add range dates": "ES_Ajout d'un intervalle de dates",
"Start date": "ES_Date de début", "Start date": "ES_Date de début",
"End date": "ES_Date de fin" "End date": "ES_Date de fin"
}, },
"Language selector": { "Language selector": {
"Select the language": "ES_Choisir la langue", "Select the language": "Elegir el idioma",
"Change the language": "ES_Changer la langue" "Change the language": "Cambiar el idioma"
}, },
"Homepage": { "Homepage": {
"Schedule an event": "Encuesta para planificar un evento", "Schedule an event": "Planificar un evento",
"Make a classic poll": "ES_Créer un sondage classique", "Make a classic poll": "Crear una encuesta clásica",
"Where are my polls": "ES_Où sont mes sondages ?" "Where are my polls": "¿Dónde están mis encuestas?"
}, },
"Maintenance": { "Maintenance": {
"The application": "ES_L'application", "The application": "La aplicación",
"is currently under maintenance.": "ES_est en cours de maintenance.", "is currently under maintenance.": "se encuentra en mantenimiento.",
"Thank you for your understanding.": "ES_Merci de votre compréhension." "Thank you for your understanding.": "Gracias por su comprensión."
}, },
"1st section": { "1st section": {
"What is that?": "ES_Prise en main", "What is that?": "¿De que se trata?",
"Framadate is an online service for planning an appointment or make a decision quickly and easily. No registration is required.": "ES_Framadate est un service en ligne permettant de planifier un rendez-vous ou prendre des décisions rapidement et simplement. Aucune inscription préalable nest nécessaire.", "Framadate is an online service for planning an appointment or make a decision quickly and easily. No registration is required.": "Framadate es un servicio en línea que permite planificar un encuentro o tomar decisiones rapidamente y de manera sencilla. No es necesario registrarse.",
"Here is how it works:": "ES_Voici comment ça fonctionne :", "Here is how it works:": "Así funciona:",
"Make a poll": "Crear una encuesta", "Make a poll": "Crear una encuesta",
"Define dates or subjects to choose": "ES_Déterminez les dates ou les sujets à choisir", "Define dates or subjects to choose": "Definir las fechas o los temas a elegir",
"Send the poll link to your friends or colleagues": "ES_Envoyez le lien du sondage à vos amis ou collègues", "Send the poll link to your friends or colleagues": "Enviar el enlace de la encuesta a sus amigos o colegas",
"Discuss and make a decision": "ES_Discutez et prenez votre décision", "Discuss and make a decision": "Discutan y toman una decisión",
"Do you want to": "ES_Voulez-vous", "Do you want to": "¿Quiere",
"view an example?": "ES_voir un exemple ?" "view an example?": "ver un ejemplo?"
}, },
"2nd section": { "2nd section": {
"The software": "ES_Le logiciel", "The software": "El software",
"Framadate was initially based on ": "ES_Framadate est initialement basé sur ", "Framadate was initially based on ": "Framadate esta basado sobre",
"a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "ES_ un logiciel développé par l'Université de Strasbourg. Aujourd'hui, son développement est assuré par lassociation Framasoft.", "a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "un software desarrollado por la Universidad de Estrasburgo. Ahora, su desarrollo esta realizado por la asociación Framasoft.",
"This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "ES_Ce logiciel requiert lactivation du javascript et des cookies. Il est compatible avec les navigateurs web suivants :", "This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Este software requiere activar javascript y los cookies. Es compatible con los siguientes navegadores:",
"It is governed by the": "ES_Il est régi par la", "It is governed by the": "Se encuentra bajo la",
"CeCILL-B license": "ES_licence CeCILL-B" "CeCILL-B license": "licencia CeCILL-B"
}, },
"3rd section": { "3rd section": {
"Cultivate your garden": "ES_Cultivez votre jardin", "Cultivate your garden": "Cultive su jardín",
"To participate in the software development, suggest improvements or simply download it, please visit ": "ES_Pour participer au développement du logiciel, proposer des améliorations ou simplement le télécharger, rendez-vous sur ", "To participate in the software development, suggest improvements or simply download it, please visit ": "Para participar del desarrollo del software, proponer mejoras o simplemente descargarlo, ir a",
"the development site": "ES_le site de développement", "the development site": "la página de desarrollo",
"If you want to install the software for your own use and thus increase your independence, we help you on:": "ES_Si vous souhaitez installer ce logiciel pour votre propre usage et ainsi gagner en autonomie, nous vous aidons sur :" "If you want to install the software for your own use and thus increase your independence, we help you on:": "Si quiere instalar este software para su propio uso y de esta manera ganar en autonomía, nos puede ayudar en:"
}, },
"PollInfo": { "PollInfo": {
"Remove the poll": "Borrada de encuesta", "Remove the poll": "Borrar la encuesta",
"Remove all the comments": "ES_Supprimer tous les commentaires", "Remove all the comments": "Borrar todos los comentarios",
"Remove all the votes": "ES_Supprimer tous les votes", "Remove all the votes": "Borrar todos los votos",
"Print": "ES_Imprimer", "Print": "Imprimir",
"Export to CSV": "ES_Export en CSV", "Export to CSV": "Exportar en CSV",
"Title": "ES_Titre du sondage", "Title": "Título de la encuesta",
"Edit the title": "ES_Modifier le titre", "Edit the title": "Modificar el título",
"Save the new title": "ES_Enregistrer le nouveau titre", "Save the new title": "Guardar el nuevo título",
"Cancel the title edit": "ES_Annuler le changement de titre", "Cancel the title edit": "Cancelar el cambio de título",
"Initiator of the poll": "Autor dela encuesta", "Initiator of the poll": "Autor de la encuesta",
"Edit the name": "ES_Modification de l'auteur", "Edit the name": "Modificar el autor",
"Save the new name": "ES_Enregistrer l'auteur", "Save the new name": "Guardar el autor",
"Cancel the name edit": "ES_Annuler le changement d'auteur", "Cancel the name edit": "Cancelar el cambio de autor",
"Email": "ES_Courriel", "Email": "Correo electrónico",
"Edit the email adress": "ES_Modifier le courriel", "Edit the email adress": "Modificar el correo electrónico",
"Save the email address": "ES_Enregistrer le courriel", "Save the email address": "Guardar el correo electrónico",
"Cancel the email address edit": "ES_Annuler le changement de courriel", "Cancel the email address edit": "Cancelar el cambio de correo electrónico",
"Edit the description": "ES_Modifier la description", "Edit the description": "Modificar la descripción",
"Save the description": "ES_Enregistrer la description", "Save the description": "Guardar la descripción",
"Cancel the description edit": "ES_Annuler le changement de description", "Cancel the description edit": "Cancelar el cambio de descripción",
"Public link of the poll": "ES_Lien public du sondage", "Public link of the poll": "Enlace público de la encuesta",
"Admin link of the poll": "ES_Lien d'administration du sondage", "Admin link of the poll": "Enlace de administración de la encuesta",
"Expiration date": "ES_Date d'expiration", "Expiration date": "Fecha de expiración",
"Edit the expiration date": "ES_Modifier la date d'expiration", "Edit the expiration date": "Modificar la fecha de expiración",
"Save the new expiration date": "ES_Enregistrer la date d'expiration", "Save the new expiration date": "Guardar la fecha de expiración",
"Cancel the expiration date edit": "ES_Annuler le changement de date d'expiration", "Cancel the expiration date edit": "Cancelar el cambio de fecha de expiración",
"Poll rules": "ES_Permissions du sondage", "Poll rules": "Permisos de la encuesta",
"Edit the poll rules": "ES_Modifier les permissions du sondage", "Edit the poll rules": "Modificar los permisos de la encuesta",
"Votes and comments are locked": "ES_Les votes et commentaires sont verrouillés", "Votes and comments are locked": "Los votos y comentarios están bloqueados",
"Votes and comments are open": "ES_Les votes et commentaires sont ouverts", "Votes and comments are open": "ES_Les votes et commentaires sont ouverts",
"Votes are editable": "ES_Les votes sont modifiables", "Votes are editable": "ES_Les votes sont modifiables",
"Votes are editable solely by their owner.": "ES_Les votes sont modifiables uniquement par leur créateur", "Votes are editable solely by their owner.": "ES_Les votes sont modifiables uniquement par leur créateur",
"Save the new rules": "ES_Enregistrer les nouvelles permissions", "Save the new rules": "ES_Enregistrer les nouvelles permissions",
"Cancel the rules edit": "ES_Annuler le changement de permissions", "Cancel the rules edit": "ES_Annuler le changement de permissions",
"Results are hidden.": "ES_Les résultats sont cachés.", "Results are hidden": "Los resutaldos no son visibles",
"Results are visible.": "ES_Les résultats sont visibles.", "Results are visible": "Los resultados son visibles",
"Password protected.": "ES_Protégé par mot de passe.", "Password protected": "ES_Protégé par mot de passe",
"Votes protected by password.": "ES_Votes protégés par mot de passe.", "Votes protected by password": "ES_Votes protégés par mot de passe",
"No password.": "ES_Pas de mot de passe", "No password": "ES_Pas de mot de passe",
"Remove password.": "ES_Supprimer le mot de passe." "Remove password": "ES_Supprimer le mot de passe"
}, },
"Poll results": { "Poll results": {
"Votes of the poll": "ES_Votes du sondage", "Votes of the poll": "Votos de la encuesta",
"Edit the line:": "ES_Modifier la ligne :", "Edit the line:": "Modificar la fila:",
"Remove the line:": "ES_Supprimer la ligne :", "Remove the line:": "Borrar la fila:",
"Vote no for": "ES_Voter « non » pour", "Vote no for": "Votar « no » para",
"Vote yes for": "ES_Voter « oui » pour", "Vote yes for": "Votar « si » para",
"Vote ifneedbe for": "ES_Voter « Si nécessaire » pour", "Vote ifneedbe for": "Votar « en caso de ser necesario » para",
"Save the choices": "ES_Enregister les choix", "Save the choices": "Guardar los cambios",
"Addition": "Suma", "Addition": "Suma",
"Best choice": "ES_Meilleur choix", "Best choice": "Mejor elección",
"Best choices": "ES_Meilleurs choix", "Best choices": "Mejores elecciones",
"The best choice at this time is:": "ES_Le meilleur choix pour l'instant est :", "The best choice at this time is:": "La mejor elección a la fecha es:",
"The bests choices at this time are:": "ES_Les meilleurs choix pour l'instant sont :", "The bests choices at this time are:": "Las mejores elecciones a la fecha son:",
"Scroll to the left": "ES_Faire défiler à gauche", "Scroll to the left": "Hacer desfilar hacia la izquierda",
"Scroll to the right": "ES_Faire défiler à droite", "Scroll to the right": "Hacer desfilar hacia la derecha",
"polled user": "ES_votant", "polled user": "Votante",
"polled users": "ES_votants", "polled users": "Votantes",
"Display the chart of the results": "ES_Afficher le graphique des résultats", "Display the chart of the results": "Mostrar el gráfico de resultados",
"Chart": "ES_Graphique" "Chart": "Gráfico"
}, },
"Comments": { "Comments": {
"Comments of polled people": "ES_Commentaires de sondés", "Comments of polled people": "Comentarios de los votantes",
"Remove the comment": "ES_Supprimer le commentaire", "Remove the comment": "Borrar el comentario",
"Add a comment to the poll": "ES_Ajouter un commentaire au sondage", "Add a comment to the poll": "Añadir un comentario a la encuesta",
"Your comment": "ES_Votre commentaire", "Your comment": "Su comentario",
"Send the comment": "ES_Envoyer le commentaire", "Send the comment": "Enviar el comentario",
"anonyme": "ES_anonyme", "anonyme": "anónimo",
"Comment added": "ES_Commentaire ajouté" "Comment added": "Comentario añadido"
}, },
"Password": { "Password": {
"Password": "ES_Mot de passe", "Password": "ES_Mot de passe",
@ -173,194 +173,200 @@
"You have to provide a password so you can participate to the poll.": "ES_Vous devez donner le mot de passe pour pouvoir participer à ce sondage." "You have to provide a password so you can participate to the poll.": "ES_Vous devez donner le mot de passe pour pouvoir participer à ce sondage."
}, },
"studs": { "studs": {
"If you want to vote in this poll, you have to give your name, choose the values that fit best for you and validate with the plus button at the end of the line.": "Para participar a esta encuesta, introduzca su nombre, elige todas las valores que son apriopriadas y validar su seleccion con el botón verde a la fin de línea.", "If you want to vote in this poll, you have to give your name, choose the values that fit best for you and validate with the plus button at the end of the line.": "Para participar a esta encuesta, introduzca su nombre, elija las opciones que le parezcan más adecuadas, y valide con el botón MÁS al fin de fila.",
"POLL_LOCKED_WARNING": "ES_L'administrateur a verrouillé ce sondage. Les votes et commentaires sont gelés, il n'est plus possible de participer", "POLL_LOCKED_WARNING": "La persona a cargo de la administración bloqueó esta encuesta. Los votos y comentarios están bloqueados, ya no se permite participar.",
"The poll is expired, it will be deleted soon.": "ES_Le sondage a expiré, il sera bientôt supprimé.", "The poll is expired, it will be deleted soon.": "La encuesta expiró, pronto desaparecerá.",
"Deletion date:": "ES_Date de suppression :", "Deletion date:": "Fecha de supresión:",
"Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:": "ES_Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez le précieusement ! ", "Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:": "Su voto fue guardado, pero tome en cuenta que esta encuesta solo permite modificar su voto a través del enlace siguiente ; ¡conservelo con cuidado!",
"Update vote succeeded": "ES_Mise à jour du vote réussi", "Update vote succeeded": "Actualización exítosa de su voto",
"Adding the vote succeeded": "ES_Ajout du vote réussi" "Adding the vote succeeded": "Voto guardado con exíto"
}, },
"adminstuds": { "adminstuds": {
"As poll administrator, you can change all the lines of this poll with this button": "En calidad de administrador, Usted puede cambiar todas la líneas de este encuesta con este botón", "As poll administrator, you can change all the lines of this poll with this button": "Como administrador, Usted puede cambiar todas las filas de la encuesta con este botón",
"remove a column or a line with": "ES_effacer une colonne ou une ligne avec", "remove a column or a line with": "borrar una columna o una fila con",
"and add a new column with": "ES_et si vous avez oublié de saisir un choix, vous pouvez rajouter une colonne en cliquant sur", "and add a new column with": "y se puede añadir una columna con",
"Finally, you can change the informations of this poll like the title, the comments or your email address.": "Para acabar, Usted puede cambiar las informaciones relativas a su encuesta como el titulo, los comentarios o ademas su dirección electrónica.", "Finally, you can change the informations of this poll like the title, the comments or your email address.": "Finalmente, puede cambiar las informaciones de esta encuesta, como el título, los comentarios o la dirección de correo electrónico.",
"Column's adding": "Añadido de columna", "Column's adding": "Añadir una columna",
"You can add a new scheduling date to your poll.": "ES_Vous pouvez ajouter une date à votre sondage.", "You can add a new scheduling date to your poll.": "Puede añadir una nueva fecha de encuentro a su encuesta.",
"If you just want to add a new hour to an existant date, put the same date and choose a new hour.": "ES_Si vous voulez juste ajouter un horaire à une date existante, mettez la même date et choisissez un autre horaire. Il sera intégré normalement au sondage existant.", "If you just want to add a new hour to an existant date, put the same date and choose a new hour.": "Si solo quiere añadir una nueva hora para una fecha existente, ponga la misma fecha y elija una nueva hora.",
"Confirm removal of the poll": "Confirmar el borrado dela encuesta", "Confirm removal of the poll": "Confirmar la supresión de la encuesta",
"Delete the poll": "ES_Je supprime le sondage", "Delete the poll": "Borrar la encuesta",
"Keep the poll": "ES_Je garde le sondage", "Keep the poll": "Conservar la encuesta",
"Your poll has been removed!": "Su encuesta ha sido borrado!", "Your poll has been removed!": "Su encuesta ha sido borrada",
"Poll saved": "ES_Sondage sauvegardé", "Poll saved": "Encuesta guardada",
"Vote added": "ES_Vote ajouté", "Vote added": "Voto guardado",
"Poll fully deleted": "ES_Sondage complètement supprimé", "Poll fully deleted": "Encuesta borrada definitivamente",
"Vote updated": "ES_Vote mis à jour", "Vote updated": "Voto actualizado",
"Vote deleted": "ES_Vote supprimé", "Vote deleted": "Voto borrado",
"All votes deleted": "ES_Tous les votes ont été supprimés", "All votes deleted": "Todos los votos han sido borrados",
"Back to the poll": "ES_Retour au sondage", "Back to the poll": "Volver a la encuesta",
"Add a column": "ES_Ajouter une colonne", "Add a column": "Añadir una columna",
"Remove the column": "ES_Effacer la colonne", "Remove the column": "Borrar la columna",
"Column removed": "ES_Colonne supprimée", "Column removed": "Columna borrado",
"Choice added": "ES_Choix ajouté", "Choice added": "Elección añadida",
"Confirm removal of all votes of the poll": "ES_Confirmer la suppression de tous les votes de ce sondage", "Confirm removal of all votes of the poll": "Confirma la supresión de todos los votos de la encuesta",
"Keep the votes": "ES_Garder les votes", "Keep the votes": "Conservar los votos",
"Remove the votes": "ES_Supprimer les votes", "Remove the votes": "Borrar los votos",
"Confirm removal of all comments of the poll": "ES_Confirmer la suppression de tous les commentaires de ce sondage", "Confirm removal of all comments of the poll": "Confirmar la supresión de todos los comentarios de la encuesta",
"Keep the comments": "ES_Garder les commentaires", "Keep the comments": "Conservar los comentarios",
"Remove the comments": "ES_Supprimer les commentaires", "Remove the comments": "Borrar los comentarios",
"Comment deleted": "ES_Commentaire supprimé", "Comment deleted": "Comentario borrado",
"All comments deleted": "ES_Tous les commentaires ont été supprimés", "All comments deleted": "Todos los comentarios han sido borrados",
"Keep votes": "ES_Garder les votes", "Keep votes": "Conservar los votos",
"Keep comments": "ES_Garder les commentaires", "Keep comments": "Conservar los comentarios",
"Keep this poll": "Dejar este encuesta!" "Keep this poll": "Conservar esta encuesta"
}, },
"Step 1": { "Step 1": {
"Poll creation (1 on 3)": "ES_Création de sondage (1 sur 3)", "Poll creation (1 on 3)": "Creación de la encuesta (1 de 3)",
"You are in the poll creation section.": "Usted ha eligiendo de crear une nueva encuesta!", "You are in the poll creation section.": "Usted ha eligido crear una nueva encuesta",
"Required fields cannot be left blank.": "Gracias por completar los campos con una *.", "Required fields cannot be left blank.": "Los campos requeridos tienen que ser llenados",
"Poll title": "ES_Titre du sondage", "Poll title": "Título de la encuesta",
"Votes cannot be modified.": "ES_Aucun vote ne peut être modifié", "Votes cannot be modified": "Los votos no pueden ser modificados",
"All voters can modify any vote": "ES_Tous les sondés peuvent modifier tous les votes", "All voters can modify any vote": "Los votos pueden ser modificados por cualquiera",
"Voters can modify their vote themselves": "Los encuentados pueden cambiar su línea ellos mismos", "Voters can modify their vote themselves": "Los votos peuden ser modificados por su autor",
"To receive an email for each new vote": "Usted quiere recibir un correo electónico cada vez que alguien participe a la encuesta", "To receive an email for each new vote": "Recibir un correo electrónico para cada nuevo voto",
"To receive an email for each new comment": "ES_Recevoir un courriel à chaque commentaire", "To receive an email for each new comment": "Recibir un correo electrónico para cada nuevo comentario",
"Only the poll maker can see the poll's results": "ES_Seul le créateur du sondage peut voir les résultats", "Only the poll maker can see the poll's results": "Solo el creador de la encuesta puede ver los resultados",
"Use a password to restrict access": "ES_Utiliser un mot de passe pour restreindre l'accès au sondage", "Use a password to restrict access": "ES_Utiliser un mot de passe pour restreindre l'accès au sondage",
"The results are publicly visible": "ES_Les résultats sont visibles sans mot de passe", "The results are publicly visible": "ES_Les résultats sont visibles sans mot de passe",
"Poll password": "ES_Mot de passe", "Poll password": "ES_Mot de passe",
"Confirm password": "ES_Confirmer votre mot de passe", "Confirm password": "ES_Confirmer votre mot de passe",
"Go to step 2": "ES_Aller à l'étape 2" "Go to step 2": "Ir al paso número 2"
}, },
"Step 2": { "Step 2": {
"Back to step 1": "ES_Revenir à létape 1", "Back to step 1": "Volver al paso número 1",
"Go to step 3": "ES_Aller à létape 3" "Go to step 3": "Ir al paso número 3"
}, },
"Step 2 date": { "Step 2 date": {
"Poll dates (2 on 3)": "ES_Choix des dates (2 sur 3)", "Poll dates (2 on 3)": "Elegir las fechas (2 de 3)",
"Choose the dates of your poll": "ES_Choisissez les dates de votre sondage", "Choose the dates of your poll": "Elija las fechas de su encuesta",
"To schedule an event you need to propose at least two choices (two hours for one day or two days).": "ES_Pour créer un sondage spécial dates vous devez proposer au moins deux choix (deux horaires pour une même journée ou deux jours).", "To schedule an event you need to propose at least two choices (two hours for one day or two days).": "Para programar un evento, tiene que proponer por lo menos dos opciones (dos horarios para un día, o dos días).",
"You can add or remove additionnal days and hours with the buttons": "ES_Vous pouvez ajouter ou supprimer des jours et horaires supplémentaires avec les boutons", "You can add or remove additionnal days and hours with the buttons": "Puede agregar o borrar días y horarios con los botones",
"For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)": "ES_Pour chacun des jours sélectionnés, vous avez la possibilité de choisir ou non, des heures de réunion (par exemple : \"8h\", \"8:30\", \"8h-10h\", \"soir\", etc.)", "For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)": "Para cada día seleccionado, puede elegir o no, horarios de reunión (por ejemplo: \"8:00\", \"8:30\", \"8:00-10:00\", \"noche\", etc.)",
"Remove an hour": "ES_Supprimer le dernier horaire", "Remove an hour": "Borrar el último horario",
"Add an hour": "ES_Ajouter un horaire", "Add an hour": "Añadir un horario",
"Copy hours of the first day": "ES_Reporter les horaires du premier jour sur les autres jours", "Copy hours of the first day": "Copiar los horarios del primer día en los otros días",
"Remove a day": "ES_Supprimer le dernier jour", "Remove a day": "Borrar el último día",
"Add a day": "ES_Ajouter un jour", "Add a day": "Añadir un día",
"Remove all days": "ES_Effacer tous les jours", "Remove all days": "Borrar todos los días",
"Remove all hours": "Borrar todos los horarios" "Remove all hours": "Borrar todos los horarios"
}, },
"Step 2 classic": { "Step 2 classic": {
"Poll subjects (2 on 3)": "ES_Choix des sujets (2 sur 3)", "Poll subjects (2 on 3)": "Elegir los temas (2 de 3)",
"To make a generic poll you need to propose at least two choices between differents subjects.": "ES_Pour créer un sondage classique, vous devez proposer au moins deux choix différents.", "To make a generic poll you need to propose at least two choices between differents subjects.": "Para crear una encueta clásica, dene proponer por lo menos dos opciones.",
"You can add or remove additional choices with the buttons": "ES_Vous pouvez ajouter ou supprimer des choix supplémentaires avec les boutons", "You can add or remove additional choices with the buttons": "Puede añadir o borrar las opciones con los botones",
"It's possible to propose links or images by using": "ES_Il est possible dinsérer des liens ou des images en utilisant ", "It's possible to propose links or images by using": "Se peude proponer enlaces o imágenes utilizando",
"the Markdown syntax": "ES_la syntaxe Markdown", "the Markdown syntax": "la síntaxis Markdown",
"Add a link or an image": "ES_Ajouter un lien ou une image", "Add a link or an image": "Añadir un enlace o una imagen",
"These fields are optional. You can add a link, an image or both.": "ES_Ces champs sont facultatifs. Vous pouvez ajouter un lien, une image ou les deux.", "These fields are optional. You can add a link, an image or both.": "Estos campos son opcionales. Puede añadir un enlace, una imagen, o ambos.",
"URL of the image": "ES_URL de l'image", "URL of the image": "URL de la imagen",
"Alternative text": "ES_Texte alternatif", "Alternative text": "Texto alternativo",
"Remove a choice": "ES_Supprimer le dernier choix", "Remove a choice": "Borrar la opción",
"Add a choice": "ES_Ajouter un choix" "Add a choice": "Añadir una opción"
}, },
"Step 3": { "Step 3": {
"Back to step 2": "ES_Revenir à létape 2", "Back to step 2": "Volver al paso número 2",
"Removal date and confirmation (3 on 3)": "ES_Date d'expiration et confirmation (3 sur 3)", "Removal date and confirmation (3 on 3)": "Fecha de expiración y confirmación (3 de 3)",
"Confirm the creation of your poll": "ES_Confirmez la création de votre sondage", "Confirm the creation of your poll": "Comfirmar la creación de la encuesta",
"List of your choices": "ES_Liste de vos choix", "List of your choices": "Lista de opciones",
"Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.": "ES_Une fois que vous aurez confirmé la création du sondage, vous serez redirigé automatiquement vers la page d'administration de votre sondage.", "Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.": "Una vez confirmada la creación de la encuesta, estará automáticamente redirigido/a hacia la página de administración de su encuesta.",
"Then, you will receive quickly two emails: one contening the link of your poll for sending it to the voters, the other contening the link to the administration page of your poll.": "ES_En même temps, vous recevrez deux courriels : l'un contenant le lien vers votre sondage pour le faire suivre aux futurs sondés, l'autre contenant le lien vers la page d'administration du sondage.", "Then, you will receive quickly two emails: one contening the link of your poll for sending it to the voters, the other contening the link to the administration page of your poll.": "Luego, recibirá en poco tiempo dos correos electrónico: el primero contiene el enlace de la encuesta, para enviar a los votantes, y el segundo contiene el enlace de la página de administración de la encuesta.",
"Create the poll": "Crear la encuesta", "Create the poll": "Crear la encuesta",
"Your poll will be automatically archived in %d days.": "ES_Votre sondage sera automatiquement archivé dans %d jours.", "Your poll will be automatically archived in %d days.": "Su encuesta estará archivada de manera automática en %d días.",
"You can set a closer archiving date for it.": "ES_Vous pouvez décider d'une date d'archivage plus proche.", "You can set a closer archiving date for it.": "Puede definir una otra fecha de archivo.",
"Archiving date:": "ES_Date d'archivage :" "Archiving date:": "Fecha de archivo:",
"Your poll will automatically be archived": "Su encuesta estará archivada de manera automática",
"after the last date of your poll.": "luego de la última fecha de su encuesta."
}, },
"Admin": { "Admin": {
"Back to administration": "ES_Retour à l'administration", "Back to administration": "Volver a la administración",
"Administration": "ES_Administration", "Administration": "Administración",
"Polls": "ES_Sondages", "Polls": "Encuestas",
"Migration": "ES_Migration", "Migration": "Migración",
"Purge": "ES_Purge", "Purge": "Purga",
"Logs": "Histórico", "Logs": "Histórico",
"Installation": "Instalación", "Installation": "Instalación",
"Poll ID": "ES_ID sondage", "Poll ID": "ID de la encuesta",
"Format": "ES_Format", "Format": "Formato",
"Title": "ES_Titre", "Title": "Título",
"Author": "ES_Auteur", "Author": "Autor",
"Email": "ES_Courriel", "Email": "Correo electrónico",
"Expiration date": "ES_Date d'expiration", "Expiration date": "Fecha de expiración",
"Votes": "Votos", "Votes": "Votos",
"Actions": "Acciones", "Actions": "Acciones",
"See the poll": "Ver la encuesta", "See the poll": "Ver la encuesta",
"Change the poll": "Cambiar la encuesta", "Change the poll": "Cambiar la encuesta",
"Deleted the poll": "ES_Supprimer le sondage", "Deleted the poll": "Borrar la encuesta",
"Summary": "ES_Résumé", "Summary": "Resumen",
"Success": "ES_Réussite", "Success": "Exíto",
"Fail": "ES_Échèc", "Fail": "Error",
"Nothing": "ES_Rien", "Nothing": "Nada",
"Succeeded:": "ES_Réussit:", "Succeeded:": "Con éxito:",
"Failed:": "ES_Échoué:", "Failed:": "Con error:",
"Skipped:": "ES_Passé:", "Skipped:": "Omitidos:",
"Pages:": "ES_Pages :", "Pages:": "Páginas:",
"Purged:": "ES_Purgés :", "Purged:": "Purgados:",
"Confirm removal of the poll": "Confirmar el borrado dela encuesta", "Confirm removal of the poll": "Confirmar la supresión de la encuesta",
"polls in the database at this time": "encuestas en la basa por el momento", "polls in the database at this time": "encuestas en la base de datos a la fecha",
"Purge the polls": "ES_Purger les sondages" "Purge the polls": "Purgar las encuestas"
}, },
"FindPolls": { "FindPolls": {
"Here are your polls": "ES_Voici tes sondages", "Here are your polls": "Esas son sus encuestas",
"Send me my polls": "ES_Envoyer mes sondages", "Send me my polls": "Enviarme mis encuestas",
"Polls sent": "ES_Sondages envoyés" "Polls sent": "Encuestas enviadas"
}, },
"Mail": { "Mail": {
"Poll's participation: %s": "Participación Encuesta: %s", "Poll's participation: %s": "Participación a la encuesta: %s",
"Notification of poll: %s": "Notificación de la encuesta: %s", "Notification of poll: %s": "Notificación de la encuesta: %s",
"filled a vote.\nYou can find your poll at the link": "ES_vient de voter.<br/>Vous pouvez retrouver votre sondage avec le lien suivant", "filled a vote.\nYou can find your poll at the link": "acaba de votar.<br/>Puede acceder a la encuesta siguiendo este enlace",
"updated a vote.\nYou can find your poll at the link": "ES_vient de mettre à jour un vote.<br/>Vous pouvez retrouver votre sondage avec le lien suivant", "updated a vote.\nYou can find your poll at the link": "acaba de actualizar su voto.<br/>Puede acceder a la encuesta siguiendo este enlace",
"wrote a comment.\nYou can find your poll at the link": "ES_vient de rédiger un commentaire.<br/>Vous pouvez retrouver votre sondage avec le lien suivant", "wrote a comment.\nYou can find your poll at the link": "acaba de redactar un comentario.<br/>Puede acceder a la encuesta siguiendo este enlace",
"Someone just change your poll available at the following link %s.": "Alguien acaba de cambiar su encuesta disponible en el siguiente enlace <a href=\"%1$s\">%1$s</a>.", "Someone just change your poll available at the following link %s.": "Alguien acaba de modificar su encuesta, disponible en el siguiente enlace <a href=\"%1$s\">%1$s</a>.",
"Someone just delete your poll %s.": "Alguien acaba de borrar tu encuesta \"%s\".", "Someone just delete your poll %s.": "Alguien acaba de borrar su encuesta \"%s\".",
"Thanks for your trust.": "ES_Merci de votre confiance.", "Thanks for your trust.": "Gracias por su confianza.",
"FOOTER": "", "FOOTER": "",
"[ADMINISTRATOR] New settings for your poll": "ES_[ADMINISTRATEUR] Changement de configuration du sondage", "[ADMINISTRATOR] New settings for your poll": "[ADMINISTRACIÓN] Cambio de configuración de la encuesta",
"You have changed the settings of your poll. \nYou can modify this poll with this link": "ES_Vous avez modifié la configuration de votre sondage.<br/>Vous pouvez modifier ce sondage avec le lien suivant", "You have changed the settings of your poll. \nYou can modify this poll with this link": "Acaba de cambiar los parámetros de su encuestra.<br/>Puede seguir modificando la encuesta siguiendo este enlace",
"This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "ES_Ceci est le message qui doit être envoyé aux sondés.<br/>Vous pouvez maintenant transmettre ce message à toutes les personnes susceptibles de participer au vote.", "This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Este es el mensaje que puede enviar a todos los votantes.<br/>Ahora puede transmitir Voueste mensaje para todas las personas susceptibles de participar al voto.",
"hast just created a poll called": "ES_ vient de créer un sondage intitulé ", "hast just created a poll called": "acaba de crear la encuesta llamada ",
"Thanks for filling the poll at the link above": "ES_Merci de bien vouloir participer au sondage à l'adresse suivante", "Thanks for filling the poll at the link above": "Gracias por ir a llenar la encuesta siguiendo este enlace",
"This message should NOT be sent to the polled people. It is private for the poll's creator.\n\nYou can now modify it at the link above": "ES_Ce message ne doit PAS être diffusé aux sondés. Il est réservé à l'auteur du sondage.<br/><br/>Vous pouvez modifier ce sondage à l'adresse suivante ", "This message should NOT be sent to the polled people. It is private for the poll's creator.\n\nYou can now modify it at the link above": "Este mensaje NO tiene que ser difundido a los votantes. Es reservado para el autor de la encuesta.<br/><br/>Puede modificar esta encuesta en el enlace siguiente ",
"Author's message": "Reservado al autor", "Author's message": "Reservado al autor",
"For sending to the polled users": "ES_Pour diffusion aux sondés" "For sending to the polled users": "Para difusión a los votantes"
}, },
"Error": { "Error": {
"Error!": "Error!", "Error!": "¡Error!",
"Enter a title": "Introducza un título", "Enter a title": "Introducza un título",
"Something is going wrong...": "Algo va mal...", "Something is going wrong...": "Algo anda mal...",
"Something is wrong with the format": "Algo está mal con el formato", "Something is wrong with the format": "Algo está mal con el formato",
"Enter an email address": "Introduzca una dirección electrónica", "Enter an email address": "Introduzca un correo electrónico",
"The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.": "ES_L'adresse saisie n'est pas correcte ! Il faut une adresse électronique valide (par exemple r.stallman@outlock.com) pour recevoir le lien vers le sondage.", "The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.": "El correo electrónico es incorrecto. Tiene que introducir una dirección cálida (por ejemplo r.stallman@outlook.com) para recibir el enlace de su encuesta.",
"No polls found": "ES_Aucun sondage n'a été trouvé", "No polls found": "Ninguna encuesta encontrada",
"There is a problem with your choices": "ES_Il y a un problème avec vos choix", "There is a problem with your choices": "Existe un problema con sus opciones",
"You haven't filled the first section of the poll creation.": "Usted no habia llenado la primera pagina dela encuesta", "You haven't filled the first section of the poll creation.": "Usted no llenó la primera parte de la encuesta",
"Javascript is disabled on your browser. Its activation is required to create a poll.": "ES_Javascript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", "Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript esta desactivado en su navegador. Se requiere activarlo para crear una encuesta.",
"Cookies are disabled on your browser. Theirs activation is required to create a poll.": "ES_Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.", "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Los cookies están desactivados en su navegador. Se requiere activarlos para crear una encuesta.",
"This poll doesn't exist !": "Este encuesta no existe!", "This poll doesn't exist !": "Esta encuesta no existe",
"Enter a name": "Introduzca un nombre", "Enter a name": "Introduzca un nombre",
"The name is invalid.": "ES_Le nom n'est pas valide.", "The name is invalid.": "Este nombre es invalido.",
"The name you've chosen already exist in this poll!": "El nombre entrado existe ya!", "The name you've chosen already exist in this poll!": "El nombre que eligió ya existe en la encuesta",
"Enter a name and a comment!": "Introduzca su nombre y un comentario!", "Enter a name and a comment!": "Introduzca su nombre y un comentario",
"Failed to insert the comment!": "ES_Échec à l'insertion du commentaire !", "Failed to insert the comment!": "Error al crear el comentario",
"Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "ES_Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", "Failed to delete the vote!": "Error al borrar el voto",
"Failed to save poll": "ES_Echec de la sauvegarde du sondage", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate no esta instalado correctamente, leer el archivo INSTALL para configurar la base de datos antes de continuar.",
"Update vote failed": "ES_Mise à jour du vote échoué", "Failed to save poll": "Error al guardar la encuesta",
"Adding vote failed": "ES_Ajout d'un vote échoué", "Update vote failed": "Error al actualizar el voto",
"Comment failed": "ES_Commentaire échoué", "Adding vote failed": "Error al crear el voto",
"You can't create a poll with hidden results with the following edition option:": "ES_Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ", "You already voted": "Usted ya votó",
"Poll has been updated before you vote": "La encuesta fue actualizada antes de su voto",
"Comment failed": "Error al crear el comentario",
"You can't create a poll with hidden results with the following edition option:": "No puede crear una encuesta con resultados no visibles con los siguientes opciones de edición",
"Failed to delete column": "Error al eliminar la columna", "Failed to delete column": "Error al eliminar la columna",
"MISSING_VALUES": "Los valores perdidos", "The column already exists": "La columna ya existe",
"MISSING_VALUES": "Valores inexistentes",
"CANT_CONNECT_TO_DATABASE": "No se puede conectar a la base de datos", "CANT_CONNECT_TO_DATABASE": "No se puede conectar a la base de datos",
"Password is empty": "ES_Le mot de passe est vide.", "Password is empty": "ES_Le mot de passe est vide.",
"Passwords do not match": "ES_Les mot de passes ne correspondent pas." "Passwords do not match": "ES_Les mot de passes ne correspondent pas.",
"Poll id already used": "ES_L'identifiant est déjà utilisé"
} }
} }

View File

@ -84,7 +84,7 @@
"The software": "Le logiciel", "The software": "Le logiciel",
"Framadate was initially based on ": "Framadate est initialement basé sur ", "Framadate was initially based on ": "Framadate est initialement basé sur ",
"a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "un logiciel développé par l'Université de Strasbourg. Aujourd'hui, son développement est assuré par lassociation Framasoft.", "a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "un logiciel développé par l'Université de Strasbourg. Aujourd'hui, son développement est assuré par lassociation Framasoft.",
"This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Ce logiciel requiert lactivation du javascript et des cookies. Il est compatible avec les navigateurs web suivants :", "This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Ce logiciel requiert lactivation du JavaScript et des cookies. Il est compatible avec les navigateurs web suivants :",
"It is governed by the": "Il est régi par la", "It is governed by the": "Il est régi par la",
"CeCILL-B license": "licence CeCILL-B" "CeCILL-B license": "licence CeCILL-B"
}, },
@ -123,18 +123,15 @@
"Cancel the expiration date edit": "Annuler le changement de date d'expiration", "Cancel the expiration date edit": "Annuler le changement de date d'expiration",
"Poll rules": "Permissions du sondage", "Poll rules": "Permissions du sondage",
"Edit the poll rules": "Modifier les permissions du sondage", "Edit the poll rules": "Modifier les permissions du sondage",
"Votes and comments are locked": "Les votes et commentaires sont verrouillés", "Votes and comments are locked": "Il n'est plus possible de voter",
"Votes and comments are open": "Les votes et commentaires sont ouverts",
"Votes are editable": "Les votes sont modifiables",
"Votes are editable solely by their owner.": "Les votes sont modifiables uniquement par leur créateur",
"Save the new rules": "Enregistrer les nouvelles permissions", "Save the new rules": "Enregistrer les nouvelles permissions",
"Cancel the rules edit": "Annuler le changement de permissions", "Cancel the rules edit": "Annuler le changement de permissions",
"Results are hidden.": "Les résultats sont cachés.", "Results are hidden": "Les résultats sont cachés",
"Results are visible.": "Les résultats sont visibles.", "Results are visible": "Les résultats sont visibles",
"Password protected.": "Protégé par mot de passe.", "Password protected": "Protégé par mot de passe",
"Votes protected by password.": "Votes protégés par mot de passe.", "Votes protected by password": "Votes protégés par mot de passe",
"No password.": "Pas de mot de passe", "No password": "Pas de mot de passe",
"Remove password.": "Supprimer le mot de passe." "Remove password": "Supprimer le mot de passe"
}, },
"Poll results": { "Poll results": {
"Votes of the poll": "Votes du sondage", "Votes of the poll": "Votes du sondage",
@ -143,7 +140,7 @@
"Vote no for": "Voter « non » pour", "Vote no for": "Voter « non » pour",
"Vote yes for": "Voter « oui » pour", "Vote yes for": "Voter « oui » pour",
"Vote ifneedbe for": "Voter « Si nécessaire » pour", "Vote ifneedbe for": "Voter « Si nécessaire » pour",
"Save the choices": "Enregister les choix", "Save the choices": "Enregistrer les choix",
"Addition": "Somme", "Addition": "Somme",
"Best choice": "Meilleur choix", "Best choice": "Meilleur choix",
"Best choices": "Meilleurs choix", "Best choices": "Meilleurs choix",
@ -177,7 +174,7 @@
"POLL_LOCKED_WARNING": "L'administrateur a verrouillé ce sondage. Les votes et commentaires sont gelés, il n'est plus possible de participer", "POLL_LOCKED_WARNING": "L'administrateur a verrouillé ce sondage. Les votes et commentaires sont gelés, il n'est plus possible de participer",
"The poll is expired, it will be deleted soon.": "Le sondage a expiré, il sera bientôt supprimé.", "The poll is expired, it will be deleted soon.": "Le sondage a expiré, il sera bientôt supprimé.",
"Deletion date:": "Date de suppression :", "Deletion date:": "Date de suppression :",
"Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:": "Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez le précieusement ! ", "Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:": "Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez-le précieusement ! ",
"Update vote succeeded": "Mise à jour du vote réussi", "Update vote succeeded": "Mise à jour du vote réussi",
"Adding the vote succeeded": "Ajout du vote réussi" "Adding the vote succeeded": "Ajout du vote réussi"
}, },
@ -221,7 +218,10 @@
"You are in the poll creation section.": "Vous avez choisi de créer un nouveau sondage.", "You are in the poll creation section.": "Vous avez choisi de créer un nouveau sondage.",
"Required fields cannot be left blank.": "Merci de remplir les champs obligatoires, marqués d'une *.", "Required fields cannot be left blank.": "Merci de remplir les champs obligatoires, marqués d'une *.",
"Poll title": "Titre du sondage", "Poll title": "Titre du sondage",
"Votes cannot be modified.": "Aucun vote ne peut être modifié", "Poll id": "Identifiant",
"Poll id rules": "L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".",
"Poll id warning": "En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.",
"Votes cannot be modified": "Aucun vote ne peut être modifié",
"All voters can modify any vote": "Tous les sondés peuvent modifier tous les votes", "All voters can modify any vote": "Tous les sondés peuvent modifier tous les votes",
"Voters can modify their vote themselves": "Chaque sondé peut modifier son propre vote", "Voters can modify their vote themselves": "Chaque sondé peut modifier son propre vote",
"To receive an email for each new vote": "Recevoir un courriel à chaque participation d'un sondé", "To receive an email for each new vote": "Recevoir un courriel à chaque participation d'un sondé",
@ -274,7 +274,9 @@
"Create the poll": "Créer le sondage", "Create the poll": "Créer le sondage",
"Your poll will be automatically archived in %d days.": "Votre sondage sera automatiquement archivé dans %d jours.", "Your poll will be automatically archived in %d days.": "Votre sondage sera automatiquement archivé dans %d jours.",
"You can set a closer archiving date for it.": "Vous pouvez décider d'une date d'archivage plus proche.", "You can set a closer archiving date for it.": "Vous pouvez décider d'une date d'archivage plus proche.",
"Archiving date:": "Date d'archivage :" "Archiving date:": "Date d'archivage :",
"Your poll will automatically be archived": "Votre sondage sera automatiquement archivé",
"after the last date of your poll.": "après le dernier jour de votre sondage."
}, },
"Admin": { "Admin": {
"Back to administration": "Retour à l'administration", "Back to administration": "Retour à l'administration",
@ -298,11 +300,11 @@
"Success": "Réussite", "Success": "Réussite",
"Fail": "Échec", "Fail": "Échec",
"Nothing": "Rien", "Nothing": "Rien",
"Succeeded:": "Réussit:", "Succeeded:": "Succès :",
"Failed:": "Échoué:", "Failed:": "Échec ::",
"Skipped:": "Passé:", "Skipped:": "Passé :",
"Pages:": "Pages :", "Pages:": "Pages :",
"Purged:": "Purgés :", "Purged:": "Purgés :",
"Confirm removal of the poll": "Confirmer la suppression du sondage", "Confirm removal of the poll": "Confirmer la suppression du sondage",
"polls in the database at this time": "sondages dans la base actuellement", "polls in the database at this time": "sondages dans la base actuellement",
"Purge the polls": "Purger les sondages" "Purge the polls": "Purger les sondages"
@ -356,7 +358,7 @@
"No polls found": "Aucun sondage n'a été trouvé", "No polls found": "Aucun sondage n'a été trouvé",
"There is a problem with your choices": "Il y a un problème avec vos choix", "There is a problem with your choices": "Il y a un problème avec vos choix",
"You haven't filled the first section of the poll creation.": "Vous n'avez pas renseigné la première page du sondage", "You haven't filled the first section of the poll creation.": "Vous n'avez pas renseigné la première page du sondage",
"Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", "Javascript is disabled on your browser. Its activation is required to create a poll.": "JavaScript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.",
"Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.", "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.",
"This poll doesn't exist !": "Ce sondage n'existe pas !", "This poll doesn't exist !": "Ce sondage n'existe pas !",
"Enter a name": "Vous n'avez pas saisi de nom !", "Enter a name": "Vous n'avez pas saisi de nom !",
@ -364,16 +366,21 @@
"The name you've chosen already exist in this poll!": "Le nom que vous avez choisi existe déjà !", "The name you've chosen already exist in this poll!": "Le nom que vous avez choisi existe déjà !",
"Enter a name and a comment!": "Merci de remplir les deux champs !", "Enter a name and a comment!": "Merci de remplir les deux champs !",
"Failed to insert the comment!": "Échec à l'insertion du commentaire !", "Failed to insert the comment!": "Échec à l'insertion du commentaire !",
"Failed to delete the vote!": "Échec de la suppression du vote !",
"Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.",
"Failed to save poll": "Echec de la sauvegarde du sondage", "Failed to save poll": "Échec de la sauvegarde du sondage",
"Update vote failed": "Mise à jour du vote échoué", "Update vote failed": "Échec de de la mise à jour du vote",
"Adding vote failed": "Ajout d'un vote échoué", "Adding vote failed": "Échec de l'ajout d'un vote",
"Comment failed": "Commentaire échoué", "You already voted": "Vous avez déjà voté",
"Poll has been updated before you vote": "Le sondage a été mis à jour avant votre vote",
"Comment failed": "Échec du commentaire",
"You can't create a poll with hidden results with the following edition option:": "Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ", "You can't create a poll with hidden results with the following edition option:": "Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ",
"Failed to delete column": "Échec de la suppression de colonne", "Failed to delete column": "Échec de la suppression de colonne",
"The column already exists": "La colonne existe déjà",
"MISSING_VALUES": "Il manque des valeurs", "MISSING_VALUES": "Il manque des valeurs",
"CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données", "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données",
"Password is empty": "Le mot de passe est vide.", "Password is empty": "Le mot de passe est vide.",
"Passwords do not match": "Les mots de passe ne correspondent pas." "Passwords do not match": "Les mots de passe ne correspondent pas.",
"Poll id already used": "L'identifiant est déjà utilisé"
} }
} }

View File

@ -35,7 +35,7 @@
"seconds": "secondi", "seconds": "secondi",
"Choice": "Scelta", "Choice": "Scelta",
"Link": "Link", "Link": "Link",
"Search": "Ricerca", "Search": "Cercare",
"Creation date:": "Data di creazione:", "Creation date:": "Data di creazione:",
"Caption": "Titolo", "Caption": "Titolo",
"ASTERISK": "*" "ASTERISK": "*"
@ -105,9 +105,9 @@
"Save the new title": "Salvare il nuovo titolo", "Save the new title": "Salvare il nuovo titolo",
"Cancel the title edit": "Annullare la modifica del titolo", "Cancel the title edit": "Annullare la modifica del titolo",
"Initiator of the poll": "Autore del sondaggio", "Initiator of the poll": "Autore del sondaggio",
"Edit the name": "Modifica dell'autore", "Edit the name": "Modifica il nome",
"Save the new name": "Salvare l'autore", "Save the new name": "Salvare il nuovo nome",
"Cancel the name edit": "Annulla il cambio di dell'autore", "Cancel the name edit": "Annulla il cambio di nome",
"Email": "Email", "Email": "Email",
"Edit the email adress": "Modificare l'email", "Edit the email adress": "Modificare l'email",
"Save the email address": "Salvare l'email", "Save the email address": "Salvare l'email",
@ -124,17 +124,14 @@
"Poll rules": "Permessi del sondaggio", "Poll rules": "Permessi del sondaggio",
"Edit the poll rules": "Modificare i permessi del sondaggio", "Edit the poll rules": "Modificare i permessi del sondaggio",
"Votes and comments are locked": "I voti e i commenti sono bloccati", "Votes and comments are locked": "I voti e i commenti sono bloccati",
"Votes and comments are open": "I voti e i commenti sono permessi",
"Votes are editable": " I voti sono modificabili",
"Votes are editable solely by their owner.": "Voti sono scrivibili solo dal loro creatore",
"Save the new rules": "Salvare i nuovi permessi", "Save the new rules": "Salvare i nuovi permessi",
"Cancel the rules edit": "Annullare le modifica dei permessi", "Cancel the rules edit": "Annullare le modifica dei permessi",
"Results are hidden.": "I risultati sono nascosti.", "Results are hidden": "I risultati sono nascosti",
"Results are visible.": "I risultati sono visibili.", "Results are visible": "I risultati sono visibili",
"Password protected.": "Protetto da una password.", "Password protected": "Protetto da una password",
"Votes protected by password.": "Voti protetti da una password.", "Votes protected by password": "Voti protetti da una password",
"No password.": "Nessuna password", "No password": "Nessuna password",
"Remove password.": "Eliminare la password." "Remove password": "Eliminare la password"
}, },
"Poll results": { "Poll results": {
"Votes of the poll": "Voti del sondaggio ", "Votes of the poll": "Voti del sondaggio ",
@ -151,9 +148,9 @@
"The bests choices at this time are:": "Le migliori scelte per ora sono :", "The bests choices at this time are:": "Le migliori scelte per ora sono :",
"Scroll to the left": "Spostare a sinistra", "Scroll to the left": "Spostare a sinistra",
"Scroll to the right": "Spostare a destra", "Scroll to the right": "Spostare a destra",
"polled user": "votante", "polled user": "Votante",
"polled users": "votanti", "polled users": "Votanti",
"Display the chart of the results": "Visualizzare il grafico dei risultati", "Display the chart of the results": "Mostra il grafico dei risultati",
"Chart": "Grafico" "Chart": "Grafico"
}, },
"Comments": { "Comments": {
@ -221,7 +218,10 @@
"You are in the poll creation section.": "Avete scelto di creare un nuovo sondaggio.", "You are in the poll creation section.": "Avete scelto di creare un nuovo sondaggio.",
"Required fields cannot be left blank.": "Riempire i campi obbligatori, segnati con *.", "Required fields cannot be left blank.": "Riempire i campi obbligatori, segnati con *.",
"Poll title": "Titolo del sondaggio", "Poll title": "Titolo del sondaggio",
"Votes cannot be modified.": "Nessun voto può essere modificato", "Poll id": "IT_Identifiant",
"Poll id rules": "IT_L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".",
"Poll id warning": "IT_En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.",
"Votes cannot be modified": "Nessun voto può essere modificato",
"All voters can modify any vote": "Tutti i votanti possono cambiare tutti i voti", "All voters can modify any vote": "Tutti i votanti possono cambiare tutti i voti",
"Voters can modify their vote themselves": "I partecipanti possono modificare il loro voto in autonomia", "Voters can modify their vote themselves": "I partecipanti possono modificare il loro voto in autonomia",
"To receive an email for each new vote": "Per ricevere un'email per ogni nuovo voto", "To receive an email for each new vote": "Per ricevere un'email per ogni nuovo voto",
@ -274,14 +274,16 @@
"Create the poll": "Creare il sondaggio", "Create the poll": "Creare il sondaggio",
"Your poll will be automatically archived in %d days.": "Il vostro sondaggio verrà archiviata automaticamente in %d giorni.", "Your poll will be automatically archived in %d days.": "Il vostro sondaggio verrà archiviata automaticamente in %d giorni.",
"You can set a closer archiving date for it.": "Si può decidere su una data più vicina di archiviazione.", "You can set a closer archiving date for it.": "Si può decidere su una data più vicina di archiviazione.",
"Archiving date:": "Archivio Data:" "Archiving date:": "Archivio Data:",
"Your poll will automatically be archived": "IT_Your poll will automatically be archived",
"after the last date of your poll.": "IT_after the last date of your poll."
}, },
"Admin": { "Admin": {
"Back to administration": "Ritornare all'amministrazione", "Back to administration": "Ritorna all'amministrazione",
"Administration": "Amministrazione", "Administration": "Amministrazione",
"Polls": "Sondaggi", "Polls": "Sondaggi",
"Migration": "Migrazione", "Migration": "Migrazione",
"Purge": "Depurazione", "Purge": "Depurare",
"Logs": "Log", "Logs": "Log",
"Installation": "Installazione", "Installation": "Installazione",
"Poll ID": "ID del sondaggio", "Poll ID": "ID del sondaggio",
@ -322,7 +324,7 @@
"Someone just change your poll available at the following link %s.": "Qualcuno ha appena cambiato il vostro sondaggio disponibile al seguente link <a href=\"%1$s\">%1$s</a>.", "Someone just change your poll available at the following link %s.": "Qualcuno ha appena cambiato il vostro sondaggio disponibile al seguente link <a href=\"%1$s\">%1$s</a>.",
"Someone just delete your poll %s.": "Qualcuno ha appena cancellato il vostro sondaggio \"%s\".", "Someone just delete your poll %s.": "Qualcuno ha appena cancellato il vostro sondaggio \"%s\".",
"Thanks for your trust.": "Grazie per la vostra fiducia.", "Thanks for your trust.": "Grazie per la vostra fiducia.",
"FOOTER": La strada è lunga, ma la via è libera… »\nFramasoft vive solo grazie alle vostre donazioni (deducibili dalle imposte).\nGrazie in anticipo per il vostro sostegno http://soutenir.framasoft.org.", "FOOTER": La strada è lunga, ma la via è libera… »\nFramasoft vive solo grazie alle vostre donazioni (deducibili dalle imposte).\nGrazie in anticipo per il vostro sostegno http://soutenir.framasoft.org.",
"[ADMINISTRATOR] New settings for your poll": "[AMMINISTRATORE] Modifica di configurazione del sondaggio", "[ADMINISTRATOR] New settings for your poll": "[AMMINISTRATORE] Modifica di configurazione del sondaggio",
"You have changed the settings of your poll. \nYou can modify this poll with this link": "Avete modificato la configurazione del vostro sondaggio. \nPotete modificare questo sondaggio con le Link seguente", "You have changed the settings of your poll. \nYou can modify this poll with this link": "Avete modificato la configurazione del vostro sondaggio. \nPotete modificare questo sondaggio con le Link seguente",
"This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Questo è il messaggio che deve essere inviato ai partecipanti. \nPotete ora inviare questo messaggio a tutte le persone a cui volete chiedere il voto.", "This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Questo è il messaggio che deve essere inviato ai partecipanti. \nPotete ora inviare questo messaggio a tutte le persone a cui volete chiedere il voto.",
@ -346,18 +348,23 @@
"Cookies are disabled on your browser. Theirs activation is required to create a poll.": "I cookies non sono permessi sul vostro browser. E' necessario permetterli per creare un sondaggio.", "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "I cookies non sono permessi sul vostro browser. E' necessario permetterli per creare un sondaggio.",
"This poll doesn't exist !": "Questo sondaggio non esiste più !", "This poll doesn't exist !": "Questo sondaggio non esiste più !",
"Enter a name": "Non avete inserito il nome !", "Enter a name": "Non avete inserito il nome !",
"The name is invalid.": "Le nome non è valido.", "The name is invalid.": "Nome non valido.",
"The name you've chosen already exist in this poll!": "Il nome che avete scelto esiste già !", "The name you've chosen already exist in this poll!": "Il nome che avete scelto esiste già !",
"Enter a name and a comment!": "Inserire un nome e un commento!", "Enter a name and a comment!": "Inserire un nome e un commento!",
"Failed to insert the comment!": "Errore nell'inserimento del commento !", "Failed to insert the comment!": "Errore nell'inserimento del commento !",
"Failed to delete the vote!": "IT_Échec de la suppression du vote !",
"Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate non è installato correttamente, leggete la cartella INSTALL per configurare il database prima di continuare.", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate non è installato correttamente, leggete la cartella INSTALL per configurare il database prima di continuare.",
"Failed to save poll": "Errore nel salvataggio del sondaggio", "Failed to save poll": "Errore nel salvataggio del sondaggio",
"Update vote failed": "Aggiornamento del voto fallito", "Update vote failed": "Aggiornamento del voto fallito",
"Adding vote failed": "Aggiunta del voto fallita", "Adding vote failed": "Aggiunta del voto fallito",
"You already voted": "IT_Vous avez déjà voté",
"Poll has been updated before you vote": "IT_Le sondage a été mis à jour avant votre vote",
"Comment failed": "Commento fallito", "Comment failed": "Commento fallito",
"You can't create a poll with hidden results with the following edition option:": "Non potete creare un sondaggio con i risultati nascosti con queste opzioni: : ", "You can't create a poll with hidden results with the following edition option:": "Non potete creare un sondaggio con i risultati nascosti con queste opzioni: ",
"Failed to delete column": "Impossibile eliminare la colonna", "Failed to delete column": "Impossibile eliminare la colonna",
"The column already exists": "IT_La colonne existe déjà",
"MISSING_VALUES": "Valori mancanti", "MISSING_VALUES": "Valori mancanti",
"CANT_CONNECT_TO_DATABASE": "Impossibile connettersi al database" "CANT_CONNECT_TO_DATABASE": "Impossibile connettersi al database",
"Poll id already used": "IT_L'identifiant est déjà utilisé"
} }
} }

363
locale/oc.json Normal file
View File

@ -0,0 +1,363 @@
{
"Generic": {
"Make your polls": "Organizar de rencontres simplament, liurament",
"Home": "Acuèlh",
"Poll": "Sondatge",
"Save": "Enregistrar",
"Cancel": "Anullar",
"Add": "Apondre",
"Remove": "Suprimir",
"Validate": "Validar",
"Edit": "Modificar",
"Next": "Contunhar",
"Back": "Tornar",
"Close": "Tampar",
"Your name": "Vòstre nom",
"Your email address": "Vòstre adreça",
"(in the format name@mail.com)": "(al format nom@mail.com)",
"Description": "Descripcion",
"Back to the homepage of": "Tornar a la pagina d'acuèlh de",
"days": "jorns",
"months": "meses",
"Day": "Jorn",
"Time": "Ora",
"with": "amb",
"vote": "vòte",
"votes": "vòtes",
"for": "per",
"Yes": "Òc",
"Ifneedbe": "Se cal",
"No": "Non",
"Legend:": "Legenda :",
"Date": "Data",
"Classic": "Classic",
"Page generated in": "Pagina generada en",
"seconds": "segondas",
"Choice": "Causida",
"Link": "Ligam",
"Search": "Cercar",
"Creation date:": "Data de creacion :",
"ASTERISK": "*"
},
"Date": {
"dd/mm/yyyy": "jj/mm/aaaa",
"%A, den %e. %B %Y": "%A %e %B %Y",
"FULL": "%A %e %B %Y",
"SHORT": "%A %e %B %Y",
"DAY": "%a %e",
"DATE": "%Y-%m-%d",
"MONTH_YEAR": "%B %Y"
},
"Language selector": {
"Select the language": "Seleccionar la lenga",
"Change the language": "Cambiar la lenga"
},
"Homepage": {
"Schedule an event": "Crear un sondatge especial datas",
"Make a classic poll": "Crear un sondatge classic",
"Where are my polls": "Ont son mos sondatges ?"
},
"Maintenance": {
"The application": "L'aplicacion",
"is currently under maintenance.": "es en mantenença.",
"Thank you for your understanding.": "Mercés de tornar dins un momenton."
},
"1st section": {
"What is that?": "Primièrs passes",
"Framadate is an online service for planning an appointment or make a decision quickly and easily. No registration is required.": "Framadate es un servici en linha que permet d'organizar un rendètz-vos o de prene de decisions rapidament e simplament. Cap d'inscripcion es pas demandada.",
"Here is how it works:": "Vaquí cossí fonciona :",
"Make a poll": "Creatz un sondatge",
"Define dates or subjects to choose": "Determinatz las datas o los tèmas a causir",
"Send the poll link to your friends or colleagues": "Mandatz lo ligam del sondatge a vòstres amics o companhs",
"Discuss and make a decision": "Charratz e prenètz vòstra decision",
"Do you want to": "Volètz",
"view an example?": "veire un example ?"
},
"2nd section": {
"The software": "Lo logicial",
"Framadate was initially based on ": "Framadate es inicialament basat sus ",
"a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "un logicial desvolopat per l'Universitat d'Estrasborg. Uèi son desvolopament es fach per lassociacion Framasoft.",
"This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Aqueste logicial requerís lactivacion del javascript e dels cookies. Es compatible amb los navigadors web seguents :",
"It is governed by the": "Es regit per la",
"CeCILL-B license": "licéncia CeCILL-B"
},
"3rd section": {
"Cultivate your garden": "Cultivatz vòstre òrt",
"To participate in the software development, suggest improvements or simply download it, please visit ": "Per participar al desvolopament del logicial, prepausar de milhoraments o simplament lo telecargar, anatz sus ",
"the development site": "lo site de desvolopament",
"If you want to install the software for your own use and thus increase your independence, we help you on:": "Se volètz installar aqueste logicial per vòstra pròpia utilizacion e aital aver mai d'automonia, nos podètz ajudar sus :"
},
"PollInfo": {
"Remove the poll": "Suprimir lo sondatge",
"Remove all the comments": "Suprimir totes los comentaris",
"Remove all the votes": "Suprimir totes los vòtes",
"Print": "Imprimir",
"Export to CSV": "Exportar en CSV",
"Title": "Títol del sondatge",
"Edit the title": "Modificar lo títol",
"Save the new title": "Enregistrar lo novèl títol",
"Cancel the title edit": "Anullar lo cambiament de títol",
"Initiator of the poll": "Autor del sondatge",
"Edit the name": "Modificacion de l'autor",
"Save the new name": "Enregistrar l'autor",
"Cancel the name edit": "Anullar lo cambiament d'autor",
"Email": "Adreça",
"Edit the email adress": "Modificar l'adreça",
"Save the email address": "Enregistrar l'adreça",
"Cancel the email address edit": "Anullar lo cambiament d'adreça",
"Edit the description": "Modificar la descripcion",
"Save the description": "Enregistrar la descripcion",
"Cancel the description edit": "Anullar lo cambiament de descripcion",
"Public link of the poll": "Ligam public del sondatge",
"Admin link of the poll": "Ligam d'administracion del sondatge",
"Expiration date": "Data d'expiracion",
"Edit the expiration date": "Modificar la data d'expiracion",
"Save the new expiration date": "Enregistrar la data d'expiracion",
"Cancel the expiration date edit": "Anullar lo cambiament de data d'expiracion",
"Poll rules": "Permissions del sondatge",
"Edit the poll rules": "Modificar las permissions del sondatge",
"Votes and comments are locked": "Los vòtes e comentaris son clavats",
"Save the new rules": "Enregistrar las permissions novèlas",
"Cancel the rules edit": "Anullar lo cambiament de permissions",
"Results are hidden": "Los resultats son amagats",
"Results are visible": "Los resultats son visibles",
"Password protected": "OC_Protégé par mot de passe",
"Votes protected by password": "OC_Votes protégés par mot de passe",
"No password": "OC_Pas de mot de passe",
"Remove password": "OC_Supprimer le mot de passe"
},
"Poll results": {
"Votes of the poll": "Vòtes del sondatge",
"Edit the line:": "Modificar la linha :",
"Remove the line:": "Suprimir la linha :",
"Vote no for": "Votar « non » per",
"Vote yes for": "Votar « òc » per",
"Vote ifneedbe for": "Votar « se cal » per",
"Save the choices": "Enregistar las causidas",
"Addition": "Soma",
"Best choice": "Milhora causida",
"Best choices": "Milhoras causidas",
"The best choice at this time is:": "Pel moment, la causida amb lo mai de vòtes es :",
"The bests choices at this time are:": "Pel moment, las causidas amb lo mai de vòtes son :",
"Scroll to the left": "Far desfilar a man esquèrra",
"Scroll to the right": "Far desfilar a man drecha",
"polled user": "votant",
"polled users": "votants",
"Display the chart of the results": "Afichar lo grafic dels resultats",
"Chart": "Grafic"
},
"Comments": {
"Comments of polled people": "Comentaris dels sondats",
"Remove the comment": "Suprimir lo comentari",
"Add a comment to the poll": "Apondre un comentari al sondatge",
"Your comment": "Vòstre comentari",
"Send the comment": "Mandar lo comentari",
"anonyme": "anonim",
"Comment added": "Comentari apondut"
},
"studs": {
"If you want to vote in this poll, you have to give your name, choose the values that fit best for you and validate with the plus button at the end of the line.": "Per participar a aqueste sondatge, picatz vòstre nom, triatz totas las valors que vos agradan e validatz amb lo boton al cap de linha.",
"POLL_LOCKED_WARNING": "L'administrator a clavat aqueste sondatge. Los vòtes e comentaris son gelats, es pas mai possible de participar",
"The poll is expired, it will be deleted soon.": "Lo sondatge a expirat, serà lèu suprimit.",
"Deletion date:": "Data de supression :",
"Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:": "Vòstre vòte es estat enregistrat corrèctament, mas mèfi : aqueste sondatge permet l'edicion de vòstre vòte solament amb lo ligam personalizat seguent ; gardatz-lo preciosament ! ",
"Update vote succeeded": "Mesa a jorn del vòte amb succès",
"Adding the vote succeeded": "Apondon del vòte capitat"
},
"adminstuds": {
"As poll administrator, you can change all the lines of this poll with this button": "En qualitat d'administrator podètz modificar totas las linhas d'aqueste sondatge amb aqueste boton",
"remove a column or a line with": "escafar una colomna o una linha amb",
"and add a new column with": "E se avètz doblidat de picar una causida, podètz tornar apondre una colomna en clicant sus",
"Finally, you can change the informations of this poll like the title, the comments or your email address.": "Per acabar podètz tanben modificar las informacions a prepaus d'aqueste sondatge coma lo títol, los comentaris o vòstre corrièl.",
"Column's adding": "Apondon de colomna",
"You can add a new scheduling date to your poll.": "Podètz apondre una data a vòstre sondatge.",
"If you just want to add a new hour to an existant date, put the same date and choose a new hour.": "Se volètz apondre un orari a una data existenta, botatz la meteissa data e causissètz un orari mai. Serà normalament integrat al sondatge existent.",
"Confirm removal of the poll": "Confirmar la supression del sondatge",
"Delete the poll": "Suprimir lo sondatge",
"Keep the poll": "Gardar lo sondatge",
"Your poll has been removed!": "Vòstre sondatge es estat suprimit !",
"Poll saved": "Sondatge salvagardat",
"Poll fully deleted": "Sondatge totalament suprimit",
"Vote added": "Vòte apondut",
"Vote updated": "Vòte mes a jorn",
"Vote deleted": "Vòte suprimit",
"All votes deleted": "Totes los vòtes son estats suprimits",
"Back to the poll": "Tornar al sondatge",
"Add a column": "Apondre una colomna",
"Remove the column": "Suprimir la colomna",
"Column removed": "Colomna suprimida",
"Choice added": "Causida aponduda",
"Confirm removal of all votes of the poll": "Confirmar la supression de totes los vòtes d'aqueste sondatge",
"Keep the votes": "Gardar los vòtes",
"Remove the votes": "Suprimir los vòtes",
"Confirm removal of all comments of the poll": "Confirmar la supression de totes los comentaris d'aqueste sondatge",
"Keep the comments": "Gardar los comentaris",
"Remove the comments": "Suprimir los comentaris",
"Comment deleted": "Comentari suprimit",
"All comments deleted": "Totes los comentaris son estats suprimits",
"Keep votes": "Gardar lòs vòtes",
"Keep comments": "Gardar los comentaris",
"Keep this poll": "Gardar aqueste sondatge"
},
"Step 1": {
"Poll creation (1 on 3)": "Creacion de sondatge (1 sus 3)",
"You are in the poll creation section.": "Avètz causit de crear un sondatge novèl.",
"Required fields cannot be left blank.": "Mercés de garnir totes los formularis obligatòris, marcats amb una *.",
"Poll title": "Títol del sondatge",
"Votes cannot be modified": "Cap de vòte pòt pas èsser modificat",
"All voters can modify any vote": "Totes los votants pòdon modificar sos vòtes",
"Voters can modify their vote themselves": "Cadun pòt modificar son pròpri vòte",
"To receive an email for each new vote": "Recebre un messatge per cada participacion",
"To receive an email for each new comment": "Recebre un messatge per cada comentari",
"Only the poll maker can see the poll's results": "Solament lo creator del sondatge pòt veire los resultats",
"Go to step 2": "Anar a l'etapa 2"
},
"Step 2": {
"Back to step 1": "Tornar a l'etapa 1",
"Go to step 3": "Anar a l'etapa 3"
},
"Step 2 date": {
"Poll dates (2 on 3)": "Causida de las datas (2 sus 3)",
"Choose the dates of your poll": "Causissètz las datas de vòstre sondatge",
"To schedule an event you need to propose at least two choices (two hours for one day or two days).": "Per crear un sondatge especial datas vos cal prepausar almens doas causidas (dos oraris per la meteissa jornada o dos jorns).",
"You can add or remove additionnal days and hours with the buttons": "Podètz apondre o suprimir de jorns e oraris suplementaris amb los botons",
"For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)": "Per cada jorn seleccionat avètz la possibilitat de causir o non d'oras de reünion (per exemple : \"8o\", \"8o30\", \"8o-10o\", \"ser\", etc.)",
"Remove an hour": "Suprimir lo darrièr orari",
"Add an hour": "Ajustar un orari",
"Copy hours of the first day": "Reportar los oraris del primièr jorn suls autres jorns",
"Remove a day": "Suprimir lo darrièr jorn",
"Add a day": "Ajustar un jorn",
"Remove all days": "Suprimir totes los jorns",
"Remove all hours": "Suprimir totes los oraris"
},
"Step 2 classic": {
"Poll subjects (2 on 3)": "Causida dels tèmas (2 sus 3)",
"To make a generic poll you need to propose at least two choices between differents subjects.": "Per crear un sondatge classic, vos cal prepausar almens doas causidas diferentas.",
"You can add or remove additional choices with the buttons": "Podètz apondre o suprimir de causidas mai amb los botons",
"It's possible to propose links or images by using": "Es possible d'inserir de ligams o d'imatges en emplegant ",
"the Markdown syntax": "la sintaxi Markdown",
"Add a link or an image": "Apondre un ligam o un imatge",
"These fields are optional. You can add a link, an image or both.": "Aquestes camps son facultatius. Podètz apondre un ligam, un imatge o los dos.",
"URL of the image": "URL de l'imatge",
"Alternative text": "Tèxte alternatiu",
"Remove a choice": "Suprimir la darrièra causida",
"Add a choice": "Apondre una causida"
},
"Step 3": {
"Back to step 2": "Tornar a l'etapa 2",
"Removal date and confirmation (3 on 3)": "Data d'expiracion e confirmacion (3 sus 3)",
"Confirm the creation of your poll": "Confirmatz la creacion de vòstre sondatge",
"List of your choices": "Lista de vòstras causidas",
"Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.": "Un còp la creacion del sondatge confirmada, seretz redirigit automaticament cap a vòstre sondatge.",
"Then, you will receive quickly two emails: one contening the link of your poll for sending it to the voters, the other contening the link to the administration page of your poll.": "D'aquel temps, recebretz dos corrièls : un amb lo ligam cap a vòstre sondatge per o mandar als sondats, l'autre amb lo ligam per la pagina d'administracion del sondatge.",
"Create the poll": "Crear lo sondatge",
"Your poll will be automatically archived in %d days.": "Vòstre sondatge serà archivat automaticament dins %d jorns.",
"You can set a closer archiving date for it.": "Podètz decidir d'una data de mesa en archiu mai pròcha.",
"Archiving date:": "Data de mesa en archiu :",
"Your poll will automatically be archived": "Vòstre sondatge serà archivat automaticament",
"after the last date of your poll.": "aprèp lo darrièr jorn del sondatge."
},
"Admin": {
"Back to administration": "Tornar a l'administracion",
"Administration": "Administracion",
"Polls": "Sondatges",
"Migration": "Migracion",
"Purge": "Purga",
"Logs": "Istoric",
"Installation": "Installacion",
"Poll ID": "ID sondatge",
"Format": "Format",
"Title": "Títol",
"Author": "Autor",
"Email": "Corrièl",
"Expiration date": "Expiracion",
"Votes": "Vòtes",
"Actions": "Accions",
"See the poll": "Veire lo sondatge",
"Change the poll": "Modificar lo sondatge",
"Deleted the poll": "Suprimir lo sondatge",
"Summary": "Resumit",
"Success": "Capitada",
"Fail": "Fracàs",
"Nothing": "Res",
"Succeeded:": "Capitat:",
"Failed:": "Fracassat:",
"Skipped:": "Passat:",
"Pages:": "Paginas :",
"Purged:": "Purgats :",
"Confirm removal of the poll": "Confirmar la supression del sondatge",
"polls in the database at this time": "sondatges dins la banca de donadas actualament",
"Purge the polls": "Purgar los sondatges"
},
"FindPolls": {
"Here are your polls": "Vaquí vòstres sondatges",
"Send me my polls": "Mandar mos sondatges",
"Polls sent": "Sondatges mandats"
},
"Mail": {
"Poll's participation: %s": "Participacion al sondatge : %s",
"Notification of poll: %s": "Notificacion d'un sondatge : %s",
"filled a vote.\nYou can find your poll at the link": "ven de votar.<br/>Podètz tornar a vòstre sondatge amb lo ligam seguent",
"updated a vote.\nYou can find your poll at the link": "ven de metre a jorn un vòte.<br/>Podètz tornar a vòstre sondatge amb lo ligam seguent",
"wrote a comment.\nYou can find your poll at the link": "ven de redigir un comentari.<br/>Podètz tornar a vòstre sondatge amb lo ligam seguent",
"Someone just change your poll available at the following link %s.": "Qualqu'un ven de modificar vòstre sondatge accessible amb lo ligam seguent <a href=\"%1$s\">%1$s</a>.",
"Someone just delete your poll %s.": "Qualqu'un ven de suprimir vòstre sondatge \"%s\".",
"Thanks for your trust.": "Mercé per vòstra fisança.",
"FOOTER": "« La rota es longa, mai lo camin es liure… »<br/>Framasoft viu solament amb vòstres dons (qu'òm pòt tirar de vòstres impòstes).<br/> Mercé d'avança pel vòstre sosten http://soutenir.framasoft.org.",
"[ADMINISTRATOR] New settings for your poll": "[ADMINISTRATOR] Cambi de configuracion del sondatge",
"You have changed the settings of your poll. \nYou can modify this poll with this link": "Avètz modificat la configuracion del sondatge.<br/>Podètz modificar aqueste sondatge amb lo ligam seguent",
"This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Aquò es lo messatge que serà mandat als sondats.<br/>Podètz ara transmetre aqueste messatge a totas las personas susceptiblas de participar al vòte.",
"hast just created a poll called": " ven de crear un sondatge titolat ",
"Thanks for filling the poll at the link above": "Mercé de ben voler participar al sondatge a l'adreça seguenta",
"This message should NOT be sent to the polled people. It is private for the poll's creator.\n\nYou can now modify it at the link above": "Aqueste messatge deu PAS èsser difusat als sondats. Es reservat a l'autor del sondatge.<br/><br/>Podètz modificar aqueste sondatge amb lo ligam seguent ",
"Author's message": "Reservat a l'autor",
"For sending to the polled users": "Per difusion als sondats"
},
"Installation": {
"AppMail": "Adreça de corrièl de l'aplicacion",
"AppName": "Nom de l'aplicacion",
"CleanUrl": "URL clars",
"Database": "Banca de donadas",
"DbConnectionString": "Cadena de connexion",
"DbPassword": "Senhal",
"DbPrefix": "Prefixe",
"DbUser": "Utilizaire",
"DefaultLanguage": "Lenga per defaut",
"General": "General",
"Install": "Installar",
"MigrationTable": "Taula de migracion",
"ResponseMail": "Adreça de responsa"
},
"Error": {
"Error!": "Error !",
"Enter a title": "Cal picar un títol !",
"Something is going wrong...": "I a quicòm que truca...",
"Something is wrong with the format": "I a quicòm que truca amb lo format.",
"Enter an email address": "Cal picar una adreça de messatjariá !",
"The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.": "L'adreça picada es pas corrècta ! Cal una adreça valida (per exemple r.stallman@outlock.com) per recebre lo ligam cap al sondatge.",
"No polls found": "Cap de sondatge pas trobat",
"There is a problem with your choices": "I a un problèma amb vòstras causidas",
"You haven't filled the first section of the poll creation.": "Avètz pas garnit la primièra pagina del sondatge",
"Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript es desactivat sus vòstre navigador. Son activacion es requesida per la creacion d'un sondatge.",
"Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Los cookies son desactivats sus vòstre navigador. Lor activacion es requesida per la creacion d'un sondatge.",
"This poll doesn't exist !": "Aqueste sondatge existís pas !",
"Enter a name": "Avètz pas picat cap de nom !",
"The name is invalid.": "Lo nom es pas valid.",
"The name you've chosen already exist in this poll!": "Lo nom qu'avètz causit existís ja !",
"Enter a name and a comment!": "Mercé de garnir los dos camps !",
"Failed to insert the comment!": "Fracàs de l'apondon del comentari !",
"Failed to delete the vote!": "Fracàs de la supression del vòte !",
"Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate es pas installat coma cal, legissètz lo fichièr per configurar la banca de donadas abans de contunhar.",
"Failed to save poll": "Fracàs del salvament del sondatge",
"Update vote failed": "Mesa a jorn del vòte fracassat",
"Adding vote failed": "Apondon d'un vòte fracassat",
"You already voted": "Avètz ja votat",
"Poll has been updated before you vote": "Lo sondatge es estat mes a jorn abans vòstre vòte",
"Comment failed": "Comentari fracassat",
"You can't create a poll with hidden results with the following edition option:": "Podètz pas crear de sondatges amb de resultats amagats amb las opcions d'edicion seguentas : ",
"Failed to delete column": "Fracàs de la supression de colomna",
"The column already exists": "La colomna existís ja",
"MISSING_VALUES": "Mancan de valors",
"CANT_CONNECT_TO_DATABASE": "Impossible de se connectar a la banca de donadas"
}
}

View File

@ -16,18 +16,27 @@
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/ */
use Framadate\Exception\AlreadyExistsException;
use Framadate\Exception\ConcurrentEditionException;
use Framadate\Services\LogService; use Framadate\Services\LogService;
use Framadate\Services\PollService; use Framadate\Services\PollService;
use Framadate\Services\InputService; use Framadate\Services\InputService;
use Framadate\Services\MailService; use Framadate\Services\MailService;
use Framadate\Services\NotificationService; use Framadate\Services\NotificationService;
use Framadate\Services\SecurityService; use Framadate\Services\SecurityService;
use Framadate\Services\SessionService;
use Framadate\Message; use Framadate\Message;
use Framadate\Utils; use Framadate\Utils;
use Framadate\Editable; use Framadate\Editable;
include_once __DIR__ . '/app/inc/init.php'; include_once __DIR__ . '/app/inc/init.php';
/* Constantes */
/* ---------- */
const USER_REMEMBER_VOTES_KEY = 'UserVotes';
/* Variables */ /* Variables */
/* --------- */ /* --------- */
@ -50,6 +59,7 @@ $inputService = new InputService();
$mailService = new MailService($config['use_smtp']); $mailService = new MailService($config['use_smtp']);
$notificationService = new NotificationService($mailService); $notificationService = new NotificationService($mailService);
$securityService = new SecurityService(); $securityService = new SecurityService();
$sessionService = new SessionService();
/* PAGE */ /* PAGE */
@ -57,9 +67,7 @@ $securityService = new SecurityService();
if (!empty($_GET['poll'])) { if (!empty($_GET['poll'])) {
$poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); $poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
if (strlen($poll_id) === 16) {
$poll = $pollService->findById($poll_id); $poll = $pollService->findById($poll_id);
}
} }
if (!$poll) { if (!$poll) {
@ -68,6 +76,8 @@ if (!$poll) {
exit; exit;
} }
$editedVoteUniqueId = $sessionService->get(USER_REMEMBER_VOTES_KEY, $poll_id, '');
// ------------------------------- // -------------------------------
// Password verification // Password verification
// ------------------------------- // -------------------------------
@ -113,6 +123,7 @@ if ($accessGranted) {
$name = $inputService->filterName($_POST['name']); $name = $inputService->filterName($_POST['name']);
$editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT); $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
if (empty($editedVote)) { if (empty($editedVote)) {
$message = new Message('danger', __('Error', 'Something is going wrong...')); $message = new Message('danger', __('Error', 'Something is going wrong...'));
@ -123,11 +134,13 @@ if ($accessGranted) {
if ($message == null) { if ($message == null) {
// Update vote // Update vote
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); try {
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash);
if ($result) { if ($result) {
if ($poll->editable == Editable::EDITABLE_BY_OWN) { if ($poll->editable == Editable::EDITABLE_BY_OWN) {
$editedVoteUniqId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); $editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
$urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqId); $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
$urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
$message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote); $message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote);
} else { } else {
$message = new Message('success', __('studs', 'Update vote succeeded')); $message = new Message('success', __('studs', 'Update vote succeeded'));
@ -136,10 +149,14 @@ if ($accessGranted) {
} else { } else {
$message = new Message('danger', __('Error', 'Update vote failed')); $message = new Message('danger', __('Error', 'Update vote failed'));
} }
} catch (ConcurrentEditionException $cee) {
$message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
}
} }
} elseif (isset($_POST['save'])) { // Add a new vote } elseif (isset($_POST['save'])) { // Add a new vote
$name = $inputService->filterName($_POST['name']); $name = $inputService->filterName($_POST['name']);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
if ($name == null) { if ($name == null) {
$message = new Message('danger', __('Error', 'The name is invalid.')); $message = new Message('danger', __('Error', 'The name is invalid.'));
@ -150,10 +167,13 @@ if ($accessGranted) {
if ($message == null) { if ($message == null) {
// Add vote // Add vote
$result = $pollService->addVote($poll_id, $name, $choices); try {
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash);
if ($result) { if ($result) {
if ($poll->editable == Editable::EDITABLE_BY_OWN) { if ($poll->editable == Editable::EDITABLE_BY_OWN) {
$urlEditVote = Utils::getUrlSondage($poll_id, false, $result->uniqId); $editedVoteUniqueId = $result->uniqId;
$sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
$urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
$message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote); $message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote);
} else { } else {
$message = new Message('success', __('studs', 'Adding the vote succeeded')); $message = new Message('success', __('studs', 'Adding the vote succeeded'));
@ -162,12 +182,17 @@ if ($accessGranted) {
} else { } else {
$message = new Message('danger', __('Error', 'Adding vote failed')); $message = new Message('danger', __('Error', 'Adding vote failed'));
} }
} catch (AlreadyExistsException $aee) {
$message = new Message('danger', __('Error', 'You already voted'));
} catch (ConcurrentEditionException $cee) {
$message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
}
} }
} }
} }
// Retrieve data // Retrieve data
if ($resultPubliclyVisible) { if ($resultPubliclyVisible || $accessGranted) {
$slots = $pollService->allSlotsByPoll($poll); $slots = $pollService->allSlotsByPoll($poll);
$votes = $pollService->allVotesByPollId($poll_id); $votes = $pollService->allVotesByPollId($poll_id);
$comments = $pollService->allCommentsByPollId($poll_id); $comments = $pollService->allCommentsByPollId($poll_id);
@ -180,6 +205,7 @@ $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
$smarty->assign('expired', strtotime($poll->end_date) < time()); $smarty->assign('expired', strtotime($poll->end_date) < time());
$smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400); $smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400);
$smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots); $smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots);
$smarty->assign('slots_hash', $pollService->hashSlots($slots));
$smarty->assign('votes', $pollService->splitVotes($votes)); $smarty->assign('votes', $pollService->splitVotes($votes));
$smarty->assign('best_choices', $pollService->computeBestChoices($votes)); $smarty->assign('best_choices', $pollService->computeBestChoices($votes));
$smarty->assign('comments', $comments); $smarty->assign('comments', $comments);
@ -189,5 +215,6 @@ $smarty->assign('admin', false);
$smarty->assign('hidden', $poll->hidden); $smarty->assign('hidden', $poll->hidden);
$smarty->assign('accessGranted', $accessGranted); $smarty->assign('accessGranted', $accessGranted);
$smarty->assign('resultPubliclyVisible', $resultPubliclyVisible); $smarty->assign('resultPubliclyVisible', $resultPubliclyVisible);
$smarty->assign('editedVoteUniqueId', $editedVoteUniqueId);
$smarty->display('studs.tpl'); $smarty->display('studs.tpl');

View File

@ -32,7 +32,7 @@
{/if} {/if}
<div class="form-group"> <div class="form-group">
<button class="btn btn-default" type="submit" name="back">{__('adminstuds', 'Back to the poll')}</button> <button class="btn btn-default" type="submit" name="back">{__('adminstuds', 'Back to the poll')}</button>
<button type="submit" name="confirm_add_slot" class="btn btn-success">{__('adminstuds', 'Add a column')}</button> <button type="submit" name="confirm_add_column" class="btn btn-success">{__('adminstuds', 'Add a column')}</button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -16,7 +16,8 @@
{__('Step 1', 'Required fields cannot be left blank.')} {__('Step 1', 'Required fields cannot be left blank.')}
</p> </p>
</div> </div>
<div class="form-group '.$errors['title']['class'].'">
<div class="form-group {$errors['title']['class']}">
<label for="poll_title" class="col-sm-4 control-label">{__('Step 1', 'Poll title')} *</label> <label for="poll_title" class="col-sm-4 control-label">{__('Step 1', 'Poll title')} *</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -32,7 +33,31 @@
</div> </div>
{/if} {/if}
<div class="form-group '.$errors['description']['class'].'"> <div class="form-group {$errors['id']['class']}">
<label for="poll_id" class="col-sm-4 control-label">{__('Step 1', 'Poll id')}</label>
<div class="col-sm-8">
<div class="input-group">
<span class="input-group-addon">
<input id="customize_id" name="customize_id" type="checkbox"/>
</span>
<input id="poll_id" type="text" name="id" class="form-control" {$errors['id']['aria']}
value="{$poll_id}" aria-describedBy="pollIdDesc" disabled="disabled" maxlength="64"
pattern="[A-Za-z0-9-]+"/>
</div>
<span id="pollIdDesc" class="help-block">{__('Step 1', 'Poll id rules')}</span>
<span class="help-block text-warning">{__('Step 1', 'Poll id warning')}</span>
</div>
</div>
{if !empty($errors['id']['msg'])}
<div class="alert alert-danger">
<p id="poll_title_error">
{$errors['id']['msg']}
</p>
</div>
{/if}
<div class="form-group {$errors['description']['class']}">
<label for="poll_comments" class="col-sm-4 control-label">{__('Generic', 'Description')}</label> <label for="poll_comments" class="col-sm-4 control-label">{__('Generic', 'Description')}</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -106,7 +131,7 @@
</label> </label>
<label> <label>
<input type="radio" name="editable" {if empty($poll_editable) or $poll_editable==constant("Framadate\Editable::NOT_EDITABLE")}checked{/if} value="{constant("Framadate\Editable::NOT_EDITABLE")}"> <input type="radio" name="editable" {if empty($poll_editable) or $poll_editable==constant("Framadate\Editable::NOT_EDITABLE")}checked{/if} value="{constant("Framadate\Editable::NOT_EDITABLE")}">
{__('Step 1', 'Votes cannot be modified.')} {__('Step 1', 'Votes cannot be modified')}
</label> </label>
</div> </div>
</div> </div>

View File

@ -1,4 +1,5 @@
<div id="comments_list"> <div id="comments_list">
<form action="{if $admin}{poll_url id=$admin_poll_id admin=true}{else}{poll_url id=$poll_id}{/if}" method="POST">
{if $comments|count > 0} {if $comments|count > 0}
<h3>{__('Comments', 'Comments of polled people')}</h3> <h3>{__('Comments', 'Comments of polled people')}</h3>
{foreach $comments as $comment} {foreach $comments as $comment}
@ -12,5 +13,6 @@
</div> </div>
{/foreach} {/foreach}
{/if} {/if}
</form>
<div id="comments_alerts"></div> <div id="comments_alerts"></div>
</div> </div>

View File

@ -93,12 +93,12 @@
<div class="row"> <div class="row">
<div class="form-group form-group {if $admin}col-md-4{else}col-md-6{/if}"> <div class="form-group form-group {if $admin}col-md-4{else}col-md-6{/if}">
<label for="public-link"><a class="public-link" href="{poll_url id=$poll_id}">{__('PollInfo', 'Public link of the poll')} <span class="btn-link glyphicon glyphicon-link"></span></a></label> <label for="public-link"><a class="public-link" href="{poll_url id=$poll_id}">{__('PollInfo', 'Public link of the poll')} <span class="btn-link glyphicon glyphicon-link"></span></a></label>
<input class="form-control" id="public-link" type="text" readonly="readonly" value="{poll_url id=$poll_id}" /> <input class="form-control" id="public-link" type="text" readonly="readonly" value="{poll_url id=$poll_id}" onclick="select();"/>
</div> </div>
{if $admin} {if $admin}
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="admin-link"><a class="admin-link" href="{poll_url id=$admin_poll_id admin=true}">{__('PollInfo', 'Admin link of the poll')} <span class="btn-link glyphicon glyphicon-link"></span></a></label> <label for="admin-link"><a class="admin-link" href="{poll_url id=$admin_poll_id admin=true}">{__('PollInfo', 'Admin link of the poll')} <span class="btn-link glyphicon glyphicon-link"></span></a></label>
<input class="form-control" id="admin-link" type="text" readonly="readonly" value="{poll_url id=$admin_poll_id admin=true}" /> <input class="form-control" id="admin-link" type="text" readonly="readonly" value="{poll_url id=$admin_poll_id admin=true}" onclick="select();"/>
</div> </div>
<div id="expiration-form" class="form-group col-md-4"> <div id="expiration-form" class="form-group col-md-4">
<label class="control-label">{__('PollInfo', 'Expiration date')}</label> <label class="control-label">{__('PollInfo', 'Expiration date')}</label>
@ -123,11 +123,11 @@
<div class="col-md-4"> <div class="col-md-4">
<div id="password-form"> <div id="password-form">
{if !empty($poll->password_hash) && !$poll->results_publicly_visible} {if !empty($poll->password_hash) && !$poll->results_publicly_visible}
{$password_text = __('PollInfo', 'Password protected.')} {$password_text = __('PollInfo', 'Password protected')}
{elseif !empty($poll->password_hash) && $poll->results_publicly_visible} {elseif !empty($poll->password_hash) && $poll->results_publicly_visible}
{$password_text = __('PollInfo', 'Votes protected by password.')} {$password_text = __('PollInfo', 'Votes protected by password')}
{else} {else}
{$password_text = __('PollInfo', 'No password.')} {$password_text = __('PollInfo', 'No password')}
{/if} {/if}
<p class=""><span class="glyphicon glyphicon-lock"> </span> {$password_text}<button class="btn btn-link btn-sm btn-edit" title="{__('PollInfo', 'Edit the poll rules')}"><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button></p> <p class=""><span class="glyphicon glyphicon-lock"> </span> {$password_text}<button class="btn btn-link btn-sm btn-edit" title="{__('PollInfo', 'Edit the poll rules')}"><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button></p>
<div class="hidden js-password"> <div class="hidden js-password">
@ -135,14 +135,14 @@
{if !empty($poll->password_hash)} {if !empty($poll->password_hash)}
<div class="input-group"> <div class="input-group">
<input type="checkbox" id="removePassword" name="removePassword"/> <input type="checkbox" id="removePassword" name="removePassword"/>
<label for="removePassword">{__('PollInfo', 'Remove password.')}</label> <label for="removePassword">{__('PollInfo', 'Remove password')}</label>
<button type="submit" name="update_poll_info" value="removePassword" class="btn btn-success hidden" title="{__('PollInfo', 'Save the new rules')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Remove password.')}</span></button> <button type="submit" name="update_poll_info" value="removePassword" class="btn btn-success hidden" title="{__('PollInfo', 'Save the new rules')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Remove password.')}</span></button>
</div> </div>
{/if} {/if}
<div id="password_information"> <div id="password_information">
<div class="input-group"> <div class="input-group">
<input type="checkbox" id="resultsPubliclyVisible" name="resultsPubliclyVisible" {if $poll->results_publicly_visible}checked="checked"{/if}/> <input type="checkbox" id="resultsPubliclyVisible" name="resultsPubliclyVisible" {if $poll->results_publicly_visible}checked="checked"{/if}/>
<label for="resultsPubliclyVisible">{__('PollInfo', 'Results are visible.')}</label> <label for="resultsPubliclyVisible">{__('PollInfo', 'Results are visible')}</label>
</div> </div>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" id="password" name="password"/> <input type="text" class="form-control" id="password" name="password"/>
@ -159,16 +159,16 @@
<div id="poll-hidden-form"> <div id="poll-hidden-form">
{if $poll->hidden} {if $poll->hidden}
{$hidden_icon = "glyphicon-eye-close"} {$hidden_icon = "glyphicon-eye-close"}
{$hidden_text = __('PollInfo', 'Results are hidden.')} {$hidden_text = __('PollInfo', 'Results are hidden')}
{else} {else}
{$hidden_icon = "glyphicon-eye-open"} {$hidden_icon = "glyphicon-eye-open"}
{$hidden_text = __('PollInfo', 'Results are visible.')} {$hidden_text = __('PollInfo', 'Results are visible')}
{/if} {/if}
<p class=""><span class="glyphicon {$hidden_icon}"> </span> {$hidden_text}<button class="btn btn-link btn-sm btn-edit" title="{__('PollInfo', 'Edit the poll rules')}"><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button></p> <p class=""><span class="glyphicon {$hidden_icon}"> </span> {$hidden_text}<button class="btn btn-link btn-sm btn-edit" title="{__('PollInfo', 'Edit the poll rules')}"><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button></p>
<div class="hidden js-poll-hidden"> <div class="hidden js-poll-hidden">
<div class="input-group"> <div class="input-group">
<input type="checkbox" id="hidden" name="hidden" {if $poll->hidden}checked="checked"{/if}/> <input type="checkbox" id="hidden" name="hidden" {if $poll->hidden}checked="checked"{/if}/>
<label for="hidden">{__('PollInfo', 'Results are hidden.')}</label> <label for="hidden">{__('PollInfo', 'Results are hidden')}</label>
<span class="input-group-btn"> <span class="input-group-btn">
<button type="submit" name="update_poll_info" value="hidden" class="btn btn-success" title="{__('PollInfo', 'Save the new rules')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Save')}</span></button> <button type="submit" name="update_poll_info" value="hidden" class="btn btn-success" title="{__('PollInfo', 'Save the new rules')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Save')}</span></button>
<button class="btn btn-link btn-cancel" title="{__('PollInfo', 'Cancel the rules edit')}"><span class="glyphicon glyphicon-remove"></span><span class="sr-only">{__('Generic', 'Cancel')}</span></button> <button class="btn btn-link btn-cancel" title="{__('PollInfo', 'Cancel the rules edit')}"><span class="glyphicon glyphicon-remove"></span><span class="sr-only">{__('Generic', 'Cancel')}</span></button>
@ -183,16 +183,16 @@
{if $poll->editable} {if $poll->editable}
{if $poll->editable == constant("Framadate\Editable::EDITABLE_BY_ALL")} {if $poll->editable == constant("Framadate\Editable::EDITABLE_BY_ALL")}
{$rule_id = 2} {$rule_id = 2}
{$rule_txt = __('PollInfo', 'Votes are editable')} {$rule_txt = __('Step 1', 'All voters can modify any vote')}
{else} {else}
{$rule_id = 3} {$rule_id = 3}
{$rule_txt = __('PollInfo', 'Votes are editable solely by their owner.')} {$rule_txt = __('Step 1', 'Voters can modify their vote themselves')}
{/if} {/if}
{$rule_icon = '<span class="glyphicon glyphicon-edit"></span>'} {$rule_icon = '<span class="glyphicon glyphicon-edit"></span>'}
{else} {else}
{$rule_id = 1} {$rule_id = 1}
{$rule_icon = '<span class="glyphicon glyphicon-check"></span>'} {$rule_icon = '<span class="glyphicon glyphicon-check"></span>'}
{$rule_txt = __('PollInfo', 'Votes and comments are open')} {$rule_txt = __('Step 1', 'Votes cannot be modified')}
{/if} {/if}
{else} {else}
{$rule_id = 0} {$rule_id = 0}
@ -206,9 +206,9 @@
<div class="input-group"> <div class="input-group">
<select class="form-control" id="rules" name="rules"> <select class="form-control" id="rules" name="rules">
<option value="0"{if $rule_id==0} selected="selected"{/if}>{__('PollInfo', 'Votes and comments are locked')}</option> <option value="0"{if $rule_id==0} selected="selected"{/if}>{__('PollInfo', 'Votes and comments are locked')}</option>
<option value="1"{if $rule_id==1} selected="selected"{/if}>{__('PollInfo', 'Votes and comments are open')}</option> <option value="1"{if $rule_id==1} selected="selected"{/if}>{__('Step 1', 'Votes cannot be modified')}</option>
<option value="2"{if $rule_id==2} selected="selected"{/if}>{__('PollInfo', 'Votes are editable')}</option> <option value="3"{if $rule_id==3} selected="selected"{/if}>{__('Step 1', 'Voters can modify their vote themselves')}</option>
<option value="3"{if $rule_id==3} selected="selected"{/if}>{__('PollInfo', 'Votes are editable solely by their owner.')}</option> <option value="2"{if $rule_id==2} selected="selected"{/if}>{__('Step 1', 'All voters can modify any vote')}</option>
</select> </select>
<span class="input-group-btn"> <span class="input-group-btn">
<button type="submit" name="update_poll_info" value="rules" class="btn btn-success" title="{__('PollInfo', 'Save the new rules')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Save')}</span></button> <button type="submit" name="update_poll_info" value="rules" class="btn btn-success" title="{__('PollInfo', 'Save the new rules')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Save')}</span></button>

View File

@ -11,6 +11,7 @@
<div id="tableContainer" class="tableContainer"> <div id="tableContainer" class="tableContainer">
<form action="{if $admin}{poll_url id=$admin_poll_id admin=true}{else}{poll_url id=$poll_id}{/if}" method="POST" id="poll_form"> <form action="{if $admin}{poll_url id=$admin_poll_id admin=true}{else}{poll_url id=$poll_id}{/if}" method="POST" id="poll_form">
<input type="hidden" name="control" value="{$slots_hash}"/>
<table class="results"> <table class="results">
<caption class="sr-only">{__('Poll results', 'Votes of the poll')} {$poll->title|html}</caption> <caption class="sr-only">{__('Poll results', 'Votes of the poll')} {$poll->title|html}</caption>
<thead> <thead>
@ -26,8 +27,8 @@
</td> </td>
{/foreach} {/foreach}
<td> <td>
<a href="{poll_url id=$admin_poll_id admin=true action='add_slot' action_value=true}" <a href="{poll_url id=$admin_poll_id admin=true action='add_column'}"
class="btn btn-link btn-sm" title="{__('adminstuds', 'Add a column')} {$slot->title|html}"> class="btn btn-link btn-sm" title="{__('adminstuds', 'Add a column')}">
<i class="glyphicon glyphicon-plus text-success"></i><span class="sr-only">{__('Poll results', 'Add a column')}</span> <i class="glyphicon glyphicon-plus text-success"></i><span class="sr-only">{__('Poll results', 'Add a column')}</span>
</a> </a>
</td> </td>
@ -36,15 +37,16 @@
<tr> <tr>
<th role="presentation"></th> <th role="presentation"></th>
{foreach $slots as $id=>$slot} {foreach $slots as $id=>$slot}
<th class="bg-info" id="C{$id}">{$slot->title|markdown}</th> <th class="bg-info" id="C{$id}" title="{$slot->title|markdown:true}">{$slot->title|markdown}</th>
{/foreach} {/foreach}
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{foreach $votes as $vote} {foreach $votes as $vote}
{* Edited line *}
{if $editingVoteId === $vote->uniqId} {* Edited line *} {if $editingVoteId === $vote->uniqId && !$expired}
<tr class="hidden-print"> <tr class="hidden-print">
<td class="bg-info" style="padding:5px"> <td class="bg-info" style="padding:5px">
@ -99,7 +101,14 @@
{/foreach} {/foreach}
{if $active && !$expired && ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL') or $admin) && $accessGranted} {if $active && !$expired && $accessGranted &&
(
$poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL')
or $admin
or ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_OWN') && $editedVoteUniqueId == $vote->uniqId)
)
}
<td class="hidden-print"> <td class="hidden-print">
<a href="{if $admin}{poll_url id=$poll->admin_id vote_id=$vote->uniqId admin=true}{else}{poll_url id=$poll->id vote_id=$vote->uniqId}{/if}" class="btn btn-default btn-sm" title="{__('Poll results', 'Edit the line:')|html} {$vote->name|html}"> <a href="{if $admin}{poll_url id=$poll->admin_id vote_id=$vote->uniqId admin=true}{else}{poll_url id=$poll->id vote_id=$vote->uniqId}{/if}" class="btn btn-default btn-sm" title="{__('Poll results', 'Edit the line:')|html} {$vote->name|html}">
<i class="glyphicon glyphicon-pencil"></i><span class="sr-only">{__('Generic', 'Edit')}</span> <i class="glyphicon glyphicon-pencil"></i><span class="sr-only">{__('Generic', 'Edit')}</span>

View File

@ -12,6 +12,7 @@
<div id="tableContainer" class="tableContainer"> <div id="tableContainer" class="tableContainer">
<form action="{if $admin}{poll_url id=$admin_poll_id admin=true}{else}{poll_url id=$poll_id}{/if}" method="POST" id="poll_form"> <form action="{if $admin}{poll_url id=$admin_poll_id admin=true}{else}{poll_url id=$poll_id}{/if}" method="POST" id="poll_form">
<input type="hidden" name="control" value="{$slots_hash}"/>
<table class="results"> <table class="results">
<caption class="sr-only">{__('Poll results', 'Votes of the poll')} {$poll->title|html}</caption> <caption class="sr-only">{__('Poll results', 'Votes of the poll')} {$poll->title|html}</caption>
<thead> <thead>
@ -22,7 +23,7 @@
{foreach $slots as $slot} {foreach $slots as $slot}
{foreach $slot->moments as $id=>$moment} {foreach $slot->moments as $id=>$moment}
<td headers="M{$slot@key} D{$headersDCount} H{$headersDCount}"> <td headers="M{$slot@key} D{$headersDCount} H{$headersDCount}">
<a href="{poll_url id=$admin_poll_id admin=true action='delete_column' action_value=$slot->day|cat:'@'|cat:urlencode($moment)}" <a href="{poll_url id=$admin_poll_id admin=true action='delete_column' action_value=$slot->day|cat:'@'|cat:$moment}"
class="btn btn-link btn-sm" class="btn btn-link btn-sm"
title="{__('adminstuds', 'Remove the column')} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}"> title="{__('adminstuds', 'Remove the column')} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
<i class="glyphicon glyphicon-remove text-danger"></i><span class="sr-only">{__('Generic', 'Remove')}</span> <i class="glyphicon glyphicon-remove text-danger"></i><span class="sr-only">{__('Generic', 'Remove')}</span>
@ -32,8 +33,8 @@
{/foreach} {/foreach}
{/foreach} {/foreach}
<td> <td>
<a href="{poll_url id=$admin_poll_id admin=true action='add_slot' action_value=true}" <a href="{poll_url id=$admin_poll_id admin=true action='add_column'}"
class="btn btn-link btn-sm" title="{__('adminstuds', 'Add a column')} {$slot->day|html}"> class="btn btn-link btn-sm" title="{__('adminstuds', 'Add a column')}">
<i class="glyphicon glyphicon-plus text-success"></i><span class="sr-only">{__('Poll results', 'Add a column')}</span> <i class="glyphicon glyphicon-plus text-success"></i><span class="sr-only">{__('Poll results', 'Add a column')}</span>
</a> </a>
</td> </td>
@ -150,7 +151,13 @@
{/foreach} {/foreach}
{if $active && !$expired && ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL') or $admin) && $accessGranted} {if $active && !$expired && $accessGranted &&
(
$poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL')
or $admin
or ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_OWN') && $editedVoteUniqueId == $vote->uniqId)
)
}
<td class="hidden-print"> <td class="hidden-print">
<a href="{if $admin}{poll_url id=$poll->admin_id vote_id=$vote->uniqId admin=true}{else}{poll_url id=$poll->id vote_id=$vote->uniqId}{/if}" class="btn btn-default btn-sm" title="{__('Poll results', 'Edit the line:')|escape} {$vote->name|html}"> <a href="{if $admin}{poll_url id=$poll->admin_id vote_id=$vote->uniqId admin=true}{else}{poll_url id=$poll->id vote_id=$vote->uniqId}{/if}" class="btn btn-default btn-sm" title="{__('Poll results', 'Edit the line:')|escape} {$vote->name|html}">
<i class="glyphicon glyphicon-pencil"></i><span class="sr-only">{__('Generic', 'Edit')}</span> <i class="glyphicon glyphicon-pencil"></i><span class="sr-only">{__('Generic', 'Edit')}</span>