mirror of
https://github.com/YunoHost-Apps/kanboard_ynh.git
synced 2024-09-03 19:36:17 +02:00
Update kanboard v1.0.13
This commit is contained in:
parent
932fb1198c
commit
4ce57aec07
252 changed files with 11509 additions and 795 deletions
83
sources/app/Action/TaskAssignColorColumn.php
Normal file
83
sources/app/Action/TaskAssignColorColumn.php
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Action;
|
||||||
|
|
||||||
|
use Model\Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign a color to a task
|
||||||
|
*
|
||||||
|
* @package action
|
||||||
|
*/
|
||||||
|
class TaskAssignColorColumn extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the list of compatible events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCompatibleEvents()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
Task::EVENT_MOVE_COLUMN,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the action (defined by the user)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getActionRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'column_id' => t('Column'),
|
||||||
|
'color_id' => t('Color'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the event
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getEventRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'task_id',
|
||||||
|
'column_id',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the action (set the task color)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool True if the action was executed or false when not executed
|
||||||
|
*/
|
||||||
|
public function doAction(array $data)
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'id' => $data['task_id'],
|
||||||
|
'color_id' => $this->getParam('color_id'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->taskModification->update($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the event data meet the action condition
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasRequiredCondition(array $data)
|
||||||
|
{
|
||||||
|
return $data['column_id'] == $this->getParam('column_id');
|
||||||
|
}
|
||||||
|
}
|
90
sources/app/Action/TaskMoveColumnAssigned.php
Normal file
90
sources/app/Action/TaskMoveColumnAssigned.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Action;
|
||||||
|
|
||||||
|
use Model\Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a task to another column when an assignee is set
|
||||||
|
*
|
||||||
|
* @package action
|
||||||
|
* @author Francois Ferrand
|
||||||
|
*/
|
||||||
|
class TaskMoveColumnAssigned extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the list of compatible events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCompatibleEvents()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
Task::EVENT_ASSIGNEE_CHANGE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the action (defined by the user)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getActionRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'src_column_id' => t('Source column'),
|
||||||
|
'dest_column_id' => t('Destination column')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the event
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getEventRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'task_id',
|
||||||
|
'column_id',
|
||||||
|
'project_id',
|
||||||
|
'owner_id'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the action (move the task to another column)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool True if the action was executed or false when not executed
|
||||||
|
*/
|
||||||
|
public function doAction(array $data)
|
||||||
|
{
|
||||||
|
$original_task = $this->taskFinder->getById($data['task_id']);
|
||||||
|
|
||||||
|
return $this->taskPosition->movePosition(
|
||||||
|
$data['project_id'],
|
||||||
|
$data['task_id'],
|
||||||
|
$this->getParam('dest_column_id'),
|
||||||
|
$original_task['position'],
|
||||||
|
$original_task['swimlane_id'],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the event data meet the action condition
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasRequiredCondition(array $data)
|
||||||
|
{
|
||||||
|
return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'];
|
||||||
|
}
|
||||||
|
}
|
90
sources/app/Action/TaskMoveColumnUnAssigned.php
Normal file
90
sources/app/Action/TaskMoveColumnUnAssigned.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Action;
|
||||||
|
|
||||||
|
use Model\Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a task to another column when an assignee is cleared
|
||||||
|
*
|
||||||
|
* @package action
|
||||||
|
* @author Francois Ferrand
|
||||||
|
*/
|
||||||
|
class TaskMoveColumnUnAssigned extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the list of compatible events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCompatibleEvents()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
Task::EVENT_ASSIGNEE_CHANGE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the action (defined by the user)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getActionRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'src_column_id' => t('Source column'),
|
||||||
|
'dest_column_id' => t('Destination column')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the event
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getEventRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'task_id',
|
||||||
|
'column_id',
|
||||||
|
'project_id',
|
||||||
|
'owner_id'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the action (move the task to another column)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool True if the action was executed or false when not executed
|
||||||
|
*/
|
||||||
|
public function doAction(array $data)
|
||||||
|
{
|
||||||
|
$original_task = $this->taskFinder->getById($data['task_id']);
|
||||||
|
|
||||||
|
return $this->taskPosition->movePosition(
|
||||||
|
$data['project_id'],
|
||||||
|
$data['task_id'],
|
||||||
|
$this->getParam('dest_column_id'),
|
||||||
|
$original_task['position'],
|
||||||
|
$original_task['swimlane_id'],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the event data meet the action condition
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasRequiredCondition(array $data)
|
||||||
|
{
|
||||||
|
return $data['column_id'] == $this->getParam('src_column_id') && ! $data['owner_id'];
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ use Pimple\Container;
|
||||||
* @package auth
|
* @package auth
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*
|
*
|
||||||
|
* @property \Core\Session $session
|
||||||
* @property \Model\Acl $acl
|
* @property \Model\Acl $acl
|
||||||
* @property \Model\LastLogin $lastLogin
|
* @property \Model\LastLogin $lastLogin
|
||||||
* @property \Model\User $user
|
* @property \Model\User $user
|
||||||
|
|
|
@ -34,7 +34,7 @@ class GitHub extends Base
|
||||||
{
|
{
|
||||||
$user = $this->user->getByGitHubId($github_id);
|
$user = $this->user->getByGitHubId($github_id);
|
||||||
|
|
||||||
if ($user) {
|
if (! empty($user)) {
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->refresh($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Google extends Base
|
||||||
{
|
{
|
||||||
$user = $this->user->getByGoogleId($google_id);
|
$user = $this->user->getByGoogleId($google_id);
|
||||||
|
|
||||||
if ($user) {
|
if (! empty($user)) {
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->refresh($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Ldap extends Base
|
||||||
|
|
||||||
$user = $this->user->getByUsername($username);
|
$user = $this->user->getByUsername($username);
|
||||||
|
|
||||||
if ($user) {
|
if (! empty($user)) {
|
||||||
|
|
||||||
// There is already a local user with that name
|
// There is already a local user with that name
|
||||||
if ($user['is_ldap_user'] == 0) {
|
if ($user['is_ldap_user'] == 0) {
|
||||||
|
@ -241,7 +241,7 @@ class Ldap extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
// User id not retrieved: LDAP_ACCOUNT_ID not properly configured
|
// User id not retrieved: LDAP_ACCOUNT_ID not properly configured
|
||||||
if (! $username && ! isset($info[0][LDAP_ACCOUNT_ID][0])) {
|
if (empty($username) && ! isset($info[0][LDAP_ACCOUNT_ID][0])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ class Ldap extends Base
|
||||||
private function getQuery($username, $email)
|
private function getQuery($username, $email)
|
||||||
{
|
{
|
||||||
if ($username && $email) {
|
if ($username && $email) {
|
||||||
return '(&('.sprintf(LDAP_USER_PATTERN, $username).')('.sprintf(LDAP_ACCOUNT_EMAIL, $email).')';
|
return '(&('.sprintf(LDAP_USER_PATTERN, $username).')('.LDAP_ACCOUNT_EMAIL.'='.$email.'))';
|
||||||
}
|
}
|
||||||
else if ($username) {
|
else if ($username) {
|
||||||
return sprintf(LDAP_USER_PATTERN, $username);
|
return sprintf(LDAP_USER_PATTERN, $username);
|
||||||
|
|
|
@ -103,6 +103,9 @@ class RememberMe extends Base
|
||||||
// Create the session
|
// Create the session
|
||||||
$this->userSession->refresh($this->user->getById($record['user_id']));
|
$this->userSession->refresh($this->user->getById($record['user_id']));
|
||||||
|
|
||||||
|
// Do not ask 2FA for remember me session
|
||||||
|
$this->session['2fa_validated'] = true;
|
||||||
|
|
||||||
$this->container['dispatcher']->dispatch(
|
$this->container['dispatcher']->dispatch(
|
||||||
'auth.success',
|
'auth.success',
|
||||||
new AuthEvent(self::AUTH_NAME, $this->userSession->getId())
|
new AuthEvent(self::AUTH_NAME, $this->userSession->getId())
|
||||||
|
|
|
@ -32,7 +32,7 @@ class ReverseProxy extends Base
|
||||||
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
|
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
|
||||||
$user = $this->user->getByUsername($login);
|
$user = $this->user->getByUsername($login);
|
||||||
|
|
||||||
if (! $user) {
|
if (empty($user)) {
|
||||||
$this->createUser($login);
|
$this->createUser($login);
|
||||||
$user = $this->user->getByUsername($login);
|
$user = $this->user->getByUsername($login);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use Symfony\Component\Console\Command\Command;
|
||||||
* @property \Model\Task $task
|
* @property \Model\Task $task
|
||||||
* @property \Model\TaskExport $taskExport
|
* @property \Model\TaskExport $taskExport
|
||||||
* @property \Model\TaskFinder $taskFinder
|
* @property \Model\TaskFinder $taskFinder
|
||||||
|
* @property \Model\Transition $transition
|
||||||
*/
|
*/
|
||||||
abstract class Base extends Command
|
abstract class Base extends Command
|
||||||
{
|
{
|
||||||
|
|
34
sources/app/Console/TransitionExport.php
Normal file
34
sources/app/Console/TransitionExport.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Console;
|
||||||
|
|
||||||
|
use Core\Tool;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class TransitionExport extends Base
|
||||||
|
{
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('export:transitions')
|
||||||
|
->setDescription('Task transitions CSV export')
|
||||||
|
->addArgument('project_id', InputArgument::REQUIRED, 'Project id')
|
||||||
|
->addArgument('start_date', InputArgument::REQUIRED, 'Start date (YYYY-MM-DD)')
|
||||||
|
->addArgument('end_date', InputArgument::REQUIRED, 'End date (YYYY-MM-DD)');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$data = $this->transition->export(
|
||||||
|
$input->getArgument('project_id'),
|
||||||
|
$input->getArgument('start_date'),
|
||||||
|
$input->getArgument('end_date')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (is_array($data)) {
|
||||||
|
Tool::csv($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -157,7 +157,7 @@ class Action extends Base
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$action = $this->action->getById($this->request->getIntegerParam('action_id'));
|
$action = $this->action->getById($this->request->getIntegerParam('action_id'));
|
||||||
|
|
||||||
if ($action && $this->action->remove($action['id'])) {
|
if (! empty($action) && $this->action->remove($action['id'])) {
|
||||||
$this->session->flash(t('Action removed successfully.'));
|
$this->session->flash(t('Action removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this action.'));
|
$this->session->flashError(t('Unable to remove this action.'));
|
||||||
|
|
|
@ -46,21 +46,21 @@ class App extends Base
|
||||||
$project_ids = array_keys($projects);
|
$project_ids = array_keys($projects);
|
||||||
|
|
||||||
$task_paginator = $this->paginator
|
$task_paginator = $this->paginator
|
||||||
->setUrl('app', $action, array('pagination' => 'tasks'))
|
->setUrl('app', $action, array('pagination' => 'tasks', 'user_id' => $user_id))
|
||||||
->setMax(10)
|
->setMax(10)
|
||||||
->setOrder('tasks.id')
|
->setOrder('tasks.id')
|
||||||
->setQuery($this->taskFinder->getUserQuery($user_id))
|
->setQuery($this->taskFinder->getUserQuery($user_id))
|
||||||
->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks');
|
->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks');
|
||||||
|
|
||||||
$subtask_paginator = $this->paginator
|
$subtask_paginator = $this->paginator
|
||||||
->setUrl('app', $action, array('pagination' => 'subtasks'))
|
->setUrl('app', $action, array('pagination' => 'subtasks', 'user_id' => $user_id))
|
||||||
->setMax(10)
|
->setMax(10)
|
||||||
->setOrder('tasks.id')
|
->setOrder('tasks.id')
|
||||||
->setQuery($this->subtask->getUserQuery($user_id, $status))
|
->setQuery($this->subtask->getUserQuery($user_id, $status))
|
||||||
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
|
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
|
||||||
|
|
||||||
$project_paginator = $this->paginator
|
$project_paginator = $this->paginator
|
||||||
->setUrl('app', $action, array('pagination' => 'projects'))
|
->setUrl('app', $action, array('pagination' => 'projects', 'user_id' => $user_id))
|
||||||
->setMax(10)
|
->setMax(10)
|
||||||
->setOrder('name')
|
->setOrder('name')
|
||||||
->setQuery($this->project->getQueryColumnStats($project_ids))
|
->setQuery($this->project->getQueryColumnStats($project_ids))
|
||||||
|
|
|
@ -34,6 +34,7 @@ use Symfony\Component\EventDispatcher\Event;
|
||||||
* @property \Model\Config $config
|
* @property \Model\Config $config
|
||||||
* @property \Model\DateParser $dateParser
|
* @property \Model\DateParser $dateParser
|
||||||
* @property \Model\File $file
|
* @property \Model\File $file
|
||||||
|
* @property \Model\HourlyRate $hourlyRate
|
||||||
* @property \Model\LastLogin $lastLogin
|
* @property \Model\LastLogin $lastLogin
|
||||||
* @property \Model\Notification $notification
|
* @property \Model\Notification $notification
|
||||||
* @property \Model\Project $project
|
* @property \Model\Project $project
|
||||||
|
@ -43,6 +44,7 @@ use Symfony\Component\EventDispatcher\Event;
|
||||||
* @property \Model\ProjectActivity $projectActivity
|
* @property \Model\ProjectActivity $projectActivity
|
||||||
* @property \Model\ProjectDailySummary $projectDailySummary
|
* @property \Model\ProjectDailySummary $projectDailySummary
|
||||||
* @property \Model\Subtask $subtask
|
* @property \Model\Subtask $subtask
|
||||||
|
* @property \Model\SubtaskForecast $subtaskForecast
|
||||||
* @property \Model\Swimlane $swimlane
|
* @property \Model\Swimlane $swimlane
|
||||||
* @property \Model\Task $task
|
* @property \Model\Task $task
|
||||||
* @property \Model\Link $link
|
* @property \Model\Link $link
|
||||||
|
@ -56,12 +58,16 @@ use Symfony\Component\EventDispatcher\Event;
|
||||||
* @property \Model\TaskPosition $taskPosition
|
* @property \Model\TaskPosition $taskPosition
|
||||||
* @property \Model\TaskPermission $taskPermission
|
* @property \Model\TaskPermission $taskPermission
|
||||||
* @property \Model\TaskStatus $taskStatus
|
* @property \Model\TaskStatus $taskStatus
|
||||||
|
* @property \Model\Timetable $timetable
|
||||||
|
* @property \Model\TimetableDay $timetableDay
|
||||||
|
* @property \Model\TimetableWeek $timetableWeek
|
||||||
|
* @property \Model\TimetableExtra $timetableExtra
|
||||||
|
* @property \Model\TimetableOff $timetableOff
|
||||||
* @property \Model\TaskValidator $taskValidator
|
* @property \Model\TaskValidator $taskValidator
|
||||||
* @property \Model\TaskLink $taskLink
|
* @property \Model\TaskLink $taskLink
|
||||||
* @property \Model\CommentHistory $commentHistory
|
* @property \Model\CommentHistory $commentHistory
|
||||||
* @property \Model\SubtaskHistory $subtaskHistory
|
* @property \Model\SubtaskHistory $subtaskHistory
|
||||||
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
|
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
|
||||||
* @property \Model\TimeTracking $timeTracking
|
|
||||||
* @property \Model\User $user
|
* @property \Model\User $user
|
||||||
* @property \Model\UserSession $userSession
|
* @property \Model\UserSession $userSession
|
||||||
* @property \Model\Webhook $webhook
|
* @property \Model\Webhook $webhook
|
||||||
|
@ -148,7 +154,7 @@ abstract class Base
|
||||||
$this->response->xss();
|
$this->response->xss();
|
||||||
|
|
||||||
// Allow the public board iframe inclusion
|
// Allow the public board iframe inclusion
|
||||||
if ($action !== 'readonly') {
|
if (ENABLE_XFRAME && $action !== 'readonly') {
|
||||||
$this->response->xframe();
|
$this->response->xframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +177,7 @@ abstract class Base
|
||||||
|
|
||||||
if (! $this->acl->isPublicAction($controller, $action)) {
|
if (! $this->acl->isPublicAction($controller, $action)) {
|
||||||
$this->handleAuthentication();
|
$this->handleAuthentication();
|
||||||
|
$this->handle2FA($controller, $action);
|
||||||
$this->handleAuthorization($controller, $action);
|
$this->handleAuthorization($controller, $action);
|
||||||
|
|
||||||
$this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
$this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
||||||
|
@ -194,6 +201,25 @@ abstract class Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check 2FA
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function handle2FA($controller, $action)
|
||||||
|
{
|
||||||
|
$ignore = ($controller === 'twofactor' && in_array($action, array('code', 'check'))) || ($controller === 'user' && $action === 'logout');
|
||||||
|
|
||||||
|
if ($ignore === false && $this->userSession->has2FA() && ! $this->userSession->check2FA()) {
|
||||||
|
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
$this->response->text('Not Authorized', 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('twofactor', 'code'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check page access and authorization
|
* Check page access and authorization
|
||||||
*
|
*
|
||||||
|
@ -311,7 +337,7 @@ abstract class Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
||||||
|
|
||||||
if (! $task) {
|
if (empty($task)) {
|
||||||
$this->notfound();
|
$this->notfound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +356,7 @@ abstract class Base
|
||||||
$project_id = $this->request->getIntegerParam('project_id', $project_id);
|
$project_id = $this->request->getIntegerParam('project_id', $project_id);
|
||||||
$project = $this->project->getById($project_id);
|
$project = $this->project->getById($project_id);
|
||||||
|
|
||||||
if (! $project) {
|
if (empty($project)) {
|
||||||
$this->session->flashError(t('Project not found.'));
|
$this->session->flashError(t('Project not found.'));
|
||||||
$this->response->redirect('?controller=project');
|
$this->response->redirect('?controller=project');
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ class Board extends Base
|
||||||
$project = $this->project->getByToken($token);
|
$project = $this->project->getByToken($token);
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (! $project) {
|
if (empty($project)) {
|
||||||
$this->forbidden(true);
|
$this->forbidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,7 @@ class Board extends Base
|
||||||
'swimlanes' => $this->board->getBoard($project['id']),
|
'swimlanes' => $this->board->getBoard($project['id']),
|
||||||
'categories' => $this->category->getList($project['id'], false),
|
'categories' => $this->category->getList($project['id'], false),
|
||||||
'title' => $project['name'],
|
'title' => $project['name'],
|
||||||
|
'description' => $project['description'],
|
||||||
'no_layout' => true,
|
'no_layout' => true,
|
||||||
'not_editable' => true,
|
'not_editable' => true,
|
||||||
'board_public_refresh_interval' => $this->config->get('board_public_refresh_interval'),
|
'board_public_refresh_interval' => $this->config->get('board_public_refresh_interval'),
|
||||||
|
@ -187,6 +188,7 @@ class Board extends Base
|
||||||
'swimlanes' => $this->board->getBoard($project['id']),
|
'swimlanes' => $this->board->getBoard($project['id']),
|
||||||
'categories' => $this->category->getList($project['id'], true, true),
|
'categories' => $this->category->getList($project['id'], true, true),
|
||||||
'title' => $project['name'],
|
'title' => $project['name'],
|
||||||
|
'description' => $project['description'],
|
||||||
'board_selector' => $board_selector,
|
'board_selector' => $board_selector,
|
||||||
'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
|
'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
|
||||||
'board_highlight_period' => $this->config->get('board_highlight_period'),
|
'board_highlight_period' => $this->config->get('board_highlight_period'),
|
||||||
|
@ -309,7 +311,7 @@ class Board extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
$column = $this->board->getColumn($this->request->getIntegerParam('column_id'));
|
$column = $this->board->getColumn($this->request->getIntegerParam('column_id'));
|
||||||
|
|
||||||
if ($column && $this->board->removeColumn($column['id'])) {
|
if (! empty($column) && $this->board->removeColumn($column['id'])) {
|
||||||
$this->session->flash(t('Column removed successfully.'));
|
$this->session->flash(t('Column removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this column.'));
|
$this->session->flashError(t('Unable to remove this column.'));
|
||||||
|
@ -439,7 +441,8 @@ class Board extends Base
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
|
||||||
$this->response->html($this->template->render('board/files', array(
|
$this->response->html($this->template->render('board/files', array(
|
||||||
'files' => $this->file->getAll($task['id']),
|
'files' => $this->file->getAllDocuments($task['id']),
|
||||||
|
'images' => $this->file->getAllImages($task['id']),
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
135
sources/app/Controller/Budget.php
Normal file
135
sources/app/Controller/Budget.php
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Budget
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Budget extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Budget index page
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$this->response->html($this->projectLayout('budget/index', array(
|
||||||
|
'daily_budget' => $this->budget->getDailyBudgetBreakdown($project['id']),
|
||||||
|
'project' => $project,
|
||||||
|
'title' => t('Budget')
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cost breakdown by users/subtasks/tasks
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function breakdown()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$paginator = $this->paginator
|
||||||
|
->setUrl('budget', 'breakdown', array('project_id' => $project['id']))
|
||||||
|
->setMax(30)
|
||||||
|
->setOrder('start')
|
||||||
|
->setDirection('DESC')
|
||||||
|
->setQuery($this->budget->getSubtaskBreakdown($project['id']))
|
||||||
|
->calculate();
|
||||||
|
|
||||||
|
$this->response->html($this->projectLayout('budget/breakdown', array(
|
||||||
|
'paginator' => $paginator,
|
||||||
|
'project' => $project,
|
||||||
|
'title' => t('Budget')
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create budget lines
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function create(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
$values['date'] = date('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->html($this->projectLayout('budget/create', array(
|
||||||
|
'lines' => $this->budget->getAll($project['id']),
|
||||||
|
'values' => $values + array('project_id' => $project['id']),
|
||||||
|
'errors' => $errors,
|
||||||
|
'project' => $project,
|
||||||
|
'title' => t('Budget')
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and save a new budget
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->budget->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
|
||||||
|
if ($this->budget->create($values['project_id'], $values['amount'], $values['comment'], $values['date'])) {
|
||||||
|
$this->session->flash(t('The budget line have been created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url('budget', 'create', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to create the budget line.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->create($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirmation dialog before removing a budget
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$this->response->html($this->projectLayout('budget/remove', array(
|
||||||
|
'project' => $project,
|
||||||
|
'budget_id' => $this->request->getIntegerParam('budget_id'),
|
||||||
|
'title' => t('Remove a budget line'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a budget
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
if ($this->budget->remove($this->request->getIntegerParam('budget_id'))) {
|
||||||
|
$this->session->flash(t('Budget line removed successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->session->flashError(t('Unable to remove this budget line.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('budget', 'create', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ use Model\Task as TaskModel;
|
||||||
class Calendar extends Base
|
class Calendar extends Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show calendar view
|
* Show calendar view for projects
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
|
@ -59,9 +59,7 @@ class Calendar extends Base
|
||||||
->filterByDueDateRange($start, $end)
|
->filterByDueDateRange($start, $end)
|
||||||
->toCalendarEvents();
|
->toCalendarEvents();
|
||||||
|
|
||||||
$subtask_timeslots = $this->subtaskTimeTracking->getProjectCalendarEvents($project_id, $start, $end);
|
$this->response->json($due_tasks);
|
||||||
|
|
||||||
$this->response->json(array_merge($due_tasks, $subtask_timeslots));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,7 +82,9 @@ class Calendar extends Base
|
||||||
|
|
||||||
$subtask_timeslots = $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end);
|
$subtask_timeslots = $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end);
|
||||||
|
|
||||||
$this->response->json(array_merge($due_tasks, $subtask_timeslots));
|
$subtask_forcast = $this->config->get('subtask_forecast') == 1 ? $this->subtaskForecast->getCalendarEvents($user_id, $end) : array();
|
||||||
|
|
||||||
|
$this->response->json(array_merge($due_tasks, $subtask_timeslots, $subtask_forcast));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,7 +100,7 @@ class Calendar extends Base
|
||||||
|
|
||||||
$this->taskModification->update(array(
|
$this->taskModification->update(array(
|
||||||
'id' => $values['task_id'],
|
'id' => $values['task_id'],
|
||||||
'date_due' => $values['date_due'],
|
'date_due' => substr($values['date_due'], 0, 10),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Category extends Base
|
||||||
{
|
{
|
||||||
$category = $this->category->getById($this->request->getIntegerParam('category_id'));
|
$category = $this->category->getById($this->request->getIntegerParam('category_id'));
|
||||||
|
|
||||||
if (! $category) {
|
if (empty($category)) {
|
||||||
$this->session->flashError(t('Category not found.'));
|
$this->session->flashError(t('Category not found.'));
|
||||||
$this->response->redirect('?controller=category&action=index&project_id='.$project_id);
|
$this->response->redirect('?controller=category&action=index&project_id='.$project_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Comment extends Base
|
||||||
{
|
{
|
||||||
$comment = $this->comment->getById($this->request->getIntegerParam('comment_id'));
|
$comment = $this->comment->getById($this->request->getIntegerParam('comment_id'));
|
||||||
|
|
||||||
if (! $comment) {
|
if (empty($comment)) {
|
||||||
$this->notfound();
|
$this->notfound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,14 @@ class Config extends Base
|
||||||
{
|
{
|
||||||
if ($this->request->isPost()) {
|
if ($this->request->isPost()) {
|
||||||
|
|
||||||
$values = $this->request->getValues() + array('subtask_restriction' => 0, 'subtask_time_tracking' => 0);
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if ($redirect === 'board') {
|
||||||
|
$values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0, 'subtask_forecast' => 0);
|
||||||
|
}
|
||||||
|
else if ($redirect === 'integrations') {
|
||||||
|
$values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->config->save($values)) {
|
if ($this->config->save($values)) {
|
||||||
$this->config->reload();
|
$this->config->reload();
|
||||||
|
@ -97,6 +104,20 @@ class Config extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the integration settings page
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function integrations()
|
||||||
|
{
|
||||||
|
$this->common('integrations');
|
||||||
|
|
||||||
|
$this->response->html($this->layout('config/integrations', array(
|
||||||
|
'title' => t('Settings').' > '.t('Integrations'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the webhook settings page
|
* Display the webhook settings page
|
||||||
*
|
*
|
||||||
|
|
89
sources/app/Controller/Currency.php
Normal file
89
sources/app/Controller/Currency.php
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currency controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Currency extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Common layout for config views
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $template Template name
|
||||||
|
* @param array $params Template parameters
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function layout($template, array $params)
|
||||||
|
{
|
||||||
|
$params['board_selector'] = $this->projectPermission->getAllowedProjects($this->userSession->getId());
|
||||||
|
$params['config_content_for_layout'] = $this->template->render($template, $params);
|
||||||
|
|
||||||
|
return $this->template->layout('config/layout', $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display all currency rates and form
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$this->response->html($this->layout('currency/index', array(
|
||||||
|
'config_values' => array('application_currency' => $this->config->get('application_currency')),
|
||||||
|
'values' => $values,
|
||||||
|
'errors' => $errors,
|
||||||
|
'rates' => $this->currency->getAll(),
|
||||||
|
'currencies' => $this->config->getCurrencies(),
|
||||||
|
'title' => t('Settings').' > '.t('Currency rates'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and save a new currency rate
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->currency->validate($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
|
||||||
|
if ($this->currency->create($values['currency'], $values['rate'])) {
|
||||||
|
$this->session->flash(t('The currency rate have been added successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url('currency', 'index'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to add this currency rate.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save reference currency
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function reference()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if ($this->config->save($values)) {
|
||||||
|
$this->config->reload();
|
||||||
|
$this->session->flash(t('Settings saved successfully.'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to save your settings.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('currency', 'index'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,4 +72,14 @@ class Export extends Base
|
||||||
{
|
{
|
||||||
$this->common('projectDailySummary', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
|
$this->common('projectDailySummary', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition export
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function transitions()
|
||||||
|
{
|
||||||
|
$this->common('transition', 'export', t('Transitions'), 'transitions', t('Task transitions export'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,70 @@ class File extends Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return image thumbnails
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function thumbnail()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||||
|
$width_param = $this->request->getIntegerParam('width');
|
||||||
|
$height_param = $this->request->getIntegerParam('height');
|
||||||
|
$filename = FILES_DIR.$file['path'];
|
||||||
|
|
||||||
|
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
||||||
|
|
||||||
|
// Get new sizes
|
||||||
|
list($width, $height) = getimagesize($filename);
|
||||||
|
|
||||||
|
if ($width_param == 0 && $height_param == 0) {
|
||||||
|
$newwidth = 100;
|
||||||
|
$newheight = 100;
|
||||||
|
} elseif ($width_param > 0 && $height_param == 0) {
|
||||||
|
$newwidth = $width_param;
|
||||||
|
$newheight = floor($height * ($width_param / $width));
|
||||||
|
} elseif ($width_param == 0 && $height_param > 0) {
|
||||||
|
$newwidth = floor($width * ($height_param / $height));
|
||||||
|
$newheight = $height_param;
|
||||||
|
} else {
|
||||||
|
$newwidth = $width_param;
|
||||||
|
$newheight = $height_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load
|
||||||
|
$thumb = imagecreatetruecolor($newwidth, $newheight);
|
||||||
|
$extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
switch ($extension) {
|
||||||
|
case 'jpeg':
|
||||||
|
case 'jpg':
|
||||||
|
$source = imagecreatefromjpeg($filename);
|
||||||
|
break;
|
||||||
|
case 'png':
|
||||||
|
$source = imagecreatefrompng($filename);
|
||||||
|
break;
|
||||||
|
case 'gif':
|
||||||
|
$source = imagecreatefromgif($filename);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
die('File "' . $filename . '" is not valid jpg, png or gif image.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize
|
||||||
|
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
|
||||||
|
|
||||||
|
$metadata = getimagesize($filename);
|
||||||
|
|
||||||
|
if (isset($metadata['mime'])) {
|
||||||
|
$this->response->contentType($metadata['mime']);
|
||||||
|
imagejpeg($thumb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a file
|
* Remove a file
|
||||||
*
|
*
|
||||||
|
|
89
sources/app/Controller/Hourlyrate.php
Normal file
89
sources/app/Controller/Hourlyrate.php
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hourly Rate controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Hourlyrate extends User
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display rate and form
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout('hourlyrate/index', array(
|
||||||
|
'rates' => $this->hourlyRate->getAllByUser($user['id']),
|
||||||
|
'currencies_list' => $this->config->getCurrencies(),
|
||||||
|
'values' => $values + array('user_id' => $user['id']),
|
||||||
|
'errors' => $errors,
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and save a new rate
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->hourlyRate->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
|
||||||
|
if ($this->hourlyRate->create($values['user_id'], $values['rate'], $values['currency'], $values['date_effective'])) {
|
||||||
|
$this->session->flash(t('Hourly rate created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url('hourlyrate', 'index', array('user_id' => $values['user_id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to save the hourly rate.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirmation dialag box to remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout('hourlyrate/remove', array(
|
||||||
|
'rate_id' => $this->request->getIntegerParam('rate_id'),
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if ($this->hourlyRate->remove($this->request->getIntegerParam('rate_id'))) {
|
||||||
|
$this->session->flash(t('Rate removed successfully.'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flash(t('Unable to remove this rate.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('hourlyrate', 'index', array('user_id' => $user['id'])));
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ class Link extends Base
|
||||||
{
|
{
|
||||||
$link = $this->link->getById($this->request->getIntegerParam('link_id'));
|
$link = $this->link->getById($this->request->getIntegerParam('link_id'));
|
||||||
|
|
||||||
if (! $link) {
|
if (empty($link)) {
|
||||||
$this->notfound();
|
$this->notfound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,11 @@ class Project extends Base
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if ($project['is_private'] == 1) {
|
||||||
|
$values += array('is_private' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
list($valid, $errors) = $this->project->validateModification($values);
|
list($valid, $errors) = $this->project->validateModification($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Subtask extends Base
|
||||||
{
|
{
|
||||||
$subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
|
$subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
|
||||||
|
|
||||||
if (! $subtask) {
|
if (empty($subtask)) {
|
||||||
$this->notfound();
|
$this->notfound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,4 +259,22 @@ class Subtask extends Base
|
||||||
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move subtask position
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function movePosition()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$project_id = $this->request->getIntegerParam('project_id');
|
||||||
|
$task_id = $this->request->getIntegerParam('task_id');
|
||||||
|
$subtask_id = $this->request->getIntegerParam('subtask_id');
|
||||||
|
$direction = $this->request->getStringParam('direction');
|
||||||
|
$method = $direction === 'up' ? 'moveUp' : 'moveDown';
|
||||||
|
|
||||||
|
$this->subtask->$method($task_id, $subtask_id);
|
||||||
|
$this->response->redirect($this->helper->url('task', 'show', array('project_id' => $project_id, 'task_id' => $task_id)).'#subtasks');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Swimlane extends Base
|
||||||
{
|
{
|
||||||
$swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
|
$swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
|
||||||
|
|
||||||
if (! $swimlane) {
|
if (empty($swimlane)) {
|
||||||
$this->session->flashError(t('Swimlane not found.'));
|
$this->session->flashError(t('Swimlane not found.'));
|
||||||
$this->response->redirect('?controller=swimlane&action=index&project_id='.$project_id);
|
$this->response->redirect('?controller=swimlane&action=index&project_id='.$project_id);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ class Swimlane extends Base
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
|
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues() + array('show_default_swimlane' => 0);
|
||||||
list($valid,) = $this->swimlane->validateDefaultModification($values);
|
list($valid,) = $this->swimlane->validateDefaultModification($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
|
|
|
@ -22,13 +22,13 @@ class Task extends Base
|
||||||
$project = $this->project->getByToken($this->request->getStringParam('token'));
|
$project = $this->project->getByToken($this->request->getStringParam('token'));
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (! $project) {
|
if (empty($project)) {
|
||||||
$this->forbidden(true);
|
$this->forbidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
||||||
|
|
||||||
if (! $task) {
|
if (empty($task)) {
|
||||||
$this->notfound(true);
|
$this->notfound(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,12 +68,14 @@ class Task extends Base
|
||||||
|
|
||||||
$this->response->html($this->taskLayout('task/show', array(
|
$this->response->html($this->taskLayout('task/show', array(
|
||||||
'project' => $this->project->getById($task['project_id']),
|
'project' => $this->project->getById($task['project_id']),
|
||||||
'files' => $this->file->getAll($task['id']),
|
'files' => $this->file->getAllDocuments($task['id']),
|
||||||
|
'images' => $this->file->getAllImages($task['id']),
|
||||||
'comments' => $this->comment->getAll($task['id']),
|
'comments' => $this->comment->getAll($task['id']),
|
||||||
'subtasks' => $subtasks,
|
'subtasks' => $subtasks,
|
||||||
'links' => $this->taskLink->getLinks($task['id']),
|
'links' => $this->taskLink->getLinks($task['id']),
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
|
'link_label_list' => $this->link->getList(0, false),
|
||||||
'columns_list' => $this->board->getColumnsList($task['project_id']),
|
'columns_list' => $this->board->getColumnsList($task['project_id']),
|
||||||
'colors_list' => $this->color->getList(),
|
'colors_list' => $this->color->getList(),
|
||||||
'date_format' => $this->config->get('application_date_format'),
|
'date_format' => $this->config->get('application_date_format'),
|
||||||
|
@ -82,6 +84,23 @@ class Task extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display task activities
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function activites()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task/activity', array(
|
||||||
|
'title' => $task['title'],
|
||||||
|
'task' => $task,
|
||||||
|
'ajax' => $this->request->isAjax(),
|
||||||
|
'events' => $this->projectActivity->getTask($task['id']),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a form to create a new task
|
* Display a form to create a new task
|
||||||
*
|
*
|
||||||
|
@ -91,11 +110,12 @@ class Task extends Base
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$method = $this->request->isAjax() ? 'render' : 'layout';
|
$method = $this->request->isAjax() ? 'render' : 'layout';
|
||||||
|
$swimlanes_list = $this->swimlane->getList($project['id']);
|
||||||
|
|
||||||
if (empty($values)) {
|
if (empty($values)) {
|
||||||
|
|
||||||
$values = array(
|
$values = array(
|
||||||
'swimlane_id' => $this->request->getIntegerParam('swimlane_id'),
|
'swimlane_id' => $this->request->getIntegerParam('swimlane_id', key($swimlanes_list)),
|
||||||
'column_id' => $this->request->getIntegerParam('column_id'),
|
'column_id' => $this->request->getIntegerParam('column_id'),
|
||||||
'color_id' => $this->request->getStringParam('color_id'),
|
'color_id' => $this->request->getStringParam('color_id'),
|
||||||
'owner_id' => $this->request->getIntegerParam('owner_id'),
|
'owner_id' => $this->request->getIntegerParam('owner_id'),
|
||||||
|
@ -112,6 +132,7 @@ class Task extends Base
|
||||||
'users_list' => $this->projectPermission->getMemberList($project['id'], true, false, true),
|
'users_list' => $this->projectPermission->getMemberList($project['id'], true, false, true),
|
||||||
'colors_list' => $this->color->getList(),
|
'colors_list' => $this->color->getList(),
|
||||||
'categories_list' => $this->category->getList($project['id']),
|
'categories_list' => $this->category->getList($project['id']),
|
||||||
|
'swimlanes_list' => $swimlanes_list,
|
||||||
'date_format' => $this->config->get('application_date_format'),
|
'date_format' => $this->config->get('application_date_format'),
|
||||||
'date_formats' => $this->dateParser->getAvailableFormats(),
|
'date_formats' => $this->dateParser->getAvailableFormats(),
|
||||||
'title' => $project['name'].' > '.t('New task')
|
'title' => $project['name'].' > '.t('New task')
|
||||||
|
@ -522,4 +543,19 @@ class Task extends Base
|
||||||
'subtask_paginator' => $subtask_paginator,
|
'subtask_paginator' => $subtask_paginator,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the task transitions
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function transitions()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task/transitions', array(
|
||||||
|
'task' => $task,
|
||||||
|
'transitions' => $this->transition->getAllByTask($task['id']),
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Tasklink extends Base
|
||||||
{
|
{
|
||||||
$link = $this->taskLink->getById($this->request->getIntegerParam('link_id'));
|
$link = $this->taskLink->getById($this->request->getIntegerParam('link_id'));
|
||||||
|
|
||||||
if (! $link) {
|
if (empty($link)) {
|
||||||
$this->notfound();
|
$this->notfound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ class Tasklink extends Base
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
$ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax');
|
||||||
|
|
||||||
if (empty($values)) {
|
if (empty($values)) {
|
||||||
$values = array(
|
$values = array(
|
||||||
|
@ -43,6 +44,17 @@ class Tasklink extends Base
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($ajax) {
|
||||||
|
$this->response->html($this->template->render('tasklink/create', array(
|
||||||
|
'values' => $values,
|
||||||
|
'errors' => $errors,
|
||||||
|
'task' => $task,
|
||||||
|
'labels' => $this->link->getList(0, false),
|
||||||
|
'title' => t('Add a new link'),
|
||||||
|
'ajax' => $ajax,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
$this->response->html($this->taskLayout('tasklink/create', array(
|
$this->response->html($this->taskLayout('tasklink/create', array(
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
|
@ -61,6 +73,7 @@ class Tasklink extends Base
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
|
$ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax');
|
||||||
|
|
||||||
list($valid, $errors) = $this->taskLink->validateCreation($values);
|
list($valid, $errors) = $this->taskLink->validateCreation($values);
|
||||||
|
|
||||||
|
@ -68,6 +81,9 @@ class Tasklink extends Base
|
||||||
|
|
||||||
if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
||||||
$this->session->flash(t('Link added successfully.'));
|
$this->session->flash(t('Link added successfully.'));
|
||||||
|
if ($ajax) {
|
||||||
|
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
39
sources/app/Controller/Timetable.php
Normal file
39
sources/app/Controller/Timetable.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timetable controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Timetable extends User
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display timetable for the user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$from = $this->request->getStringParam('from', date('Y-m-d'));
|
||||||
|
$to = $this->request->getStringParam('to', date('Y-m-d', strtotime('next week')));
|
||||||
|
$timetable = $this->timetable->calculate($user['id'], new DateTime($from), new DateTime($to));
|
||||||
|
|
||||||
|
$this->response->html($this->layout('timetable/index', array(
|
||||||
|
'user' => $user,
|
||||||
|
'timetable' => $timetable,
|
||||||
|
'values' => array(
|
||||||
|
'from' => $from,
|
||||||
|
'to' => $to,
|
||||||
|
'controller' => 'timetable',
|
||||||
|
'action' => 'index',
|
||||||
|
'user_id' => $user['id'],
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
88
sources/app/Controller/Timetableday.php
Normal file
88
sources/app/Controller/Timetableday.php
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Day Timetable controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Timetableday extends User
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display timetable for the user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout('timetable_day/index', array(
|
||||||
|
'timetable' => $this->timetableDay->getByUser($user['id']),
|
||||||
|
'values' => $values + array('user_id' => $user['id']),
|
||||||
|
'errors' => $errors,
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and save
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->timetableDay->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
|
||||||
|
if ($this->timetableDay->create($values['user_id'], $values['start'], $values['end'])) {
|
||||||
|
$this->session->flash(t('Time slot created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url('timetableday', 'index', array('user_id' => $values['user_id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to save this time slot.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirmation dialag box to remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout('timetable_day/remove', array(
|
||||||
|
'slot_id' => $this->request->getIntegerParam('slot_id'),
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if ($this->timetableDay->remove($this->request->getIntegerParam('slot_id'))) {
|
||||||
|
$this->session->flash(t('Time slot removed successfully.'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flash(t('Unable to remove this time slot.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('timetableday', 'index', array('user_id' => $user['id'])));
|
||||||
|
}
|
||||||
|
}
|
16
sources/app/Controller/Timetableextra.php
Normal file
16
sources/app/Controller/Timetableextra.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Over-time Timetable controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Timetableextra extends Timetableoff
|
||||||
|
{
|
||||||
|
protected $model = 'timetableExtra';
|
||||||
|
protected $controller_url = 'timetableextra';
|
||||||
|
protected $template_dir = 'timetable_extra';
|
||||||
|
}
|
107
sources/app/Controller/Timetableoff.php
Normal file
107
sources/app/Controller/Timetableoff.php
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time-off Timetable controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Timetableoff extends User
|
||||||
|
{
|
||||||
|
protected $model = 'timetableOff';
|
||||||
|
protected $controller_url = 'timetableoff';
|
||||||
|
protected $template_dir = 'timetable_off';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display timetable for the user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$paginator = $this->paginator
|
||||||
|
->setUrl($this->controller_url, 'index', array('user_id' => $user['id']))
|
||||||
|
->setMax(10)
|
||||||
|
->setOrder('date')
|
||||||
|
->setDirection('desc')
|
||||||
|
->setQuery($this->{$this->model}->getUserQuery($user['id']))
|
||||||
|
->calculate();
|
||||||
|
|
||||||
|
$this->response->html($this->layout($this->template_dir.'/index', array(
|
||||||
|
'values' => $values + array('user_id' => $user['id']),
|
||||||
|
'errors' => $errors,
|
||||||
|
'paginator' => $paginator,
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and save
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->{$this->model}->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
|
||||||
|
if ($this->{$this->model}->create(
|
||||||
|
$values['user_id'],
|
||||||
|
$values['date'],
|
||||||
|
isset($values['all_day']) && $values['all_day'] == 1,
|
||||||
|
$values['start'],
|
||||||
|
$values['end'],
|
||||||
|
$values['comment'])) {
|
||||||
|
|
||||||
|
$this->session->flash(t('Time slot created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url($this->controller_url, 'index', array('user_id' => $values['user_id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to save this time slot.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirmation dialag box to remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout($this->template_dir.'/remove', array(
|
||||||
|
'slot_id' => $this->request->getIntegerParam('slot_id'),
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if ($this->{$this->model}->remove($this->request->getIntegerParam('slot_id'))) {
|
||||||
|
$this->session->flash(t('Time slot removed successfully.'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flash(t('Unable to remove this time slot.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url($this->controller_url, 'index', array('user_id' => $user['id'])));
|
||||||
|
}
|
||||||
|
}
|
99
sources/app/Controller/Timetableweek.php
Normal file
99
sources/app/Controller/Timetableweek.php
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Week Timetable controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Timetableweek extends User
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display timetable for the user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
|
||||||
|
$day = $this->timetableDay->getByUser($user['id']);
|
||||||
|
|
||||||
|
$values = array(
|
||||||
|
'user_id' => $user['id'],
|
||||||
|
'start' => isset($day[0]['start']) ? $day[0]['start'] : null,
|
||||||
|
'end' => isset($day[0]['end']) ? $day[0]['end'] : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->html($this->layout('timetable_week/index', array(
|
||||||
|
'timetable' => $this->timetableWeek->getByUser($user['id']),
|
||||||
|
'values' => $values,
|
||||||
|
'errors' => $errors,
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and save
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->timetableWeek->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
|
||||||
|
if ($this->timetableWeek->create($values['user_id'], $values['day'], $values['start'], $values['end'])) {
|
||||||
|
$this->session->flash(t('Time slot created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url('timetableweek', 'index', array('user_id' => $values['user_id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to save this time slot.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirmation dialag box to remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout('timetable_week/remove', array(
|
||||||
|
'slot_id' => $this->request->getIntegerParam('slot_id'),
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a row
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if ($this->timetableWeek->remove($this->request->getIntegerParam('slot_id'))) {
|
||||||
|
$this->session->flash(t('Time slot removed successfully.'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flash(t('Unable to remove this time slot.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('timetableweek', 'index', array('user_id' => $user['id'])));
|
||||||
|
}
|
||||||
|
}
|
140
sources/app/Controller/Twofactor.php
Normal file
140
sources/app/Controller/Twofactor.php
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
use Otp\Otp;
|
||||||
|
use Otp\GoogleAuthenticator;
|
||||||
|
use Base32\Base32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Two Factor Auth controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Twofactor extends User
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Only the current user can access to 2FA settings
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
private function checkCurrentUser(array $user)
|
||||||
|
{
|
||||||
|
if ($user['id'] != $this->userSession->getId()) {
|
||||||
|
$this->forbidden();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$this->checkCurrentUser($user);
|
||||||
|
|
||||||
|
$label = $user['email'] ?: $user['username'];
|
||||||
|
|
||||||
|
$this->response->html($this->layout('twofactor/index', array(
|
||||||
|
'user' => $user,
|
||||||
|
'qrcode_url' => $user['twofactor_activated'] == 1 ? GoogleAuthenticator::getQrCodeUrl('totp', $label, $user['twofactor_secret']) : '',
|
||||||
|
'key_url' => $user['twofactor_activated'] == 1 ? GoogleAuthenticator::getKeyUri('totp', $label, $user['twofactor_secret']) : '',
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable/disable 2FA
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$this->checkCurrentUser($user);
|
||||||
|
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if (isset($values['twofactor_activated']) && $values['twofactor_activated'] == 1) {
|
||||||
|
$this->user->update(array(
|
||||||
|
'id' => $user['id'],
|
||||||
|
'twofactor_activated' => 1,
|
||||||
|
'twofactor_secret' => GoogleAuthenticator::generateRandom(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->user->update(array(
|
||||||
|
'id' => $user['id'],
|
||||||
|
'twofactor_activated' => 0,
|
||||||
|
'twofactor_secret' => '',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow the user to test or disable the feature
|
||||||
|
$_SESSION['user']['twofactor_activated'] = false;
|
||||||
|
|
||||||
|
$this->session->flash(t('User updated successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url('twofactor', 'index', array('user_id' => $user['id'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test 2FA
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function test()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$this->checkCurrentUser($user);
|
||||||
|
|
||||||
|
$otp = new Otp;
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
|
||||||
|
$this->session->flash(t('The two factor authentication code is valid.'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('The two factor authentication code is not valid.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url('twofactor', 'index', array('user_id' => $user['id'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check 2FA
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function check()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
$this->checkCurrentUser($user);
|
||||||
|
|
||||||
|
$otp = new Otp;
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
|
||||||
|
$this->session['2fa_validated'] = true;
|
||||||
|
$this->session->flash(t('The two factor authentication code is valid.'));
|
||||||
|
$this->response->redirect($this->helper->url('app', 'index'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('The two factor authentication code is not valid.'));
|
||||||
|
$this->response->redirect($this->helper->url('twofactor', 'code'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the 2FA code
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function code()
|
||||||
|
{
|
||||||
|
$this->response->html($this->template->layout('twofactor/check', array(
|
||||||
|
'title' => t('Check two factor authentication code'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,12 +69,12 @@ class User extends Base
|
||||||
/**
|
/**
|
||||||
* Common layout for user views
|
* Common layout for user views
|
||||||
*
|
*
|
||||||
* @access private
|
* @access protected
|
||||||
* @param string $template Template name
|
* @param string $template Template name
|
||||||
* @param array $params Template parameters
|
* @param array $params Template parameters
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function layout($template, array $params)
|
protected function layout($template, array $params)
|
||||||
{
|
{
|
||||||
$content = $this->template->render($template, $params);
|
$content = $this->template->render($template, $params);
|
||||||
$params['user_content_for_layout'] = $content;
|
$params['user_content_for_layout'] = $content;
|
||||||
|
@ -90,14 +90,14 @@ class User extends Base
|
||||||
/**
|
/**
|
||||||
* Common method to get the user
|
* Common method to get the user
|
||||||
*
|
*
|
||||||
* @access private
|
* @access protected
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function getUser()
|
protected function getUser()
|
||||||
{
|
{
|
||||||
$user = $this->user->getById($this->request->getIntegerParam('user_id'));
|
$user = $this->user->getById($this->request->getIntegerParam('user_id'));
|
||||||
|
|
||||||
if (! $user) {
|
if (empty($user)) {
|
||||||
$this->notfound();
|
$this->notfound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -502,7 +502,7 @@ class Helper
|
||||||
public function markdown($text, array $link = array())
|
public function markdown($text, array $link = array())
|
||||||
{
|
{
|
||||||
$parser = new Markdown($link, $this);
|
$parser = new Markdown($link, $this);
|
||||||
$parser->setMarkupEscaped(true);
|
$parser->setMarkupEscaped(MARKDOWN_ESCAPE_HTML);
|
||||||
return $parser->text($text);
|
return $parser->text($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,4 +677,114 @@ class Helper
|
||||||
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect)
|
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all hours for day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDayHours()
|
||||||
|
{
|
||||||
|
$values = array();
|
||||||
|
|
||||||
|
foreach (range(0, 23) as $hour) {
|
||||||
|
foreach (array(0, 30) as $minute) {
|
||||||
|
$time = sprintf('%02d:%02d', $hour, $minute);
|
||||||
|
$values[$time] = $time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all days of a week
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getWeekDays()
|
||||||
|
{
|
||||||
|
$values = array();
|
||||||
|
|
||||||
|
foreach (range(1, 7) as $day) {
|
||||||
|
$values[$day] = $this->getWeekDay($day);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the localized day name from the day number
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $day Day number
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getWeekDay($day)
|
||||||
|
{
|
||||||
|
return dt('%A', strtotime('next Monday +'.($day - 1).' days'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file icon
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $filename Filename
|
||||||
|
* @return string Font-Awesome-Icon-Name
|
||||||
|
*/
|
||||||
|
public function getFileIcon($filename){
|
||||||
|
|
||||||
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
switch ($extension) {
|
||||||
|
case 'jpeg':
|
||||||
|
case 'jpg':
|
||||||
|
case 'png':
|
||||||
|
case 'gif':
|
||||||
|
return 'fa-file-image-o';
|
||||||
|
case 'xls':
|
||||||
|
case 'xlsx':
|
||||||
|
return 'fa-file-excel-o';
|
||||||
|
case 'doc':
|
||||||
|
case 'docx':
|
||||||
|
return 'fa-file-word-o';
|
||||||
|
case 'ppt':
|
||||||
|
case 'pptx':
|
||||||
|
return 'fa-file-powerpoint-o';
|
||||||
|
case 'zip':
|
||||||
|
case 'rar':
|
||||||
|
return 'fa-archive-o';
|
||||||
|
case 'mp3':
|
||||||
|
return 'fa-audio-o';
|
||||||
|
case 'avi':
|
||||||
|
return 'fa-video-o';
|
||||||
|
case 'php':
|
||||||
|
case 'html':
|
||||||
|
case 'css':
|
||||||
|
return 'fa-code-o';
|
||||||
|
case 'pdf':
|
||||||
|
return 'fa-file-pdf-o';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'fa-file-o';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display gravatar image
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $email
|
||||||
|
* @param string $alt
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function avatar($email, $alt = '')
|
||||||
|
{
|
||||||
|
if (! empty($email) && $this->config->get('integration_gravatar') == 1) {
|
||||||
|
return '<img class="avatar" src="https://www.gravatar.com/avatar/'.md5(strtolower($email)).'?s=25" alt="'.$this->e($alt).'" title="'.$this->e($alt).'">';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
68
sources/app/Core/HttpClient.php
Normal file
68
sources/app/Core/HttpClient.php
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP client
|
||||||
|
*
|
||||||
|
* @package core
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class HttpClient
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* HTTP connection timeout in seconds
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const HTTP_TIMEOUT = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of maximum redirections for the HTTP client
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const HTTP_MAX_REDIRECTS = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP client user agent
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const HTTP_USER_AGENT = 'Kanboard Webhook';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a POST HTTP request
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $url
|
||||||
|
* @param array $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function post($url, array $data)
|
||||||
|
{
|
||||||
|
if (empty($url)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = array(
|
||||||
|
'User-Agent: '.self::HTTP_USER_AGENT,
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'Connection: close',
|
||||||
|
);
|
||||||
|
|
||||||
|
$context = stream_context_create(array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'protocol_version' => 1.1,
|
||||||
|
'timeout' => self::HTTP_TIMEOUT,
|
||||||
|
'max_redirects' => self::HTTP_MAX_REDIRECTS,
|
||||||
|
'header' => implode("\r\n", $headers),
|
||||||
|
'content' => json_encode($data)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
return @file_get_contents(trim($url), false, $context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ use Pimple\Container;
|
||||||
* @package integration
|
* @package integration
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*
|
*
|
||||||
|
* @property \Model\ProjectActivity $projectActivity
|
||||||
* @property \Model\Task $task
|
* @property \Model\Task $task
|
||||||
* @property \Model\TaskFinder $taskFinder
|
* @property \Model\TaskFinder $taskFinder
|
||||||
* @property \Model\User $user
|
* @property \Model\User $user
|
||||||
|
|
|
@ -78,7 +78,7 @@ class BitbucketWebhook extends Base
|
||||||
|
|
||||||
$task = $this->taskFinder->getById($task_id);
|
$task = $this->taskFinder->getById($task_id);
|
||||||
|
|
||||||
if (! $task) {
|
if (empty($task)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ class GithubWebhook extends Base
|
||||||
|
|
||||||
$task = $this->taskFinder->getById($task_id);
|
$task = $this->taskFinder->getById($task_id);
|
||||||
|
|
||||||
if (! $task) {
|
if (empty($task)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ class GithubWebhook extends Base
|
||||||
$task = $this->taskFinder->getByReference($payload['issue']['number']);
|
$task = $this->taskFinder->getByReference($payload['issue']['number']);
|
||||||
$user = $this->user->getByUsername($payload['comment']['user']['login']);
|
$user = $this->user->getByUsername($payload['comment']['user']['login']);
|
||||||
|
|
||||||
if ($task && $user) {
|
if (! empty($task) && ! empty($user)) {
|
||||||
|
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
|
@ -198,7 +198,7 @@ class GithubWebhook extends Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getByReference($issue['number']);
|
$task = $this->taskFinder->getByReference($issue['number']);
|
||||||
|
|
||||||
if ($task) {
|
if (! empty($task)) {
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
'task_id' => $task['id'],
|
'task_id' => $task['id'],
|
||||||
|
@ -227,7 +227,7 @@ class GithubWebhook extends Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getByReference($issue['number']);
|
$task = $this->taskFinder->getByReference($issue['number']);
|
||||||
|
|
||||||
if ($task) {
|
if (! empty($task)) {
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
'task_id' => $task['id'],
|
'task_id' => $task['id'],
|
||||||
|
@ -257,7 +257,7 @@ class GithubWebhook extends Base
|
||||||
$user = $this->user->getByUsername($issue['assignee']['login']);
|
$user = $this->user->getByUsername($issue['assignee']['login']);
|
||||||
$task = $this->taskFinder->getByReference($issue['number']);
|
$task = $this->taskFinder->getByReference($issue['number']);
|
||||||
|
|
||||||
if ($user && $task) {
|
if (! empty($user) && ! empty($task)) {
|
||||||
|
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
|
@ -288,7 +288,7 @@ class GithubWebhook extends Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getByReference($issue['number']);
|
$task = $this->taskFinder->getByReference($issue['number']);
|
||||||
|
|
||||||
if ($task) {
|
if (! empty($task)) {
|
||||||
|
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
|
@ -320,7 +320,7 @@ class GithubWebhook extends Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getByReference($issue['number']);
|
$task = $this->taskFinder->getByReference($issue['number']);
|
||||||
|
|
||||||
if ($task) {
|
if (! empty($task)) {
|
||||||
|
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
|
@ -352,7 +352,7 @@ class GithubWebhook extends Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getByReference($issue['number']);
|
$task = $this->taskFinder->getByReference($issue['number']);
|
||||||
|
|
||||||
if ($task) {
|
if (! empty($task)) {
|
||||||
|
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
|
|
|
@ -122,7 +122,7 @@ class GitlabWebhook extends Base
|
||||||
|
|
||||||
$task = $this->taskFinder->getById($task_id);
|
$task = $this->taskFinder->getById($task_id);
|
||||||
|
|
||||||
if (! $task) {
|
if (empty($task)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ class GitlabWebhook extends Base
|
||||||
{
|
{
|
||||||
$task = $this->taskFinder->getByReference($issue['id']);
|
$task = $this->taskFinder->getByReference($issue['id']);
|
||||||
|
|
||||||
if ($task) {
|
if (! empty($task)) {
|
||||||
$event = array(
|
$event = array(
|
||||||
'project_id' => $this->project_id,
|
'project_id' => $this->project_id,
|
||||||
'task_id' => $task['id'],
|
'task_id' => $task['id'],
|
||||||
|
|
53
sources/app/Integration/Hipchat.php
Normal file
53
sources/app/Integration/Hipchat.php
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Integration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hipchat Webhook
|
||||||
|
*
|
||||||
|
* @package integration
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Hipchat extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send message to the Hipchat room
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id Project id
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @param string $event_name Event name
|
||||||
|
* @param array $event Event data
|
||||||
|
*/
|
||||||
|
public function notify($project_id, $task_id, $event_name, array $event)
|
||||||
|
{
|
||||||
|
$project = $this->project->getbyId($project_id);
|
||||||
|
|
||||||
|
$event['event_name'] = $event_name;
|
||||||
|
$event['author'] = $this->user->getFullname($this->session['user']);
|
||||||
|
|
||||||
|
$html = '<img src="http://kanboard.net/assets/img/favicon-32x32.png"/>';
|
||||||
|
$html .= '<strong>'.$project['name'].'</strong><br/>';
|
||||||
|
$html .= $this->projectActivity->getTitle($event);
|
||||||
|
|
||||||
|
if ($this->config->get('application_url')) {
|
||||||
|
$html .= '<br/><a href="'.$this->config->get('application_url');
|
||||||
|
$html .= $this->helper->u('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id)).'">';
|
||||||
|
$html .= t('view the task on Kanboard').'</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = array(
|
||||||
|
'message' => $html,
|
||||||
|
'color' => 'yellow',
|
||||||
|
);
|
||||||
|
|
||||||
|
$url = sprintf(
|
||||||
|
'%s/v2/room/%s/notification?auth_token=%s',
|
||||||
|
$this->config->get('integration_hipchat_api_url'),
|
||||||
|
$this->config->get('integration_hipchat_room_id'),
|
||||||
|
$this->config->get('integration_hipchat_room_token')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->httpClient->post($url, $payload);
|
||||||
|
}
|
||||||
|
}
|
43
sources/app/Integration/SlackWebhook.php
Normal file
43
sources/app/Integration/SlackWebhook.php
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Integration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slack Webhook
|
||||||
|
*
|
||||||
|
* @package integration
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class SlackWebhook extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send message to the incoming Slack webhook
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id Project id
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @param string $event_name Event name
|
||||||
|
* @param array $event Event data
|
||||||
|
*/
|
||||||
|
public function notify($project_id, $task_id, $event_name, array $event)
|
||||||
|
{
|
||||||
|
$project = $this->project->getbyId($project_id);
|
||||||
|
|
||||||
|
$event['event_name'] = $event_name;
|
||||||
|
$event['author'] = $this->user->getFullname($this->session['user']);
|
||||||
|
|
||||||
|
$payload = array(
|
||||||
|
'text' => '*['.$project['name'].']* '.str_replace('"', '"', $this->projectActivity->getTitle($event)),
|
||||||
|
'username' => 'Kanboard',
|
||||||
|
'icon_url' => 'http://kanboard.net/assets/img/favicon.png',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->config->get('application_url')) {
|
||||||
|
$payload['text'] .= ' - <'.$this->config->get('application_url');
|
||||||
|
$payload['text'] .= $this->helper->u('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id));
|
||||||
|
$payload['text'] .= '|'.t('view the task on Kanboard').'>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->httpClient->post($this->config->get('integration_slack_webhook_url'), $payload);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Ingen',
|
'None' => 'Ingen',
|
||||||
'edit' => 'rediger',
|
'edit' => 'rediger',
|
||||||
'Edit' => 'Rediger',
|
'Edit' => 'Rediger',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'number.decimals_separator' => ',',
|
||||||
|
'number.thousands_separator' => '.',
|
||||||
'None' => 'Keines',
|
'None' => 'Keines',
|
||||||
'edit' => 'Bearbeiten',
|
'edit' => 'Bearbeiten',
|
||||||
'Edit' => 'Bearbeiten',
|
'Edit' => 'Bearbeiten',
|
||||||
|
@ -408,13 +410,13 @@ return array(
|
||||||
'Comment updated' => 'Kommentar wurde aktualisiert',
|
'Comment updated' => 'Kommentar wurde aktualisiert',
|
||||||
'New comment posted by %s' => 'Neuer Kommentar verfasst durch %s',
|
'New comment posted by %s' => 'Neuer Kommentar verfasst durch %s',
|
||||||
'List of due tasks for the project "%s"' => 'Liste der fälligen Aufgaben für das Projekt "%s"',
|
'List of due tasks for the project "%s"' => 'Liste der fälligen Aufgaben für das Projekt "%s"',
|
||||||
// 'New attachment' => '',
|
'New attachment' => 'Neuer Anhang',
|
||||||
// 'New comment' => '',
|
'New comment' => 'Neuer Kommentar',
|
||||||
// 'New subtask' => '',
|
'New subtask' => 'Neue Teilaufgabe',
|
||||||
// 'Subtask updated' => '',
|
'Subtask updated' => 'Teilaufgabe aktualisiert',
|
||||||
// 'Task updated' => '',
|
'Task updated' => 'Aufgabe aktualisiert',
|
||||||
// 'Task closed' => '',
|
'Task closed' => 'Aufgabe geschlossen',
|
||||||
// 'Task opened' => '',
|
'Task opened' => 'Aufgabe geöffnet',
|
||||||
'[%s][Due tasks]' => '[%s][Fällige Aufgaben]',
|
'[%s][Due tasks]' => '[%s][Fällige Aufgaben]',
|
||||||
'[Kanboard] Notification' => '[Kanboard] Benachrichtigung',
|
'[Kanboard] Notification' => '[Kanboard] Benachrichtigung',
|
||||||
'I want to receive notifications only for those projects:' => 'Ich möchte nur für diese Projekte Benachrichtigungen erhalten:',
|
'I want to receive notifications only for those projects:' => 'Ich möchte nur für diese Projekte Benachrichtigungen erhalten:',
|
||||||
|
@ -498,9 +500,9 @@ return array(
|
||||||
'Task assignee change' => 'Zuständigkeit geändert',
|
'Task assignee change' => 'Zuständigkeit geändert',
|
||||||
'%s change the assignee of the task #%d to %s' => '%s hat die Zusständigkeit der Aufgabe #%d geändert um %s',
|
'%s change the assignee of the task #%d to %s' => '%s hat die Zusständigkeit der Aufgabe #%d geändert um %s',
|
||||||
'%s changed the assignee of the task %s to %s' => '%s hat die Zuständigkeit der Aufgabe %s geändert um %s',
|
'%s changed the assignee of the task %s to %s' => '%s hat die Zuständigkeit der Aufgabe %s geändert um %s',
|
||||||
// 'Column Change' => '',
|
'Column Change' => 'Spalte ändern',
|
||||||
// 'Position Change' => '',
|
'Position Change' => 'Position ändern',
|
||||||
// 'Assignee Change' => '',
|
'Assignee Change' => 'Zuordnung ändern',
|
||||||
'New password for the user "%s"' => 'Neues Passwort des Benutzers "%s"',
|
'New password for the user "%s"' => 'Neues Passwort des Benutzers "%s"',
|
||||||
'Choose an event' => 'Aktion wählen',
|
'Choose an event' => 'Aktion wählen',
|
||||||
'Github commit received' => 'Github commit empfangen',
|
'Github commit received' => 'Github commit empfangen',
|
||||||
|
@ -625,8 +627,8 @@ return array(
|
||||||
'Example: "Bug, Feature Request, Improvement"' => 'Beispiel: "Bug, Funktionswünsche, Verbesserung"',
|
'Example: "Bug, Feature Request, Improvement"' => 'Beispiel: "Bug, Funktionswünsche, Verbesserung"',
|
||||||
'Default categories for new projects (Comma-separated)' => 'Standard Kategorien für neue Projekte (Komma-getrennt)',
|
'Default categories for new projects (Comma-separated)' => 'Standard Kategorien für neue Projekte (Komma-getrennt)',
|
||||||
'Gitlab commit received' => 'Gitlab commit erhalten',
|
'Gitlab commit received' => 'Gitlab commit erhalten',
|
||||||
'Gitlab issue opened' => 'Gitlab Thema eröffnet',
|
'Gitlab issue opened' => 'Gitlab Fehler eröffnet',
|
||||||
'Gitlab issue closed' => 'Gitlab Thema geschlossen',
|
'Gitlab issue closed' => 'Gitlab Fehler geschlossen',
|
||||||
'Gitlab webhooks' => 'Gitlab Webhook',
|
'Gitlab webhooks' => 'Gitlab Webhook',
|
||||||
'Help on Gitlab webhooks' => 'Hilfe für Gitlab Webhooks',
|
'Help on Gitlab webhooks' => 'Hilfe für Gitlab Webhooks',
|
||||||
'Integrations' => 'Integration',
|
'Integrations' => 'Integration',
|
||||||
|
@ -635,7 +637,7 @@ return array(
|
||||||
'Project manager' => 'Projektmanager',
|
'Project manager' => 'Projektmanager',
|
||||||
'Project member' => 'Projektmitglied',
|
'Project member' => 'Projektmitglied',
|
||||||
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Ein Projektmanager kann die Projekteinstellungen ändern und hat mehr Rechte als ein normaler Benutzer.',
|
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Ein Projektmanager kann die Projekteinstellungen ändern und hat mehr Rechte als ein normaler Benutzer.',
|
||||||
'Gitlab Issue' => 'Gitlab Thema',
|
'Gitlab Issue' => 'Gitlab Fehler',
|
||||||
'Subtask Id' => 'Teilaufgaben Id',
|
'Subtask Id' => 'Teilaufgaben Id',
|
||||||
'Subtasks' => 'Teilaufgaben',
|
'Subtasks' => 'Teilaufgaben',
|
||||||
'Subtasks Export' => 'Teilaufgaben Export',
|
'Subtasks Export' => 'Teilaufgaben Export',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
'Filter recently updated' => 'Zuletzt geänderte anzeigen',
|
'Filter recently updated' => 'Zuletzt geänderte anzeigen',
|
||||||
'since %B %e, %Y at %k:%M %p' => 'seit %B %e, %Y um %k:%M %p',
|
'since %B %e, %Y at %k:%M %p' => 'seit %B %e, %Y um %k:%M %p',
|
||||||
'More filters' => 'Mehr Filter',
|
'More filters' => 'Mehr Filter',
|
||||||
|
'Compact view' => 'Kompaktansicht',
|
||||||
|
'Horizontal scrolling' => 'Horizontales Scrollen',
|
||||||
|
'Compact/wide view' => 'Kompakt/Breite-Ansicht',
|
||||||
|
'No results match:' => 'Keine Ergebnisse:',
|
||||||
|
'Remove hourly rate' => 'Stundensatz entfernen',
|
||||||
|
'Do you really want to remove this hourly rate?' => 'Diesen Stundensatz wirklich entfernen?',
|
||||||
|
'Hourly rates' => 'Stundensätze',
|
||||||
|
'Hourly rate' => 'Stundensatz',
|
||||||
|
'Currency' => 'Währung',
|
||||||
|
'Effective date' => 'Inkraftsetzung',
|
||||||
|
'Add new rate' => 'Neue Rate hinzufügen',
|
||||||
|
'Rate removed successfully.' => 'Rate erfolgreich entfernt',
|
||||||
|
'Unable to remove this rate.' => 'Nicht in der Lage, diese Rate zu entfernen.',
|
||||||
|
'Unable to save the hourly rate.' => 'Nicht in der Lage, diese Rate zu speichern',
|
||||||
|
'Hourly rate created successfully.' => 'Stundensatz erfolgreich angelegt.',
|
||||||
|
'Start time' => 'Startzeit',
|
||||||
|
'End time' => 'Endzeit',
|
||||||
|
'Comment' => 'Kommentar',
|
||||||
|
'All day' => 'ganztägig',
|
||||||
|
'Day' => 'Tag',
|
||||||
|
'Manage timetable' => 'Zeitplan verwalten',
|
||||||
|
'Overtime timetable' => 'Überstunden Zeitplan',
|
||||||
|
'Time off timetable' => 'Freizeit Zeitplan',
|
||||||
|
'Timetable' => 'Zeitplan',
|
||||||
|
'Work timetable' => 'Arbeitszeitplan',
|
||||||
|
'Week timetable' => 'Wochenzeitplan',
|
||||||
|
'Day timetable' => 'Tageszeitplan',
|
||||||
|
'From' => 'von',
|
||||||
|
'To' => 'bis',
|
||||||
|
'Time slot created successfully.' => 'Zeitfenster erfolgreich erstellt.',
|
||||||
|
'Unable to save this time slot.' => 'Nicht in der Lage, dieses Zeitfenster zu speichern.',
|
||||||
|
'Time slot removed successfully.' => 'Zeitfenster erfolgreich entfernt.',
|
||||||
|
'Unable to remove this time slot.' => 'Nicht in der Lage, dieses Zeitfenster zu entfernen',
|
||||||
|
'Do you really want to remove this time slot?' => 'Soll diese Zeitfenster wirklich gelöscht werden?',
|
||||||
|
'Remove time slot' => 'Zeitfenster entfernen',
|
||||||
|
'Add new time slot' => 'Neues Zeitfenster hinzufügen',
|
||||||
|
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Dieses Zeitfenster wird verwendet, wenn die Checkbox "gantägig" für Freizeit und Überstunden angeklickt ist.',
|
||||||
|
'Files' => 'Dateien',
|
||||||
|
'Images' => 'Bilder',
|
||||||
|
'Private project' => 'privates Projekt',
|
||||||
|
'Amount' => 'Betrag',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
'Budget' => 'Budget',
|
||||||
|
'Budget line' => 'Budgetlinie',
|
||||||
|
'Budget line removed successfully.' => 'Budgetlinie erfolgreich entfernt',
|
||||||
|
'Budget lines' => 'Budgetlinien',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
'Cost' => 'Kosten',
|
||||||
|
'Cost breakdown' => 'Kostenaufschlüsselung',
|
||||||
|
'Custom Stylesheet' => 'benutzerdefiniertes Stylesheet',
|
||||||
|
'download' => 'Download',
|
||||||
|
'Do you really want to remove this budget line?' => 'Soll diese Budgetlinie wirklich entfernt werden?',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
'Expenses' => 'Kosten',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
'New budget line' => 'Neue Budgetlinie',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
'Remove a budget line' => 'Budgetlinie entfernen',
|
||||||
|
'Remove budget line' => 'Budgetlinie entfernen',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
'The budget line have been created successfully.' => 'Die Budgetlinie wurde erfolgreich angelegt.',
|
||||||
|
'Unable to create the budget line.' => 'Budgetlinie konnte nicht erstellt werden.',
|
||||||
|
'Unable to remove this budget line.' => 'Budgetlinie konnte nicht gelöscht werden.',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
'Remaining' => 'Verbleibend',
|
||||||
|
'Destination column' => 'Zielspalte',
|
||||||
|
'Move the task to another column when assigned to a user' => 'Aufgabe in eine andere Spalte verschieben, wenn ein User zugeordnet wurde.',
|
||||||
|
'Move the task to another column when assignee is cleared' => 'Aufgabe in eine andere Spalte verschieben, wenn die Zuordnung gelöscht wurde.',
|
||||||
|
'Source column' => 'Quellspalte',
|
||||||
|
'Show subtask estimates in the user calendar' => 'Teilaufgabenschätzung in Benutzerkalender anzeigen.',
|
||||||
|
'Transitions' => 'Übergänge',
|
||||||
|
'Executer' => 'Ausführender',
|
||||||
|
'Time spent in the column' => 'Zeit in Spalte verbracht',
|
||||||
|
'Task transitions' => 'Aufgaben Übergänge',
|
||||||
|
'Task transitions export' => 'Aufgaben Übergänge exportieren',
|
||||||
|
'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => 'Diese Auswertung enthält alle Spaltenbewegungen für jede Aufgabe mit Datum, Benutzer und Zeit vor jedem Wechsel.',
|
||||||
|
'Currency rates' => 'Währungskurse',
|
||||||
|
'Rate' => 'Kurse',
|
||||||
|
'Change reference currency' => 'Referenzwährung ändern',
|
||||||
|
'Add a new currency rate' => 'Neuen Währungskurs hinzufügen',
|
||||||
|
'Currency rates are used to calculate project budget.' => 'Währungskurse werden verwendet um das Projektbudget zu berechnen.',
|
||||||
|
'Reference currency' => 'Referenzwährung',
|
||||||
|
'The currency rate have been added successfully.' => 'Der Währungskurs wurde erfolgreich hinzugefügt.',
|
||||||
|
'Unable to add this currency rate.' => 'Währungskurs konnte nicht hinzugefügt werden',
|
||||||
|
'Send notifications to a Slack channel' => 'Benachrichtigung an einen Slack-Kanal senden',
|
||||||
|
'Webhook URL' => 'Webhook URL',
|
||||||
|
'Help on Slack integration' => 'Hilfe für Slack integration.',
|
||||||
|
'%s remove the assignee of the task %s' => '%s Zuordnung für die Aufgabe %s entfernen',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Ninguno',
|
'None' => 'Ninguno',
|
||||||
'edit' => 'modificar',
|
'edit' => 'modificar',
|
||||||
'Edit' => 'Modificar',
|
'Edit' => 'Modificar',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Ei mikään',
|
'None' => 'Ei mikään',
|
||||||
'edit' => 'muokkaa',
|
'edit' => 'muokkaa',
|
||||||
'Edit' => 'Muokkaa',
|
'Edit' => 'Muokkaa',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'number.decimals_separator' => ',',
|
||||||
|
'number.thousands_separator' => ' ',
|
||||||
'None' => 'Aucun',
|
'None' => 'Aucun',
|
||||||
'edit' => 'modifier',
|
'edit' => 'modifier',
|
||||||
'Edit' => 'Modifier',
|
'Edit' => 'Modifier',
|
||||||
|
@ -736,4 +738,114 @@ return array(
|
||||||
'Filter recently updated' => 'Récemment modifié',
|
'Filter recently updated' => 'Récemment modifié',
|
||||||
'since %B %e, %Y at %k:%M %p' => 'depuis le %d/%m/%Y à %H:%M',
|
'since %B %e, %Y at %k:%M %p' => 'depuis le %d/%m/%Y à %H:%M',
|
||||||
'More filters' => 'Plus de filtres',
|
'More filters' => 'Plus de filtres',
|
||||||
|
'Compact view' => 'Vue compacte',
|
||||||
|
'Horizontal scrolling' => 'Défilement horizontal',
|
||||||
|
'Compact/wide view' => 'Basculer entre la vue compacte et étendue',
|
||||||
|
'No results match:' => 'Aucun résultat :',
|
||||||
|
'Remove hourly rate' => 'Supprimer un taux horaire',
|
||||||
|
'Do you really want to remove this hourly rate?' => 'Voulez-vous vraiment supprimer ce taux horaire ?',
|
||||||
|
'Hourly rates' => 'Taux horaires',
|
||||||
|
'Hourly rate' => 'Taux horaire',
|
||||||
|
'Currency' => 'Devise',
|
||||||
|
'Effective date' => 'Date d\'effet',
|
||||||
|
'Add new rate' => 'Ajouter un nouveau taux horaire',
|
||||||
|
'Rate removed successfully.' => 'Taux horaire supprimé avec succès.',
|
||||||
|
'Unable to remove this rate.' => 'Impossible de supprimer ce taux horaire.',
|
||||||
|
'Unable to save the hourly rate.' => 'Impossible de sauvegarder ce taux horaire.',
|
||||||
|
'Hourly rate created successfully.' => 'Taux horaire créé avec succès.',
|
||||||
|
'Start time' => 'Date de début',
|
||||||
|
'End time' => 'Date de fin',
|
||||||
|
'Comment' => 'Commentaire',
|
||||||
|
'All day' => 'Toute la journée',
|
||||||
|
'Day' => 'Jour',
|
||||||
|
'Manage timetable' => 'Gérer les horaires',
|
||||||
|
'Overtime timetable' => 'Heures supplémentaires',
|
||||||
|
'Time off timetable' => 'Heures d\'absences',
|
||||||
|
'Timetable' => 'Horaires',
|
||||||
|
'Work timetable' => 'Horaires travaillés',
|
||||||
|
'Week timetable' => 'Horaires de la semaine',
|
||||||
|
'Day timetable' => 'Horaire d\'une journée',
|
||||||
|
'From' => 'Depuis',
|
||||||
|
'To' => 'À',
|
||||||
|
'Time slot created successfully.' => 'Créneau horaire créé avec succès.',
|
||||||
|
'Unable to save this time slot.' => 'Impossible de sauvegarder ce créneau horaire.',
|
||||||
|
'Time slot removed successfully.' => 'Créneau horaire supprimé avec succès.',
|
||||||
|
'Unable to remove this time slot.' => 'Impossible de supprimer ce créneau horaire.',
|
||||||
|
'Do you really want to remove this time slot?' => 'Voulez-vous vraiment supprimer ce créneau horaire ?',
|
||||||
|
'Remove time slot' => 'Supprimer un créneau horaire',
|
||||||
|
'Add new time slot' => 'Ajouter un créneau horaire',
|
||||||
|
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ces horaires sont utilisés lorsque la case « Toute la journée » est cochée pour les heures d\'absences ou supplémentaires programmées.',
|
||||||
|
'Files' => 'Fichiers',
|
||||||
|
'Images' => 'Images',
|
||||||
|
'Private project' => 'Projet privé',
|
||||||
|
'Amount' => 'Montant',
|
||||||
|
'AUD - Australian Dollar' => 'AUD - Dollar australien',
|
||||||
|
'Budget' => 'Budget',
|
||||||
|
'Budget line' => 'Ligne budgétaire',
|
||||||
|
'Budget line removed successfully.' => 'Ligne budgétaire supprimée avec succès.',
|
||||||
|
'Budget lines' => 'Lignes budgétaire',
|
||||||
|
'CAD - Canadian Dollar' => 'CAD - Dollar canadien',
|
||||||
|
'CHF - Swiss Francs' => 'CHF - Franc suisse',
|
||||||
|
'Cost' => 'Coût',
|
||||||
|
'Cost breakdown' => 'Détail des coûts',
|
||||||
|
'Custom Stylesheet' => 'Feuille de style personalisée',
|
||||||
|
'download' => 'télécharger',
|
||||||
|
'Do you really want to remove this budget line?' => 'Voulez-vous vraiment supprimer cette ligne budgétaire ?',
|
||||||
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
|
'Expenses' => 'Dépenses',
|
||||||
|
'GBP - British Pound' => 'GBP - Livre sterling',
|
||||||
|
'INR - Indian Rupee' => 'INR - Roupie indienne',
|
||||||
|
'JPY - Japanese Yen' => 'JPY - Yen',
|
||||||
|
'New budget line' => 'Nouvelle ligne budgétaire',
|
||||||
|
'NZD - New Zealand Dollar' => 'NZD - Dollar néo-zélandais',
|
||||||
|
'Remove a budget line' => 'Supprimer une ligne budgétaire',
|
||||||
|
'Remove budget line' => 'Supprimer une ligne budgétaire',
|
||||||
|
'RSD - Serbian dinar' => 'RSD - Dinar serbe',
|
||||||
|
'The budget line have been created successfully.' => 'La ligne de budgétaire a été créée avec succès.',
|
||||||
|
'Unable to create the budget line.' => 'Impossible de créer cette ligne budgétaire.',
|
||||||
|
'Unable to remove this budget line.' => 'Impossible de supprimer cette ligne budgétaire.',
|
||||||
|
'USD - US Dollar' => 'USD - Dollar américain',
|
||||||
|
'Remaining' => 'Restant',
|
||||||
|
'Destination column' => 'Colonne de destination',
|
||||||
|
'Move the task to another column when assigned to a user' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci est assignée à quelqu\'un',
|
||||||
|
'Move the task to another column when assignee is cleared' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci n\'est plus assignée',
|
||||||
|
'Source column' => 'Colonne d\'origine',
|
||||||
|
'Show subtask estimates in the user calendar' => 'Afficher le temps estimé des sous-tâches dans le calendrier utilisateur',
|
||||||
|
'Transitions' => 'Transitions',
|
||||||
|
'Executer' => 'Exécutant',
|
||||||
|
'Time spent in the column' => 'Temps passé dans la colonne',
|
||||||
|
'Task transitions' => 'Transitions des tâches',
|
||||||
|
'Task transitions export' => 'Export des transitions des tâches',
|
||||||
|
'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => 'Ce rapport contient tous les mouvements de colonne pour chaque tâche avec la date, l\'utilisateur et le temps passé pour chaque transition.',
|
||||||
|
'Currency rates' => 'Taux de change des devises',
|
||||||
|
'Rate' => 'Taux',
|
||||||
|
'Change reference currency' => 'Changer la monnaie de référence',
|
||||||
|
'Add a new currency rate' => 'Ajouter un nouveau taux pour une devise',
|
||||||
|
'Currency rates are used to calculate project budget.' => 'Le cours des devises est utilisé pour calculer le budget des projets.',
|
||||||
|
'Reference currency' => 'Devise de référence',
|
||||||
|
'The currency rate have been added successfully.' => 'Le taux de change a été ajouté avec succès.',
|
||||||
|
'Unable to add this currency rate.' => 'Impossible d\'ajouter ce taux de change',
|
||||||
|
'Send notifications to a Slack channel' => 'Envoyer les notifications sur un salon de discussion Slack',
|
||||||
|
'Webhook URL' => 'URL du webhook',
|
||||||
|
'Help on Slack integration' => 'Aide sur l\'intégration avec Slack',
|
||||||
|
'%s remove the assignee of the task %s' => '%s a enlevé la personne assignée à la tâche %s',
|
||||||
|
'Send notifications to Hipchat' => 'Envoyer les notifications vers Hipchat',
|
||||||
|
'API URL' => 'URL de l\'api',
|
||||||
|
'Room API ID or name' => 'Nom ou identifiant du salon de discussion',
|
||||||
|
'Room notification token' => 'Jeton de sécurité du salon de discussion',
|
||||||
|
'Help on Hipchat integration' => 'Aide sur l\'intégration avec Hipchat',
|
||||||
|
'Enable Gravatar images' => 'Activer les images Gravatar',
|
||||||
|
'Information' => 'Informations',
|
||||||
|
'Check two factor authentication code' => 'Vérification du code pour l\'authentification à deux-facteurs',
|
||||||
|
'The two factor authentication code is not valid.' => 'Le code pour l\'authentification à deux-facteurs n\'est pas valide.',
|
||||||
|
'The two factor authentication code is valid.' => 'Le code pour l\'authentification à deux-facteurs est valide.',
|
||||||
|
'Code' => 'Code',
|
||||||
|
'Two factor authentication' => 'Authentification à deux-facteurs',
|
||||||
|
'Enable/disable two factor authentication' => 'Activer/désactiver l\'authentification à deux-facteurs',
|
||||||
|
'This QR code contains the key URI: ' => 'Ce code QR contient l\'url de la clé : ',
|
||||||
|
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Sauvegardez cette clé secrete dans votre logiciel TOTP (par exemple Google Authenticator ou FreeOTP).',
|
||||||
|
'Check my code' => 'Vérifier mon code',
|
||||||
|
'Secret key: ' => 'Clé secrète : ',
|
||||||
|
'Test your device' => 'Testez votre appareil',
|
||||||
|
'Assign a color when the task is moved to a specific column' => 'Assigner une couleur lorsque la tâche est déplacée dans une colonne spécifique',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'number.decimals_separator' => ',',
|
||||||
|
'number.thousands_separator' => ' ',
|
||||||
'None' => 'Nincs',
|
'None' => 'Nincs',
|
||||||
'edit' => 'szerkesztés',
|
'edit' => 'szerkesztés',
|
||||||
'Edit' => 'Szerkesztés',
|
'Edit' => 'Szerkesztés',
|
||||||
'remove' => 'eltávolítás',
|
'remove' => 'törlés',
|
||||||
'Remove' => 'Eltávolítás',
|
'Remove' => 'Törlés',
|
||||||
'Update' => 'Frissítés',
|
'Update' => 'Frissítés',
|
||||||
'Yes' => 'Igen',
|
'Yes' => 'Igen',
|
||||||
'No' => 'Nem',
|
'No' => 'Nem',
|
||||||
|
@ -104,7 +106,7 @@ return array(
|
||||||
'Open a task' => 'Feladat felnyitás',
|
'Open a task' => 'Feladat felnyitás',
|
||||||
'Do you really want to open this task: "%s"?' => 'Tényleg meg akarja nyitni ezt a feladatot: "%s"?',
|
'Do you really want to open this task: "%s"?' => 'Tényleg meg akarja nyitni ezt a feladatot: "%s"?',
|
||||||
'Back to the board' => 'Vissza a táblához',
|
'Back to the board' => 'Vissza a táblához',
|
||||||
'Created on %B %e, %Y at %k:%M %p' => 'Létrehozva: %Y.%m.%d %H:%M',
|
'Created on %B %e, %Y at %k:%M %p' => 'Létrehozva: %Y. %m. %d. %H:%M',
|
||||||
'There is nobody assigned' => 'Nincs felelős',
|
'There is nobody assigned' => 'Nincs felelős',
|
||||||
'Column on the board:' => 'Tábla oszlopa: ',
|
'Column on the board:' => 'Tábla oszlopa: ',
|
||||||
'Status is open' => 'Nyitott állapot',
|
'Status is open' => 'Nyitott állapot',
|
||||||
|
@ -133,12 +135,12 @@ return array(
|
||||||
'The title is required' => 'A címet meg kell adni',
|
'The title is required' => 'A címet meg kell adni',
|
||||||
'The language is required' => 'A nyelvet meg kell adni',
|
'The language is required' => 'A nyelvet meg kell adni',
|
||||||
'There is no active project, the first step is to create a new project.' => 'Nincs aktív projekt. Először létre kell hozni egy projektet.',
|
'There is no active project, the first step is to create a new project.' => 'Nincs aktív projekt. Először létre kell hozni egy projektet.',
|
||||||
'Settings saved successfully.' => 'A beállítások mentése sikeres.',
|
'Settings saved successfully.' => 'A beállítások sikeresen mentve.',
|
||||||
'Unable to save your settings.' => 'A beállítások mentése sikertelen.',
|
'Unable to save your settings.' => 'A beállítások mentése sikertelen.',
|
||||||
'Database optimization done.' => 'Adatbázis optimalizálás kész.',
|
'Database optimization done.' => 'Adatbázis optimalizálás kész.',
|
||||||
'Your project have been created successfully.' => 'Projekt sikeresen létrehozva',
|
'Your project have been created successfully.' => 'Projekt sikeresen létrehozva',
|
||||||
'Unable to create your project.' => 'Projekt létrehozása sikertelen.',
|
'Unable to create your project.' => 'Projekt létrehozása sikertelen.',
|
||||||
'Project updated successfully.' => 'Projekt frissítése sikeres.',
|
'Project updated successfully.' => 'Projekt sikeresen frissítve.',
|
||||||
'Unable to update this project.' => 'Projekt frissítése sikertelen.',
|
'Unable to update this project.' => 'Projekt frissítése sikertelen.',
|
||||||
'Unable to remove this project.' => 'Projekt törlése sikertelen.',
|
'Unable to remove this project.' => 'Projekt törlése sikertelen.',
|
||||||
'Project removed successfully.' => 'Projekt sikeresen törölve.',
|
'Project removed successfully.' => 'Projekt sikeresen törölve.',
|
||||||
|
@ -146,7 +148,7 @@ return array(
|
||||||
'Unable to activate this project.' => 'Projekt aktiválása sikertelen.',
|
'Unable to activate this project.' => 'Projekt aktiválása sikertelen.',
|
||||||
'Project disabled successfully.' => 'Projekt sikeresen letiltva.',
|
'Project disabled successfully.' => 'Projekt sikeresen letiltva.',
|
||||||
'Unable to disable this project.' => 'Projekt letiltása sikertelen.',
|
'Unable to disable this project.' => 'Projekt letiltása sikertelen.',
|
||||||
'Unable to open this task.' => 'A feladat felnyitása nem sikerült.',
|
'Unable to open this task.' => 'A feladat felnyitása sikertelen.',
|
||||||
'Task opened successfully.' => 'Feladat sikeresen megnyitva .',
|
'Task opened successfully.' => 'Feladat sikeresen megnyitva .',
|
||||||
'Unable to close this task.' => 'A feladat lezárása sikertelen.',
|
'Unable to close this task.' => 'A feladat lezárása sikertelen.',
|
||||||
'Task closed successfully.' => 'Feladat sikeresen lezárva.',
|
'Task closed successfully.' => 'Feladat sikeresen lezárva.',
|
||||||
|
@ -166,8 +168,8 @@ return array(
|
||||||
'Work in progress' => 'Folyamatban',
|
'Work in progress' => 'Folyamatban',
|
||||||
'Done' => 'Kész',
|
'Done' => 'Kész',
|
||||||
'Application version:' => 'Alkalmazás verzió:',
|
'Application version:' => 'Alkalmazás verzió:',
|
||||||
'Completed on %B %e, %Y at %k:%M %p' => 'Elkészült %Y.%m.%d %H:%M ..',
|
'Completed on %B %e, %Y at %k:%M %p' => 'Elkészült: %Y. %m. %d. %H:%M',
|
||||||
'%B %e, %Y at %k:%M %p' => '%Y.%m.%d %H:%M',
|
'%B %e, %Y at %k:%M %p' => '%Y. %m. %d. %H:%M',
|
||||||
'Date created' => 'Létrehozás időpontja',
|
'Date created' => 'Létrehozás időpontja',
|
||||||
'Date completed' => 'Befejezés időpontja',
|
'Date completed' => 'Befejezés időpontja',
|
||||||
'Id' => 'ID',
|
'Id' => 'ID',
|
||||||
|
@ -211,9 +213,9 @@ return array(
|
||||||
'Edit this task' => 'Feladat módosítása',
|
'Edit this task' => 'Feladat módosítása',
|
||||||
'Due Date' => 'Határidő',
|
'Due Date' => 'Határidő',
|
||||||
'Invalid date' => 'Érvénytelen dátum',
|
'Invalid date' => 'Érvénytelen dátum',
|
||||||
'Must be done before %B %e, %Y' => 'Kész kell lennie %Y.%m.%d előtt',
|
'Must be done before %B %e, %Y' => 'Kész kell lennie %Y. %m. %d. előtt',
|
||||||
'%B %e, %Y' => '%Y.%m.%d',
|
'%B %e, %Y' => '%Y. %m. %d.',
|
||||||
'%b %e, %Y' => '%Y.%m.%d',
|
'%b %e, %Y' => '%Y. %m. %d.',
|
||||||
'Automatic actions' => 'Automatikus intézkedések',
|
'Automatic actions' => 'Automatikus intézkedések',
|
||||||
'Your automatic action have been created successfully.' => 'Az automatikus intézkedés sikeresen elkészült.',
|
'Your automatic action have been created successfully.' => 'Az automatikus intézkedés sikeresen elkészült.',
|
||||||
'Unable to create your automatic action.' => 'Automatikus intézkedés létrehozása nem lehetséges.',
|
'Unable to create your automatic action.' => 'Automatikus intézkedés létrehozása nem lehetséges.',
|
||||||
|
@ -254,7 +256,7 @@ return array(
|
||||||
'link' => 'link',
|
'link' => 'link',
|
||||||
'Update this comment' => 'Hozzászólás frissítése',
|
'Update this comment' => 'Hozzászólás frissítése',
|
||||||
'Comment updated successfully.' => 'Megjegyzés sikeresen frissítve.',
|
'Comment updated successfully.' => 'Megjegyzés sikeresen frissítve.',
|
||||||
'Unable to update your comment.' => 'Megjegyzés frissítése nem sikerült.',
|
'Unable to update your comment.' => 'Megjegyzés frissítése sikertelen.',
|
||||||
'Remove a comment' => 'Megjegyzés törlése',
|
'Remove a comment' => 'Megjegyzés törlése',
|
||||||
'Comment removed successfully.' => 'Megjegyzés sikeresen törölve.',
|
'Comment removed successfully.' => 'Megjegyzés sikeresen törölve.',
|
||||||
'Unable to remove this comment.' => 'Megjegyzés törölése nem lehetséges.',
|
'Unable to remove this comment.' => 'Megjegyzés törölése nem lehetséges.',
|
||||||
|
@ -294,8 +296,8 @@ return array(
|
||||||
'Your Google Account is not linked anymore to your profile.' => 'Google Fiók már nincs a profilhoz kapcsolva.',
|
'Your Google Account is not linked anymore to your profile.' => 'Google Fiók már nincs a profilhoz kapcsolva.',
|
||||||
'Unable to unlink your Google Account.' => 'Leválasztás a Google fiókról nem lehetséges.',
|
'Unable to unlink your Google Account.' => 'Leválasztás a Google fiókról nem lehetséges.',
|
||||||
'Google authentication failed' => 'Google azonosítás sikertelen',
|
'Google authentication failed' => 'Google azonosítás sikertelen',
|
||||||
'Unable to link your Google Account.' => 'Google profilhoz kapcsolás nem sikerült.',
|
'Unable to link your Google Account.' => 'A Google profilhoz kapcsolás sikertelen.',
|
||||||
'Your Google Account is linked to your profile successfully.' => 'Sikeresen összekapcsolva a Google fiókkal.',
|
'Your Google Account is linked to your profile successfully.' => 'Google fiókkal sikeresen összekapcsolva.',
|
||||||
'Email' => 'E-mail',
|
'Email' => 'E-mail',
|
||||||
'Link my Google Account' => 'Kapcsold össze a Google fiókkal',
|
'Link my Google Account' => 'Kapcsold össze a Google fiókkal',
|
||||||
'Unlink my Google Account' => 'Válaszd le a Google fiókomat',
|
'Unlink my Google Account' => 'Válaszd le a Google fiókomat',
|
||||||
|
@ -377,7 +379,7 @@ return array(
|
||||||
'Link my GitHub Account' => 'GitHub fiók csatolása',
|
'Link my GitHub Account' => 'GitHub fiók csatolása',
|
||||||
'Unlink my GitHub Account' => 'GitHub fiók leválasztása',
|
'Unlink my GitHub Account' => 'GitHub fiók leválasztása',
|
||||||
'Created by %s' => 'Készítette: %s',
|
'Created by %s' => 'Készítette: %s',
|
||||||
'Last modified on %B %e, %Y at %k:%M %p' => 'Utolsó módosítás: %Y.%m.%d %H:%M',
|
'Last modified on %B %e, %Y at %k:%M %p' => 'Utolsó módosítás: %Y. %m. %d. %H:%M',
|
||||||
'Tasks Export' => 'Feladatok exportálása',
|
'Tasks Export' => 'Feladatok exportálása',
|
||||||
'Tasks exportation for "%s"' => 'Feladatok exportálása: "%s"',
|
'Tasks exportation for "%s"' => 'Feladatok exportálása: "%s"',
|
||||||
'Start Date' => 'Kezdés dátuma',
|
'Start Date' => 'Kezdés dátuma',
|
||||||
|
@ -391,7 +393,7 @@ return array(
|
||||||
'Webhook URL for task modification' => 'Webhook URL a feladatot módosításakor',
|
'Webhook URL for task modification' => 'Webhook URL a feladatot módosításakor',
|
||||||
'Clone' => 'Másolat',
|
'Clone' => 'Másolat',
|
||||||
'Clone Project' => 'Projekt másolása',
|
'Clone Project' => 'Projekt másolása',
|
||||||
'Project cloned successfully.' => 'A projekt másolása sikeres',
|
'Project cloned successfully.' => 'A projekt sikeresen másolva.',
|
||||||
'Unable to clone this project.' => 'A projekt másolása sikertelen.',
|
'Unable to clone this project.' => 'A projekt másolása sikertelen.',
|
||||||
'Email notifications' => 'E-mail értesítések',
|
'Email notifications' => 'E-mail értesítések',
|
||||||
'Enable email notifications' => 'E-mail értesítések engedélyezése',
|
'Enable email notifications' => 'E-mail értesítések engedélyezése',
|
||||||
|
@ -435,7 +437,7 @@ return array(
|
||||||
'Move the task to another project' => 'Feladat áthelyezése másik projektbe',
|
'Move the task to another project' => 'Feladat áthelyezése másik projektbe',
|
||||||
'Move to another project' => 'Áthelyezés másik projektbe',
|
'Move to another project' => 'Áthelyezés másik projektbe',
|
||||||
'Do you really want to duplicate this task?' => 'Tényleg szeretné megkettőzni ezt a feladatot?',
|
'Do you really want to duplicate this task?' => 'Tényleg szeretné megkettőzni ezt a feladatot?',
|
||||||
'Duplicate a task' => 'Feladat megkettőzése',
|
'Duplicate a task' => 'Feladat másolása',
|
||||||
'External accounts' => 'Külső fiókok',
|
'External accounts' => 'Külső fiókok',
|
||||||
'Account type' => 'Fiók típusa',
|
'Account type' => 'Fiók típusa',
|
||||||
'Local' => 'Helyi',
|
'Local' => 'Helyi',
|
||||||
|
@ -517,7 +519,7 @@ return array(
|
||||||
'Label' => 'Címke',
|
'Label' => 'Címke',
|
||||||
'Database' => 'Adatbázis',
|
'Database' => 'Adatbázis',
|
||||||
'About' => 'Kanboard információ',
|
'About' => 'Kanboard információ',
|
||||||
'Database driver:' => 'Adatbázis driver:',
|
'Database driver:' => 'Adatbázis motor:',
|
||||||
'Board settings' => 'Tábla beállítások',
|
'Board settings' => 'Tábla beállítások',
|
||||||
'URL and token' => 'URL és tokenek',
|
'URL and token' => 'URL és tokenek',
|
||||||
'Webhook settings' => 'Webhook beállítások',
|
'Webhook settings' => 'Webhook beállítások',
|
||||||
|
@ -541,7 +543,7 @@ return array(
|
||||||
'Add' => 'Hozzáadás',
|
'Add' => 'Hozzáadás',
|
||||||
'Estimated time: %s hours' => 'Becsült idő: %s óra',
|
'Estimated time: %s hours' => 'Becsült idő: %s óra',
|
||||||
'Time spent: %s hours' => 'Eltöltött idő: %s óra',
|
'Time spent: %s hours' => 'Eltöltött idő: %s óra',
|
||||||
'Started on %B %e, %Y' => 'Elkezdve: %Y.%m.%d',
|
'Started on %B %e, %Y' => 'Elkezdve: %Y. %m. %d.',
|
||||||
'Start date' => 'Kezdés dátuma',
|
'Start date' => 'Kezdés dátuma',
|
||||||
'Time estimated' => 'Becsült időtartam',
|
'Time estimated' => 'Becsült időtartam',
|
||||||
'There is nothing assigned to you.' => 'Nincs kiosztott feladat.',
|
'There is nothing assigned to you.' => 'Nincs kiosztott feladat.',
|
||||||
|
@ -574,8 +576,8 @@ return array(
|
||||||
'My subtasks' => 'Részfeladataim',
|
'My subtasks' => 'Részfeladataim',
|
||||||
'User repartition' => 'Felhasználó újrafelosztás',
|
'User repartition' => 'Felhasználó újrafelosztás',
|
||||||
'User repartition for "%s"' => 'Felhasználó újrafelosztás: %s',
|
'User repartition for "%s"' => 'Felhasználó újrafelosztás: %s',
|
||||||
'Clone this project' => 'Projekt megkettőzése',
|
'Clone this project' => 'Projekt másolása',
|
||||||
'Column removed successfully.' => 'Oszlop sikeresen eltávolítva.',
|
'Column removed successfully.' => 'Oszlop sikeresen törölve.',
|
||||||
'Edit Project' => 'Projekt szerkesztése',
|
'Edit Project' => 'Projekt szerkesztése',
|
||||||
'Github Issue' => 'Github issue',
|
'Github Issue' => 'Github issue',
|
||||||
'Not enough data to show the graph.' => 'Nincs elég adat a grafikonhoz.',
|
'Not enough data to show the graph.' => 'Nincs elég adat a grafikonhoz.',
|
||||||
|
@ -669,8 +671,8 @@ return array(
|
||||||
'There is nothing to show.' => 'Nincs megjelenítendő adat.',
|
'There is nothing to show.' => 'Nincs megjelenítendő adat.',
|
||||||
'Time Tracking' => 'Idő követés',
|
'Time Tracking' => 'Idő követés',
|
||||||
'You already have one subtask in progress' => 'Már van egy folyamatban levő részfeladata',
|
'You already have one subtask in progress' => 'Már van egy folyamatban levő részfeladata',
|
||||||
'Which parts of the project do you want to duplicate?' => 'A projekt mely részeit szeretné duplikálni?',
|
'Which parts of the project do you want to duplicate?' => 'A projekt mely részeit szeretné másolni?',
|
||||||
'Change dashboard view' => 'Vezérlőpult megjelenítés változtatás',
|
'Change dashboard view' => 'Vezérlőpult megjelenés változtatás',
|
||||||
'Show/hide activities' => 'Tevékenységek megjelenítése/elrejtése',
|
'Show/hide activities' => 'Tevékenységek megjelenítése/elrejtése',
|
||||||
'Show/hide projects' => 'Projektek megjelenítése/elrejtése',
|
'Show/hide projects' => 'Projektek megjelenítése/elrejtése',
|
||||||
'Show/hide subtasks' => 'Részfeladatok megjelenítése/elrejtése',
|
'Show/hide subtasks' => 'Részfeladatok megjelenítése/elrejtése',
|
||||||
|
@ -728,10 +730,120 @@ return array(
|
||||||
'Close dialog box' => 'Ablak bezárása',
|
'Close dialog box' => 'Ablak bezárása',
|
||||||
'Submit a form' => 'Űrlap beküldése',
|
'Submit a form' => 'Űrlap beküldése',
|
||||||
'Board view' => 'Tábla nézet',
|
'Board view' => 'Tábla nézet',
|
||||||
'Keyboard shortcuts' => 'Billentyű kombináció',
|
'Keyboard shortcuts' => 'Billentyű kombinációk',
|
||||||
'Open board switcher' => 'Tábla választó lenyitása',
|
'Open board switcher' => 'Tábla választó lenyitása',
|
||||||
// 'Application' => '',
|
'Application' => 'Alkalmazás',
|
||||||
// 'Filter recently updated' => '',
|
'Filter recently updated' => 'Szűrés az utolsó módosítás ideje szerint',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
'since %B %e, %Y at %k:%M %p' => '%Y. %m. %d. %H:%M óta',
|
||||||
// 'More filters' => '',
|
'More filters' => 'További szűrők',
|
||||||
|
'Compact view' => 'Kompakt nézet',
|
||||||
|
'Horizontal scrolling' => 'Vízszintes görgetés',
|
||||||
|
'Compact/wide view' => 'Kompakt/széles nézet',
|
||||||
|
'No results match:' => 'Nincs találat:',
|
||||||
|
'Remove hourly rate' => 'Órabér törlése',
|
||||||
|
'Do you really want to remove this hourly rate?' => 'Valóban törölni kívánja az órabért?',
|
||||||
|
'Hourly rates' => 'Órabérek',
|
||||||
|
'Hourly rate' => 'Órabér',
|
||||||
|
'Currency' => 'Pénznem',
|
||||||
|
'Effective date' => 'Hatálybalépés ideje',
|
||||||
|
'Add new rate' => 'Új bér',
|
||||||
|
'Rate removed successfully.' => 'Bér sikeresen törölve.',
|
||||||
|
'Unable to remove this rate.' => 'Bér törlése sikertelen.',
|
||||||
|
'Unable to save the hourly rate.' => 'Órabér mentése sikertelen.',
|
||||||
|
'Hourly rate created successfully.' => 'Órabér sikeresen mentve.',
|
||||||
|
'Start time' => 'Kezdés ideje',
|
||||||
|
'End time' => 'Végzés ideje',
|
||||||
|
'Comment' => 'Megjegyzés',
|
||||||
|
'All day' => 'Egész nap',
|
||||||
|
'Day' => 'Nap',
|
||||||
|
'Manage timetable' => 'Időbeosztás kezelése',
|
||||||
|
'Overtime timetable' => 'Túlóra időbeosztás',
|
||||||
|
'Time off timetable' => 'Szabadság időbeosztás',
|
||||||
|
'Timetable' => 'Időbeosztás',
|
||||||
|
'Work timetable' => 'Munka időbeosztás',
|
||||||
|
'Week timetable' => 'Heti időbeosztás',
|
||||||
|
'Day timetable' => 'Napi időbeosztás',
|
||||||
|
'From' => 'Feladó:',
|
||||||
|
'To' => 'Címzett:',
|
||||||
|
'Time slot created successfully.' => 'Időszelet sikeresen létrehozva.',
|
||||||
|
'Unable to save this time slot.' => 'Időszelet mentése sikertelen.',
|
||||||
|
'Time slot removed successfully.' => 'Időszelet sikeresen törölve.',
|
||||||
|
'Unable to remove this time slot.' => 'Időszelet törlése sikertelen.',
|
||||||
|
'Do you really want to remove this time slot?' => 'Biztos törli ezt az időszeletet?',
|
||||||
|
'Remove time slot' => 'Időszelet törlése',
|
||||||
|
'Add new time slot' => 'Új Időszelet',
|
||||||
|
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ez az időbeosztás van használatban ha az "egész nap" jelölőnégyzet be van jelölve a tervezett szabadságnál és túlóránál.',
|
||||||
|
'Files' => 'Fájlok',
|
||||||
|
'Images' => 'Képek',
|
||||||
|
'Private project' => 'Privát projekt',
|
||||||
|
'Amount' => 'Összeg',
|
||||||
|
'AUD - Australian Dollar' => 'AUD - Ausztrál dollár',
|
||||||
|
'Budget' => 'Költségvetés',
|
||||||
|
'Budget line' => 'Költségvetési tétel',
|
||||||
|
'Budget line removed successfully.' => 'Költségvetési tétel sikeresen törölve.',
|
||||||
|
'Budget lines' => 'Költségvetési tételek',
|
||||||
|
'CAD - Canadian Dollar' => 'CAD - Kanadai dollár',
|
||||||
|
'CHF - Swiss Francs' => 'CHF - Svájci frank',
|
||||||
|
'Cost' => 'Költség',
|
||||||
|
'Cost breakdown' => 'Költség visszaszámlálás',
|
||||||
|
'Custom Stylesheet' => 'Egyéni sítluslap',
|
||||||
|
'download' => 'letöltés',
|
||||||
|
'Do you really want to remove this budget line?' => 'Biztos törölni akarja ezt a költségvetési tételt?',
|
||||||
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
|
'Expenses' => 'Kiadások',
|
||||||
|
'GBP - British Pound' => 'GBP - Angol font',
|
||||||
|
'INR - Indian Rupee' => 'INR - Indiai rúpia',
|
||||||
|
'JPY - Japanese Yen' => 'JPY - Japán Yen',
|
||||||
|
'New budget line' => 'Új költségvetési tétel',
|
||||||
|
'NZD - New Zealand Dollar' => 'NZD - Új-Zélandi dollár',
|
||||||
|
'Remove a budget line' => 'Költségvetési tétel törlése',
|
||||||
|
'Remove budget line' => 'Költségvetési tétel törlése',
|
||||||
|
'RSD - Serbian dinar' => 'RSD - Szerb dínár',
|
||||||
|
'The budget line have been created successfully.' => 'Költségvetési tétel sikeresen létrehozva.',
|
||||||
|
'Unable to create the budget line.' => 'Költségvetési tétel létrehozása sikertelen.',
|
||||||
|
'Unable to remove this budget line.' => 'Költségvetési tétel törlése sikertelen.',
|
||||||
|
'USD - US Dollar' => 'USD - Amerikai ollár',
|
||||||
|
'Remaining' => 'Maradék',
|
||||||
|
'Destination column' => 'Cél oszlop',
|
||||||
|
'Move the task to another column when assigned to a user' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés után',
|
||||||
|
'Move the task to another column when assignee is cleared' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés törlésekor',
|
||||||
|
'Source column' => 'Forrás oszlop',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Nessuno',
|
'None' => 'Nessuno',
|
||||||
'edit' => 'modificare',
|
'edit' => 'modificare',
|
||||||
'Edit' => 'Modificare',
|
'Edit' => 'Modificare',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'なし',
|
'None' => 'なし',
|
||||||
'edit' => '変更',
|
'edit' => '変更',
|
||||||
'Edit' => '変更',
|
'Edit' => '変更',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
849
sources/app/Locale/nl_NL/translations.php
Normal file
849
sources/app/Locale/nl_NL/translations.php
Normal file
|
@ -0,0 +1,849 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
|
'None' => 'Geen',
|
||||||
|
'edit' => 'bewerken',
|
||||||
|
'Edit' => 'Bewerken',
|
||||||
|
'remove' => 'verwijderen',
|
||||||
|
'Remove' => 'Verwijderen',
|
||||||
|
'Update' => 'Update',
|
||||||
|
'Yes' => 'Ja',
|
||||||
|
'No' => 'Nee',
|
||||||
|
'cancel' => 'annuleren',
|
||||||
|
'or' => 'of',
|
||||||
|
'Yellow' => 'Geel',
|
||||||
|
'Blue' => 'Blauw',
|
||||||
|
'Green' => 'Groen',
|
||||||
|
'Purple' => 'Paars',
|
||||||
|
'Red' => 'Rood',
|
||||||
|
'Orange' => 'Oranje',
|
||||||
|
'Grey' => 'Grijs',
|
||||||
|
'Save' => 'Opslaan',
|
||||||
|
'Login' => 'Inloggen',
|
||||||
|
'Official website:' => 'Officiële website :',
|
||||||
|
'Unassigned' => 'Niet toegewezen',
|
||||||
|
'View this task' => 'Deze taak bekijken',
|
||||||
|
'Remove user' => 'Gebruiker verwijderen',
|
||||||
|
'Do you really want to remove this user: "%s"?' => 'Weet u zeker dat u deze gebruiker wil verwijderen : « %s » ?',
|
||||||
|
'New user' => 'Nieuwe gebruiker',
|
||||||
|
'All users' => 'Alle gebruikers',
|
||||||
|
'Username' => 'Gebruikersnaam',
|
||||||
|
'Password' => 'Wachtwoord',
|
||||||
|
'Default project' => 'Standaard wachtwoord',
|
||||||
|
'Administrator' => 'Administrator',
|
||||||
|
'Sign in' => 'Inloggen',
|
||||||
|
'Users' => 'Gebruikers',
|
||||||
|
'No user' => 'Geen gebruiker',
|
||||||
|
'Forbidden' => 'Geweigerd',
|
||||||
|
'Access Forbidden' => 'Toegang geweigerd',
|
||||||
|
'Only administrators can access to this page.' => 'Alleen administrators hebben toegang tot deze pagina.',
|
||||||
|
'Edit user' => 'Gebruiker bewerken',
|
||||||
|
'Logout' => 'Uitloggen',
|
||||||
|
'Bad username or password' => 'Verkeerde gebruikersnaam of wachtwoord',
|
||||||
|
'users' => 'gebruikers',
|
||||||
|
'projects' => 'projecten',
|
||||||
|
'Edit project' => 'Project bewerken',
|
||||||
|
'Name' => 'Naam',
|
||||||
|
'Activated' => 'Geactiveerd',
|
||||||
|
'Projects' => 'Projecten',
|
||||||
|
'No project' => 'Geen project',
|
||||||
|
'Project' => 'Project',
|
||||||
|
'Status' => 'Status',
|
||||||
|
'Tasks' => 'Taken',
|
||||||
|
'Board' => 'Bord',
|
||||||
|
'Actions' => 'Acties',
|
||||||
|
'Inactive' => 'Inactief',
|
||||||
|
'Active' => 'Actief',
|
||||||
|
'Column %d' => 'Kolom %d',
|
||||||
|
'Add this column' => 'Deze kolom toevoegen',
|
||||||
|
'%d tasks on the board' => '%d taken op het bord',
|
||||||
|
'%d tasks in total' => '%d taken in totaal',
|
||||||
|
'Unable to update this board.' => 'Update van dit bord niet mogelijk.',
|
||||||
|
'Edit board' => 'Bord bewerken',
|
||||||
|
'Disable' => 'Deactiveren',
|
||||||
|
'Enable' => 'Activeren',
|
||||||
|
'New project' => 'Nieuw project',
|
||||||
|
'Do you really want to remove this project: "%s"?' => 'Weet u zeker dat u dit project wil verwijderen : « %s » ?',
|
||||||
|
'Remove project' => 'Project verwijderen',
|
||||||
|
'Boards' => 'Borden',
|
||||||
|
'Edit the board for "%s"' => 'Bord bewerken voor « %s »',
|
||||||
|
'All projects' => 'Alle projecten',
|
||||||
|
'Change columns' => 'Kolommen veranderen',
|
||||||
|
'Add a new column' => 'Kolom toevoegen',
|
||||||
|
'Title' => 'Titel',
|
||||||
|
'Add Column' => 'Kolom toevoegen',
|
||||||
|
'Project "%s"' => 'Project « %s »',
|
||||||
|
'Nobody assigned' => 'Niemand toegewezen',
|
||||||
|
'Assigned to %s' => 'Toegewezen aan %s',
|
||||||
|
'Remove a column' => 'Kolom verwijderen',
|
||||||
|
'Remove a column from a board' => 'Kolom verwijderen van het bord',
|
||||||
|
'Unable to remove this column.' => 'Verwijderen van deze kolom niet mogelijk.',
|
||||||
|
'Do you really want to remove this column: "%s"?' => 'Weet u zeker dat u deze kolom wil verwijderen : « %s » ?',
|
||||||
|
'This action will REMOVE ALL TASKS associated to this column!' => 'Deze actie zal ALLE TAKEN VERWIJDEREN die zijn geassocieerd met deze kolom!',
|
||||||
|
'Settings' => 'Instellingen',
|
||||||
|
'Application settings' => 'Applicatie instellingen',
|
||||||
|
'Language' => 'Taal',
|
||||||
|
'Webhook token:' => 'Webhook token :',
|
||||||
|
'API token:' => 'API token :',
|
||||||
|
'More information' => 'Meer informatie',
|
||||||
|
'Database size:' => 'Database grootte :',
|
||||||
|
'Download the database' => 'Download de database',
|
||||||
|
'Optimize the database' => 'Optimaliseer de database',
|
||||||
|
'(VACUUM command)' => '(VACUUM commando)',
|
||||||
|
'(Gzip compressed Sqlite file)' => '(Gzip ingepakt Sqlite bestand)',
|
||||||
|
'User settings' => 'Gebruikers instellingen',
|
||||||
|
'My default project:' => 'Mijn standaard project : ',
|
||||||
|
'Close a task' => 'Taak sluiten',
|
||||||
|
'Do you really want to close this task: "%s"?' => 'Weet u zeker dat u deze taak wil sluiten : « %s » ?',
|
||||||
|
'Edit a task' => 'Taak bewerken',
|
||||||
|
'Column' => 'Kolom',
|
||||||
|
'Color' => 'Kleur',
|
||||||
|
'Assignee' => 'Toegewezene',
|
||||||
|
'Create another task' => 'Nog een taak aanmaken',
|
||||||
|
'New task' => 'Nieuwe taak',
|
||||||
|
'Open a task' => 'Een taak openen',
|
||||||
|
'Do you really want to open this task: "%s"?' => 'Weet u zeker dat u deze taak wil openen : « %s » ?',
|
||||||
|
'Back to the board' => 'Terug naar het bord',
|
||||||
|
'Created on %B %e, %Y at %k:%M %p' => 'Aangemaakt op %d/%m/%Y à %H:%M',
|
||||||
|
'There is nobody assigned' => 'Er is niemand toegewezen',
|
||||||
|
'Column on the board:' => 'Kolom op het bord : ',
|
||||||
|
'Status is open' => 'Status is open',
|
||||||
|
'Status is closed' => 'Status is gesloten',
|
||||||
|
'Close this task' => 'Deze taak sluiten',
|
||||||
|
'Open this task' => 'Deze taak openen',
|
||||||
|
'There is no description.' => 'Er is geen omschrijving.',
|
||||||
|
'Add a new task' => 'Een nieuwe taak toevoegen',
|
||||||
|
'The username is required' => 'De gebruikersnaam is verplicht',
|
||||||
|
'The maximum length is %d characters' => 'De maximale lengte is %d karakters',
|
||||||
|
'The minimum length is %d characters' => 'De minimale lengte is %d karakters',
|
||||||
|
'The password is required' => 'Het wachtwoord is verplicht',
|
||||||
|
'This value must be an integer' => 'Deze waarde dient een integer te zijn',
|
||||||
|
'The username must be unique' => 'De gebruikersnaam moet uniek zijn',
|
||||||
|
'The username must be alphanumeric' => 'De gebruikersnaam moet alfanumeriek zijn',
|
||||||
|
'The user id is required' => 'Het gebruikers id is verplicht',
|
||||||
|
'Passwords don\'t match' => 'De wachtwoorden komen niet overeen',
|
||||||
|
'The confirmation is required' => 'De bevestiging is verplicht',
|
||||||
|
'The column is required' => 'De kolom is verplicht',
|
||||||
|
'The project is required' => 'Het project is verplicht',
|
||||||
|
'The color is required' => 'De kleur is verplicht',
|
||||||
|
'The id is required' => 'Het id is verplicht',
|
||||||
|
'The project id is required' => 'Het project id is verplicht',
|
||||||
|
'The project name is required' => 'De projectnaam is verplicht',
|
||||||
|
'This project must be unique' => 'Dit project moet uniek zijn',
|
||||||
|
'The title is required' => 'De titel is verplicht',
|
||||||
|
'The language is required' => 'De taal is verplicht',
|
||||||
|
'There is no active project, the first step is to create a new project.' => 'Er is geen actief project, de eerste stap is een nieuw project aanmaken.',
|
||||||
|
'Settings saved successfully.' => 'Instellingen succesvol opgeslagen.',
|
||||||
|
'Unable to save your settings.' => 'Instellingen opslaan niet gelukt.',
|
||||||
|
'Database optimization done.' => 'Database optimaliseren voltooid.',
|
||||||
|
'Your project have been created successfully.' => 'Uw project is succesvol aangemaakt.',
|
||||||
|
'Unable to create your project.' => 'Het aanmaken van het project is niet gelukt.',
|
||||||
|
'Project updated successfully.' => 'Project succesvol geupdate.',
|
||||||
|
'Unable to update this project.' => 'Updaten van project niet gelukt.',
|
||||||
|
'Unable to remove this project.' => 'Verwijderen van project niet gelukt.',
|
||||||
|
'Project removed successfully.' => 'Project succesvol verwijderd.',
|
||||||
|
'Project activated successfully.' => 'Project succesvol geactiveerd.',
|
||||||
|
'Unable to activate this project.' => 'Project activeren niet gelukt.',
|
||||||
|
'Project disabled successfully.' => 'Project uitschakelen succesvol.',
|
||||||
|
'Unable to disable this project.' => 'Project uitschakelen niet gelukt.',
|
||||||
|
'Unable to open this task.' => 'Openen van deze taak niet gelukt.',
|
||||||
|
'Task opened successfully.' => 'Taak succesvol geopend.',
|
||||||
|
'Unable to close this task.' => 'Sluiten van deze taak niet gelukt.',
|
||||||
|
'Task closed successfully.' => 'Taak succesvol gesloten.',
|
||||||
|
'Unable to update your task.' => 'Updaten van uw taak mislukt.',
|
||||||
|
'Task updated successfully.' => 'Taak succesvol geupdate.',
|
||||||
|
'Unable to create your task.' => 'Taak aanmaken niet gelukt.',
|
||||||
|
'Task created successfully.' => 'Taak succesvol aangemaakt.',
|
||||||
|
'User created successfully.' => 'Gebruiker succesvol aangemaakt.',
|
||||||
|
'Unable to create your user.' => 'Aanmaken van gebruiker niet gelukt.',
|
||||||
|
'User updated successfully.' => 'Gebruiker succesvol geupdate',
|
||||||
|
'Unable to update your user.' => 'Updaten van gebruiker niet gelukt.',
|
||||||
|
'User removed successfully.' => 'Gebruiker succesvol verwijderd.',
|
||||||
|
'Unable to remove this user.' => 'Verwijderen van gebruikers niet gelukt.',
|
||||||
|
'Board updated successfully.' => 'Board succesvol geupdate.',
|
||||||
|
'Ready' => 'Klaar',
|
||||||
|
'Backlog' => 'En attente',
|
||||||
|
'Work in progress' => 'In behandeling',
|
||||||
|
'Done' => 'Klaar',
|
||||||
|
'Application version:' => 'Applicatie versie :',
|
||||||
|
'Completed on %B %e, %Y at %k:%M %p' => 'Voltooid op %d/%m/%Y à %H:%M',
|
||||||
|
'%B %e, %Y at %k:%M %p' => '%d/%m/%Y op %H:%M',
|
||||||
|
'Date created' => 'Datum aangemaakt',
|
||||||
|
'Date completed' => 'Datum voltooid',
|
||||||
|
'Id' => 'Id',
|
||||||
|
'No task' => 'Geen taak',
|
||||||
|
'Completed tasks' => 'Voltooide taken',
|
||||||
|
'List of projects' => 'Lijst van projecten',
|
||||||
|
'Completed tasks for "%s"' => 'Vooltooide taken voor « %s »',
|
||||||
|
'%d closed tasks' => '%d gesloten taken',
|
||||||
|
'No task for this project' => 'Geen taken voor dit project',
|
||||||
|
'Public link' => 'Publieke link',
|
||||||
|
'There is no column in your project!' => 'Er is geen kolom in uw project !',
|
||||||
|
'Change assignee' => 'Toegewezene aanpassen',
|
||||||
|
'Change assignee for the task "%s"' => 'Toegewezene aanpassen voor taak « %s »',
|
||||||
|
'Timezone' => 'Tijdzone',
|
||||||
|
'Sorry, I didn\'t find this information in my database!' => 'Sorry deze informatie kon niet worden gevonden in de database !',
|
||||||
|
'Page not found' => 'Pagina niet gevonden',
|
||||||
|
'Complexity' => 'Complexiteit',
|
||||||
|
'limit' => 'Limiet',
|
||||||
|
'Task limit' => 'Taak limiet.',
|
||||||
|
'Task count' => 'Aantal taken',
|
||||||
|
'This value must be greater than %d' => 'Deze waarde moet groter zijn dan %d',
|
||||||
|
'Edit project access list' => 'Aanpassen toegangsrechten project',
|
||||||
|
'Edit users access' => 'Gebruikerstoegang aanpassen',
|
||||||
|
'Allow this user' => 'Deze gebruiker toestaan',
|
||||||
|
'Only those users have access to this project:' => 'Alleen deze gebruikers hebben toegang tot dit project :',
|
||||||
|
'Don\'t forget that administrators have access to everything.' => 'Vergeet niet dat administrators overal toegang hebben.',
|
||||||
|
'Revoke' => 'Intrekken',
|
||||||
|
'List of authorized users' => 'Lijst met geautoriseerde gebruikers',
|
||||||
|
'User' => 'Gebruiker',
|
||||||
|
'Nobody have access to this project.' => 'Niemand heeft toegang tot dit project',
|
||||||
|
'You are not allowed to access to this project.' => 'U heeft geen toegang tot dit project.',
|
||||||
|
'Comments' => 'Commentaar',
|
||||||
|
'Post comment' => 'Commentaar toevoegen',
|
||||||
|
'Write your text in Markdown' => 'Schrijf uw tekst in Markdown',
|
||||||
|
'Leave a comment' => 'Schrijf een commentaar',
|
||||||
|
'Comment is required' => 'Commentaar is verplicht',
|
||||||
|
'Leave a description' => 'Schrijf een omschrijving',
|
||||||
|
'Comment added successfully.' => 'Commentaar succesvol toegevoegd.',
|
||||||
|
'Unable to create your comment.' => 'Commentaar toevoegen niet gelukt.',
|
||||||
|
'The description is required' => 'Omschrijving is verplicht',
|
||||||
|
'Edit this task' => 'Deze taak aanpassen',
|
||||||
|
'Due Date' => 'Vervaldag',
|
||||||
|
'Invalid date' => 'Ongeldige datum',
|
||||||
|
'Must be done before %B %e, %Y' => 'Moet voltooid zijn voor %d/%m/%Y',
|
||||||
|
'%B %e, %Y' => '%d %B %Y',
|
||||||
|
'%b %e, %Y' => '%d/%m/%Y',
|
||||||
|
'Automatic actions' => 'Geautomatiseerd acties',
|
||||||
|
'Your automatic action have been created successfully.' => 'Geautomatiseerde actie succesvol aangemaakt.',
|
||||||
|
'Unable to create your automatic action.' => 'Geautomatiseerde actie aanmaken niet gelukt.',
|
||||||
|
'Remove an action' => 'Actie verwijderen',
|
||||||
|
'Unable to remove this action.' => 'Actie verwijderen niet gelukt',
|
||||||
|
'Action removed successfully.' => 'Actie succesvol verwijder.',
|
||||||
|
'Automatic actions for the project "%s"' => 'Automatiseer acties voor project « %s »',
|
||||||
|
'Defined actions' => 'Gedefinieerde acties',
|
||||||
|
'Add an action' => 'Actie toevoegen',
|
||||||
|
'Event name' => 'Naam gebeurtenis',
|
||||||
|
'Action name' => 'Actie naam',
|
||||||
|
'Action parameters' => 'Actie paramaters',
|
||||||
|
'Action' => 'Actie',
|
||||||
|
'Event' => 'Evenement',
|
||||||
|
'When the selected event occurs execute the corresponding action.' => 'Als de geselecteerde gebeurtenis optreedt de volgende actie uitvoeren',
|
||||||
|
'Next step' => 'Volgende stap',
|
||||||
|
'Define action parameters' => 'Bepaal actie parameters',
|
||||||
|
'Save this action' => 'Actie opslaan',
|
||||||
|
'Do you really want to remove this action: "%s"?' => 'Weet u zeker dat u de volgende actie wil verwijderen : « %s » ?',
|
||||||
|
'Remove an automatic action' => 'Automatische actie verwijderen',
|
||||||
|
'Close the task' => 'Taak sluiten',
|
||||||
|
'Assign the task to a specific user' => 'Taak toewijzen aan een gebruiker',
|
||||||
|
'Assign the task to the person who does the action' => 'Taak toewijzen aan een gebruiker die de actie uitvoert',
|
||||||
|
'Duplicate the task to another project' => 'Taak dupliceren in een ander project',
|
||||||
|
'Move a task to another column' => 'Taak verplaatsen naar een andere kolom',
|
||||||
|
'Move a task to another position in the same column' => 'Taak verplaatsen naar een andere positie in dezelfde kolom',
|
||||||
|
'Task modification' => 'Taak aanpassen',
|
||||||
|
'Task creation' => 'Taak aanmaken',
|
||||||
|
'Open a closed task' => 'Gesloten taak openen',
|
||||||
|
'Closing a task' => 'Taak sluiten',
|
||||||
|
'Assign a color to a specific user' => 'Wijs een kleur toe aan een gebruiker',
|
||||||
|
'Column title' => 'Kolom titel',
|
||||||
|
'Position' => 'Positie',
|
||||||
|
'Move Up' => 'Omhoog verplaatsen',
|
||||||
|
'Move Down' => 'Omlaag verplaatsen',
|
||||||
|
'Duplicate to another project' => 'Dupliceren in een ander project',
|
||||||
|
'Duplicate' => 'Dupliceren',
|
||||||
|
'link' => 'koppelen',
|
||||||
|
'Update this comment' => 'Commentaar aanpassen',
|
||||||
|
'Comment updated successfully.' => 'Commentaar succesvol aangepast.',
|
||||||
|
'Unable to update your comment.' => 'Commentaar aanpassen niet gelukt.',
|
||||||
|
'Remove a comment' => 'Commentaar verwijderen',
|
||||||
|
'Comment removed successfully.' => 'Commentaar succesvol verwijder.',
|
||||||
|
'Unable to remove this comment.' => 'Commentaar verwijderen niet gelukt.',
|
||||||
|
'Do you really want to remove this comment?' => 'Weet u zeker dat u dit commentaar wil verwijderen ?',
|
||||||
|
'Only administrators or the creator of the comment can access to this page.' => 'Alleen administrators of de aanmaker van het commentaar hebben toegang tot deze pagina.',
|
||||||
|
'Details' => 'Details',
|
||||||
|
'Current password for the user "%s"' => 'Huidig wachtwoord voor gebruiker « %s »',
|
||||||
|
'The current password is required' => 'Huidig wachtwoord is verplicht',
|
||||||
|
'Wrong password' => 'Onjuist wachtwoord',
|
||||||
|
'Reset all tokens' => 'Alle tokens resetten',
|
||||||
|
'All tokens have been regenerated.' => 'Alle tokens zijn opnieuw gegenereerd.',
|
||||||
|
'Unknown' => 'Onbekend',
|
||||||
|
'Last logins' => 'Laatste logins',
|
||||||
|
'Login date' => 'Login datum',
|
||||||
|
'Authentication method' => 'Authenticatie methode',
|
||||||
|
'IP address' => 'IP adres',
|
||||||
|
'User agent' => 'User agent',
|
||||||
|
'Persistent connections' => 'Persistente connectie',
|
||||||
|
'No session.' => 'Geen sessie.',
|
||||||
|
'Expiration date' => 'Verloopdatum',
|
||||||
|
'Remember Me' => 'Onthoud mij',
|
||||||
|
'Creation date' => 'Aanmaakdatum',
|
||||||
|
'Filter by user' => 'Filter op gebruiker',
|
||||||
|
'Filter by due date' => 'Filter op vervaldatum',
|
||||||
|
'Everybody' => 'Iedereen',
|
||||||
|
'Open' => 'Open',
|
||||||
|
'Closed' => 'Gesloten',
|
||||||
|
'Search' => 'Zoek',
|
||||||
|
'Nothing found.' => 'Niets gevonden.',
|
||||||
|
'Search in the project "%s"' => 'Zoek in project « %s »',
|
||||||
|
'Due date' => 'Vervaldatum',
|
||||||
|
'Others formats accepted: %s and %s' => 'Andere toegestane formaten : %s en %s',
|
||||||
|
'Description' => 'Omschrijving',
|
||||||
|
'%d comments' => '%d commentaren',
|
||||||
|
'%d comment' => '%d commentaar',
|
||||||
|
'Email address invalid' => 'Ongeldig emailadres',
|
||||||
|
'Your Google Account is not linked anymore to your profile.' => 'Uw Google Account is niet meer aan uw profiel gelinkt.',
|
||||||
|
'Unable to unlink your Google Account.' => 'Verwijderen link met Google Account niet gelukt.',
|
||||||
|
'Google authentication failed' => 'Google authenticatie niet gelukt',
|
||||||
|
'Unable to link your Google Account.' => 'Linken met Google Account niet gelukt',
|
||||||
|
'Your Google Account is linked to your profile successfully.' => 'Linken met Google Account succesvol.',
|
||||||
|
'Email' => 'Email',
|
||||||
|
'Link my Google Account' => 'Link mijn Google Account',
|
||||||
|
'Unlink my Google Account' => 'Link met Google Account verwijderen',
|
||||||
|
'Login with my Google Account' => 'Inloggen met mijn Google Account',
|
||||||
|
'Project not found.' => 'Project niet gevonden.',
|
||||||
|
'Task #%d' => 'Taak %d',
|
||||||
|
'Task removed successfully.' => 'Taak succesvol verwijderd.',
|
||||||
|
'Unable to remove this task.' => 'Taak verwijderen niet gelukt.',
|
||||||
|
'Remove a task' => 'Taak verwijderen',
|
||||||
|
'Do you really want to remove this task: "%s"?' => 'Weet u zeker dat u deze taak wil verwijderen « %s » ?',
|
||||||
|
'Assign automatically a color based on a category' => 'Automatisch een kleur toewijzen aan de hand van een categorie',
|
||||||
|
'Assign automatically a category based on a color' => 'Automatisch een categorie toewijzen aan de hand van een kleur',
|
||||||
|
'Task creation or modification' => 'Taak aanmaken of wijzigen',
|
||||||
|
'Category' => 'Categorie',
|
||||||
|
'Category:' => 'Categorie :',
|
||||||
|
'Categories' => 'Categorieën',
|
||||||
|
'Category not found.' => 'Categorie niet gevonden',
|
||||||
|
'Your category have been created successfully.' => 'Categorie succesvol aangemaakt.',
|
||||||
|
'Unable to create your category.' => 'Categorie aanmaken niet gelukt.',
|
||||||
|
'Your category have been updated successfully.' => 'Categorie succesvol aangepast.',
|
||||||
|
'Unable to update your category.' => 'Aanpassen van categorie niet gelukt.',
|
||||||
|
'Remove a category' => 'Categorie verwijderen',
|
||||||
|
'Category removed successfully.' => 'Categorie succesvol verwijderd.',
|
||||||
|
'Unable to remove this category.' => 'Categorie verwijderen niet gelukt.',
|
||||||
|
'Category modification for the project "%s"' => 'Categorie aanpassen voor project « %s »',
|
||||||
|
'Category Name' => 'Categorie naam',
|
||||||
|
'Categories for the project "%s"' => 'Categorieën voor project « %s »',
|
||||||
|
'Add a new category' => 'Categorie toevoegen',
|
||||||
|
'Do you really want to remove this category: "%s"?' => 'Weet u zeker dat u deze categorie wil verwijderen: « %s » ?',
|
||||||
|
'Filter by category' => 'Filter op categorie',
|
||||||
|
'All categories' => 'Alle categorieën',
|
||||||
|
'No category' => 'Geen categorie',
|
||||||
|
'The name is required' => 'De naam is verplicht',
|
||||||
|
'Remove a file' => 'Bestand verwijderen',
|
||||||
|
'Unable to remove this file.' => 'Bestand verwijderen niet gelukt.',
|
||||||
|
'File removed successfully.' => 'Bestand succesvol verwijdered.',
|
||||||
|
'Attach a document' => 'Document toevoegen',
|
||||||
|
'Do you really want to remove this file: "%s"?' => 'Weet u zeker dat u dit bestand wil verwijderen: « %s » ?',
|
||||||
|
'open' => 'openen',
|
||||||
|
'Attachments' => 'Bijlages',
|
||||||
|
'Edit the task' => 'Taak aanpassen',
|
||||||
|
'Edit the description' => 'Omschrijving aanpassen',
|
||||||
|
'Add a comment' => 'Commentaar toevoegen',
|
||||||
|
'Edit a comment' => 'Commentaar aanpassen',
|
||||||
|
'Summary' => 'Samenvatting',
|
||||||
|
'Time tracking' => 'Tijdschrijven',
|
||||||
|
'Estimate:' => 'Schatting :',
|
||||||
|
'Spent:' => 'Besteed :',
|
||||||
|
'Do you really want to remove this sub-task?' => 'Weet u zeker dat u deze subtaak wil verwijderen ?',
|
||||||
|
'Remaining:' => 'Restant :',
|
||||||
|
'hours' => 'uren',
|
||||||
|
'spent' => 'besteed',
|
||||||
|
'estimated' => 'geschat',
|
||||||
|
'Sub-Tasks' => 'Subtaken',
|
||||||
|
'Add a sub-task' => 'Subtaak toevoegen',
|
||||||
|
'Original estimate' => 'Orginele schatting',
|
||||||
|
'Create another sub-task' => 'Nog een subtaak toevoegen',
|
||||||
|
'Time spent' => 'Tijd besteed',
|
||||||
|
'Edit a sub-task' => 'Subtaak aanpassen',
|
||||||
|
'Remove a sub-task' => 'Subtaak verwijderen',
|
||||||
|
'The time must be a numeric value' => 'De tijd moet een numerieke waarde zijn',
|
||||||
|
'Todo' => 'Nog te doen',
|
||||||
|
'In progress' => 'In behandeling',
|
||||||
|
'Sub-task removed successfully.' => 'Subtaak succesvol verwijderd.',
|
||||||
|
'Unable to remove this sub-task.' => 'Subtaak verwijderen niet gelukt.',
|
||||||
|
'Sub-task updated successfully.' => 'Subtaak succesvol aangepast.',
|
||||||
|
'Unable to update your sub-task.' => 'Subtaak aanpassen niet gelukt.',
|
||||||
|
'Unable to create your sub-task.' => 'Subtaak aanmaken niet gelukt.',
|
||||||
|
'Sub-task added successfully.' => 'Subtaak succesvol aangemaakt.',
|
||||||
|
'Maximum size: ' => 'Maximale grootte : ',
|
||||||
|
'Unable to upload the file.' => 'Uploaden van bestand niet gelukt.',
|
||||||
|
'Display another project' => 'Een ander project weergeven',
|
||||||
|
'Your GitHub account was successfully linked to your profile.' => 'Uw Github Account is succesvol gelinkt aan uw profiel.',
|
||||||
|
'Unable to link your GitHub Account.' => 'Linken van uw Github Account niet gelukt.',
|
||||||
|
'GitHub authentication failed' => 'Github Authenticatie niet gelukt',
|
||||||
|
'Your GitHub account is no longer linked to your profile.' => 'Uw Github Account is niet langer gelinkt aan uw profiel.',
|
||||||
|
'Unable to unlink your GitHub Account.' => 'Verwijdern van de link met uw Github Account niet gelukt.',
|
||||||
|
'Login with my GitHub Account' => 'Login met mijn Github Account',
|
||||||
|
'Link my GitHub Account' => 'Link met mijn Github',
|
||||||
|
'Unlink my GitHub Account' => 'Link met mijn Github verwijderen',
|
||||||
|
'Created by %s' => 'Aangemaakt door %s',
|
||||||
|
'Last modified on %B %e, %Y at %k:%M %p' => 'Laatst gewijzigd op %d/%m/%Y à %H:%M',
|
||||||
|
'Tasks Export' => 'Taken exporteren',
|
||||||
|
'Tasks exportation for "%s"' => 'Taken exporteren voor « %s »',
|
||||||
|
'Start Date' => 'Startdatum',
|
||||||
|
'End Date' => 'Einddatum',
|
||||||
|
'Execute' => 'Uitvoeren',
|
||||||
|
'Task Id' => 'Taak Id',
|
||||||
|
'Creator' => 'Aangemaakt door',
|
||||||
|
'Modification date' => 'Wijzigingsdatum',
|
||||||
|
'Completion date' => 'Afgerond op',
|
||||||
|
'Webhook URL for task creation' => 'Webhook URL voor aanmaken taak',
|
||||||
|
'Webhook URL for task modification' => 'Webhook URL voor wijzigen taak',
|
||||||
|
'Clone' => 'Kloon',
|
||||||
|
'Clone Project' => 'Project klonen',
|
||||||
|
'Project cloned successfully.' => 'Project succesvol gekloond.',
|
||||||
|
'Unable to clone this project.' => 'Klonen van project niet gelukt.',
|
||||||
|
'Email notifications' => 'Email notificatie',
|
||||||
|
'Enable email notifications' => 'Email notificatie aanzetten',
|
||||||
|
'Task position:' => 'Taak positie :',
|
||||||
|
'The task #%d have been opened.' => 'Taak #%d is geopend.',
|
||||||
|
'The task #%d have been closed.' => 'Taak #%d is gesloten.',
|
||||||
|
'Sub-task updated' => 'Subtaak aangepast',
|
||||||
|
'Title:' => 'Titel :',
|
||||||
|
'Status:' => 'Status :',
|
||||||
|
'Assignee:' => 'Toegewezene :',
|
||||||
|
'Time tracking:' => 'Tijdschrijven :',
|
||||||
|
'New sub-task' => 'Nieuwe subtaak',
|
||||||
|
'New attachment added "%s"' => 'Nieuwe bijlage toegevoegd « %s »',
|
||||||
|
'Comment updated' => 'Commentaar aangepast',
|
||||||
|
'New comment posted by %s' => 'Nieuw commentaar geplaatst door « %s »',
|
||||||
|
'List of due tasks for the project "%s"' => 'Lijst van taken die binnenkort voltooid moeten worden voor project « %s »',
|
||||||
|
'New attachment' => 'Nieuwe bijlage',
|
||||||
|
'New comment' => 'Nieuw commentaar',
|
||||||
|
'New subtask' => 'Nieuwe subtaak',
|
||||||
|
'Subtask updated' => 'Subtaak aangepast',
|
||||||
|
'Task updated' => 'Taak aangepast',
|
||||||
|
'Task closed' => 'Taak gesloten',
|
||||||
|
'Task opened' => 'Taak geopend',
|
||||||
|
'[%s][Due tasks]' => '[%s][binnekort te voltooien taken]',
|
||||||
|
'[Kanboard] Notification' => '[Kanboard] Notificatie',
|
||||||
|
'I want to receive notifications only for those projects:' => 'Ik wil notificaties ontvangen van de volgende projecten :',
|
||||||
|
'view the task on Kanboard' => 'taak bekijken op Kanboard',
|
||||||
|
'Public access' => 'Publieke toegang',
|
||||||
|
'Category management' => 'Categorie management',
|
||||||
|
'User management' => 'Gebruikers management',
|
||||||
|
'Active tasks' => 'Actieve taken',
|
||||||
|
'Disable public access' => 'Publieke toegang uitschakelen',
|
||||||
|
'Enable public access' => 'Publieke toegang inschakelen',
|
||||||
|
'Active projects' => 'Actieve projecten',
|
||||||
|
'Inactive projects' => 'Inactieve projecten',
|
||||||
|
'Public access disabled' => 'Publieke toegang uitgeschakeld',
|
||||||
|
'Do you really want to disable this project: "%s"?' => 'Weet u zeker dat u dit project wil uitschakelen : « %s » ?',
|
||||||
|
'Do you really want to duplicate this project: "%s"?' => 'Weet u zeker dat u dit project wil dupliceren : « %s » ?',
|
||||||
|
'Do you really want to enable this project: "%s"?' => 'Weet u zeker dat u dit project wil activeren : « %s » ?',
|
||||||
|
'Project activation' => 'Project activatie',
|
||||||
|
'Move the task to another project' => 'Taak verplaatsen naar een ander project',
|
||||||
|
'Move to another project' => 'Verplaats naar een ander project',
|
||||||
|
'Do you really want to duplicate this task?' => 'Weet u zeker dat u deze taak wil dupliceren ?',
|
||||||
|
'Duplicate a task' => 'Taak dupliceren',
|
||||||
|
'External accounts' => 'Externe accounts',
|
||||||
|
'Account type' => 'Account type',
|
||||||
|
'Local' => 'Lokaal',
|
||||||
|
'Remote' => 'Remote',
|
||||||
|
'Enabled' => 'Actief',
|
||||||
|
'Disabled' => 'Inactief',
|
||||||
|
'Google account linked' => 'Gelinkt Google Account',
|
||||||
|
'Github account linked' => 'Gelinkt Github Account',
|
||||||
|
'Username:' => 'Gebruikersnaam :',
|
||||||
|
'Name:' => 'Naam :',
|
||||||
|
'Email:' => 'Email :',
|
||||||
|
'Default project:' => 'Standaard project :',
|
||||||
|
'Notifications:' => 'Notificaties :',
|
||||||
|
'Notifications' => 'Notificaties',
|
||||||
|
'Group:' => 'Groep :',
|
||||||
|
'Regular user' => 'Normale gebruiker',
|
||||||
|
'Account type:' => 'Account type:',
|
||||||
|
'Edit profile' => 'Profiel aanpassen',
|
||||||
|
'Change password' => 'Wachtwoord aanpassen',
|
||||||
|
'Password modification' => 'Wachtwoord aanpassen',
|
||||||
|
'External authentications' => 'Externe authenticatie',
|
||||||
|
'Google Account' => 'Google Account',
|
||||||
|
'Github Account' => 'Github Account',
|
||||||
|
'Never connected.' => 'Nooit verbonden.',
|
||||||
|
'No account linked.' => 'Geen account gelinkt.',
|
||||||
|
'Account linked.' => 'Account gelinkt.',
|
||||||
|
'No external authentication enabled.' => 'Geen externe authenticatie aangezet.',
|
||||||
|
'Password modified successfully.' => 'Wachtwoord succesvol aangepast.',
|
||||||
|
'Unable to change the password.' => 'Aanpassen van wachtwoord niet gelukt.',
|
||||||
|
'Change category for the task "%s"' => 'Pas categorie aan voor taak « %s »',
|
||||||
|
'Change category' => 'Categorie aanpassen',
|
||||||
|
'%s updated the task %s' => '%s heeft taak %s aangepast',
|
||||||
|
'%s opened the task %s' => '%s heeft taak %s geopend',
|
||||||
|
'%s moved the task %s to the position #%d in the column "%s"' => '%s heeft taak %s naar positie %d in de kolom « %s » verplaatst',
|
||||||
|
'%s moved the task %s to the column "%s"' => '%s heeft taak %s verplaatst naar kolom « %s »',
|
||||||
|
'%s created the task %s' => '%s heeft taak %s aangemaakt',
|
||||||
|
'%s closed the task %s' => '%s heeft taak %s gesloten',
|
||||||
|
'%s created a subtask for the task %s' => '%s heeft een subtaak aangemaakt voor taak %s',
|
||||||
|
'%s updated a subtask for the task %s' => '%s heeft een subtaak aangepast voor taak %s',
|
||||||
|
'Assigned to %s with an estimate of %s/%sh' => 'Toegewezen aan %s met een schatting van %s/%sh',
|
||||||
|
'Not assigned, estimate of %sh' => 'Niet toegewezen, schatting: %sh',
|
||||||
|
'%s updated a comment on the task %s' => '%s heeft een commentaar aangepast voor taak %s',
|
||||||
|
'%s commented the task %s' => '%s heeft een commentaar geplaatst voor taak %s',
|
||||||
|
'%s\'s activity' => 'Activiteiten van %s',
|
||||||
|
'No activity.' => 'Geen activiteiten.',
|
||||||
|
'RSS feed' => 'RSS feed',
|
||||||
|
'%s updated a comment on the task #%d' => '%s heeft een commentaar aangepast voor taak %d',
|
||||||
|
'%s commented on the task #%d' => '%s heeft commentaar geplaatst voor taak %d',
|
||||||
|
'%s updated a subtask for the task #%d' => '%s heeft een commentaar aangepast voor subtaak %d',
|
||||||
|
'%s created a subtask for the task #%d' => '%s heeft een subtaak aangemaakt voor taak %d',
|
||||||
|
'%s updated the task #%d' => '%s heeft taak %d aangepast',
|
||||||
|
'%s created the task #%d' => '%s heeft taak %d aangemaakt',
|
||||||
|
'%s closed the task #%d' => '%s heeft taak %d gesloten',
|
||||||
|
'%s open the task #%d' => '%s a heeft taak %d geopend',
|
||||||
|
'%s moved the task #%d to the column "%s"' => '%s heeft taak %d verplaatst naar kolom « %s »',
|
||||||
|
'%s moved the task #%d to the position %d in the column "%s"' => '%s heeft taak %d verplaatst naar positie %d in kolom « %s »',
|
||||||
|
'Activity' => 'Activiteit',
|
||||||
|
'Default values are "%s"' => 'Standaardwaarden zijn « %s »',
|
||||||
|
'Default columns for new projects (Comma-separated)' => 'Standaard kolommen voor nieuw projecten (komma gescheiden)',
|
||||||
|
'Task assignee change' => 'Taak toegewezene verandering',
|
||||||
|
'%s change the assignee of the task #%d to %s' => '%s heeft de toegewezene voor taak %d veranderd in %s',
|
||||||
|
'%s changed the assignee of the task %s to %s' => '%s heeft de toegewezene voor taak %d veranderd in %s',
|
||||||
|
'Column Change' => 'Kolom verandering',
|
||||||
|
'Position Change' => 'Positie verandering',
|
||||||
|
'Assignee Change' => 'Toegewezene verandering',
|
||||||
|
'New password for the user "%s"' => 'Nieuw wachtwoord voor gebruiker « %s »',
|
||||||
|
'Choose an event' => 'Kies een gebeurtenis',
|
||||||
|
'Github commit received' => 'Github commentaar ontvangen',
|
||||||
|
'Github issue opened' => 'Github issue geopend',
|
||||||
|
'Github issue closed' => 'Github issue gesloten',
|
||||||
|
'Github issue reopened' => 'Github issue heropend',
|
||||||
|
'Github issue assignee change' => 'Github toegewezen veranderd',
|
||||||
|
'Github issue label change' => 'Github issue label verander',
|
||||||
|
'Create a task from an external provider' => 'Maak een taak aan vanuit een externe provider',
|
||||||
|
'Change the assignee based on an external username' => 'Verander de toegewezene aan de hand van de externe gebruikersnaam',
|
||||||
|
'Change the category based on an external label' => 'Verander de categorie aan de hand van een extern label',
|
||||||
|
'Reference' => 'Referentie',
|
||||||
|
'Reference: %s' => 'Referentie : %s',
|
||||||
|
'Label' => 'Label',
|
||||||
|
'Database' => 'Database',
|
||||||
|
'About' => 'Over',
|
||||||
|
'Database driver:' => 'Database driver :',
|
||||||
|
'Board settings' => 'Bord instellingen',
|
||||||
|
'URL and token' => 'URL en token',
|
||||||
|
'Webhook settings' => 'Webhook instellingen',
|
||||||
|
'URL for task creation:' => 'URL voor aanmaken taken :',
|
||||||
|
'Reset token' => 'Token resetten',
|
||||||
|
'API endpoint:' => 'API endpoint :',
|
||||||
|
'Refresh interval for private board' => 'Verversingsinterval voor private borden',
|
||||||
|
'Refresh interval for public board' => 'Verversingsinterval voor publieke borden',
|
||||||
|
'Task highlight period' => 'Taak highlight periode',
|
||||||
|
'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Periode (in seconden) om aan te geven of een taak recent is aangepast (0 om uit te schakelen, standaard 2 dagen)',
|
||||||
|
'Frequency in second (60 seconds by default)' => 'Frequentie in seconden (stadaard 60)',
|
||||||
|
'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frequentie in seconden (0 om uit te schakelen, standaard 10)',
|
||||||
|
'Application URL' => 'Applicatie URL',
|
||||||
|
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Voorbeeld: http://example.kanboard.net/ (gebruikt voor email notificaties)',
|
||||||
|
'Token regenerated.' => 'Token opnieuw gegenereerd.',
|
||||||
|
'Date format' => 'Datum formaat',
|
||||||
|
'ISO format is always accepted, example: "%s" and "%s"' => 'ISO formaat is altijd geaccepteerd, bijvoorbeeld : « %s » et « %s »',
|
||||||
|
'New private project' => 'Nieuw privé project',
|
||||||
|
'This project is private' => 'Dit project is privé',
|
||||||
|
'Type here to create a new sub-task' => 'Typ hier om een nieuwe subtaak aan te maken',
|
||||||
|
'Add' => 'Toevoegen',
|
||||||
|
'Estimated time: %s hours' => 'Geschatte tijd: %s hours',
|
||||||
|
'Time spent: %s hours' => 'Tijd besteed : %s heures',
|
||||||
|
'Started on %B %e, %Y' => 'Gestart op %d/%m/%Y',
|
||||||
|
'Start date' => 'Startdatum',
|
||||||
|
'Time estimated' => 'Geschatte tijd',
|
||||||
|
'There is nothing assigned to you.' => 'Er is niets aan u toegewezen.',
|
||||||
|
'My tasks' => 'Mijn taken',
|
||||||
|
'Activity stream' => 'Activiteiten',
|
||||||
|
'Dashboard' => 'Dashboard',
|
||||||
|
// 'Confirmation' => '',
|
||||||
|
'Allow everybody to access to this project' => 'Geef iedereen toegang tot dit project',
|
||||||
|
'Everybody have access to this project.' => 'Iedereen heeft toegang tot dit project.',
|
||||||
|
'Webhooks' => 'Webhooks',
|
||||||
|
'API' => 'API',
|
||||||
|
'Integration' => 'Integratue',
|
||||||
|
'Github webhooks' => 'Github webhooks',
|
||||||
|
'Help on Github webhooks' => 'Hulp bij Github webhooks',
|
||||||
|
'Create a comment from an external provider' => 'Voeg een commentaar toe van een externe provider',
|
||||||
|
'Github issue comment created' => 'Github issue commentaar aangemaakt',
|
||||||
|
'Configure' => 'Configureren',
|
||||||
|
'Project management' => 'Project management',
|
||||||
|
'My projects' => 'Mijn projecten',
|
||||||
|
'Columns' => 'Kolommen',
|
||||||
|
'Task' => 'Taak',
|
||||||
|
'Your are not member of any project.' => 'U bent van geen enkel project lid.',
|
||||||
|
'Percentage' => 'Percentage',
|
||||||
|
'Number of tasks' => 'Aantal taken',
|
||||||
|
'Task distribution' => 'Distributie van taken',
|
||||||
|
'Reportings' => 'Rapporten',
|
||||||
|
'Task repartition for "%s"' => 'Taakverdeling voor « %s »',
|
||||||
|
'Analytics' => 'Analytics',
|
||||||
|
'Subtask' => 'Subtaak',
|
||||||
|
'My subtasks' => 'Mijn subtaken',
|
||||||
|
'User repartition' => 'Gebruikerverdeling',
|
||||||
|
'User repartition for "%s"' => 'Gebruikerverdeling voor « %s »',
|
||||||
|
'Clone this project' => 'Kloon dit project',
|
||||||
|
'Column removed successfully.' => 'Kolom succesvol verwijderd.',
|
||||||
|
'Edit Project' => 'Project aanpassen',
|
||||||
|
'Github Issue' => 'Github issue',
|
||||||
|
'Not enough data to show the graph.' => 'Niet genoeg data om de grafiek te laten zien.',
|
||||||
|
// 'Previous' => '',
|
||||||
|
'The id must be an integer' => 'Het id moet een integer zijn',
|
||||||
|
'The project id must be an integer' => 'Het project id moet een integer zijn',
|
||||||
|
'The status must be an integer' => 'De status moet een integer zijn',
|
||||||
|
'The subtask id is required' => 'Het id van de subtaak is verplicht',
|
||||||
|
'The subtask id must be an integer' => 'Het id van de subtaak moet een integer zijn',
|
||||||
|
'The task id is required' => 'Het id van de taak is verplicht',
|
||||||
|
'The task id must be an integer' => 'Het id van de taak moet een integer zijn',
|
||||||
|
'The user id must be an integer' => 'Het id van de gebruiker moet een integer zijn',
|
||||||
|
'This value is required' => 'Deze waarde is verplicht',
|
||||||
|
'This value must be numeric' => 'Deze waarde moet numeriek zijn',
|
||||||
|
'Unable to create this task.' => 'Aanmaken van de taak mislukt',
|
||||||
|
'Cumulative flow diagram' => 'Cummulatief stroomdiagram',
|
||||||
|
'Cumulative flow diagram for "%s"' => 'Cummulatief stroomdiagram voor « %s »',
|
||||||
|
'Daily project summary' => 'Dagelijkse project samenvatting',
|
||||||
|
'Daily project summary export' => 'Dagelijkse project samenvatting export',
|
||||||
|
'Daily project summary export for "%s"' => 'Dagelijkse project samenvatting voor « %s »',
|
||||||
|
'Exports' => 'Exports',
|
||||||
|
'This export contains the number of tasks per column grouped per day.' => 'Dit rapport bevat het aantal taken per kolom gegroupeerd per dag.',
|
||||||
|
'Nothing to preview...' => 'Niets om te previewen...',
|
||||||
|
'Preview' => 'Preview',
|
||||||
|
'Write' => 'Schrijf',
|
||||||
|
'Active swimlanes' => 'Actieve swinlanes',
|
||||||
|
'Add a new swimlane' => 'Nieuwe swimlane toevoegen',
|
||||||
|
'Change default swimlane' => 'Standaard swimlane aapassen',
|
||||||
|
'Default swimlane' => 'Standaard swinlane',
|
||||||
|
'Do you really want to remove this swimlane: "%s"?' => 'Weet u zeker dat u deze swimlane wil verwijderen : « %s » ?',
|
||||||
|
'Inactive swimlanes' => 'Inactieve swinlanes',
|
||||||
|
'Set project manager' => 'Project manager instellen',
|
||||||
|
'Set project member' => 'Project lid instellen',
|
||||||
|
'Remove a swimlane' => 'Verwijder swinlane',
|
||||||
|
'Rename' => 'Hernoemen',
|
||||||
|
'Show default swimlane' => 'Standaard swimlane tonen',
|
||||||
|
'Swimlane modification for the project "%s"' => 'Swinlane aanpassing voor project « %s »',
|
||||||
|
'Swimlane not found.' => 'Swimlane niet gevonden.',
|
||||||
|
'Swimlane removed successfully.' => 'Swimlane succesvol verwijderd.',
|
||||||
|
'Swimlanes' => 'Swimlanes',
|
||||||
|
'Swimlane updated successfully.' => 'Swimlane succesvol aangepast.',
|
||||||
|
'The default swimlane have been updated successfully.' => 'De standaard swimlane is succesvol aangepast.',
|
||||||
|
'Unable to create your swimlane.' => 'Swimlane aanmaken niet gelukt.',
|
||||||
|
'Unable to remove this swimlane.' => 'Swimlane verwijderen niet gelukt.',
|
||||||
|
'Unable to update this swimlane.' => 'Swimlane aanpassen niet gelukt.',
|
||||||
|
'Your swimlane have been created successfully.' => 'Swimlane succesvol aangemaakt.',
|
||||||
|
'Example: "Bug, Feature Request, Improvement"' => 'Voorbeeld: « Bug, Feature Request, Improvement »',
|
||||||
|
'Default categories for new projects (Comma-separated)' => 'Standaard categorieën voor nieuwe projecten (komma gescheiden)',
|
||||||
|
'Gitlab commit received' => 'Gitlab commir ontvangen',
|
||||||
|
'Gitlab issue opened' => 'Gitlab issue geopend',
|
||||||
|
'Gitlab issue closed' => 'Gitlab issue gesloten',
|
||||||
|
'Gitlab webhooks' => 'Gitlab webhooks',
|
||||||
|
'Help on Gitlab webhooks' => 'Hulp bij Gitlab webhooks',
|
||||||
|
'Integrations' => 'Integraties',
|
||||||
|
'Integration with third-party services' => 'Integratie met derde-partij-services',
|
||||||
|
'Role for this project' => 'Rol voor dit project',
|
||||||
|
'Project manager' => 'Project manager',
|
||||||
|
'Project member' => 'Project lid',
|
||||||
|
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Een project manager kan de instellingen van het project wijzigen en heeft meer rechten dan een normale gebruiker.',
|
||||||
|
'Gitlab Issue' => 'Gitlab issue',
|
||||||
|
'Subtask Id' => 'Subtaak id',
|
||||||
|
'Subtasks' => 'Subtaken',
|
||||||
|
'Subtasks Export' => 'Subtaken exporteren',
|
||||||
|
'Subtasks exportation for "%s"' => 'Subtaken exporteren voor project « %s »',
|
||||||
|
'Task Title' => 'Taak title',
|
||||||
|
'Untitled' => 'Geen titel',
|
||||||
|
'Application default' => 'Standaard taal voor applicatie',
|
||||||
|
'Language:' => 'Taal :',
|
||||||
|
'Timezone:' => 'Tijdzone :',
|
||||||
|
'All columns' => 'Alle kolommen',
|
||||||
|
'Calendar for "%s"' => 'Agenda voor « %s »',
|
||||||
|
'Filter by column' => 'Filter op kolom',
|
||||||
|
'Filter by status' => 'Filter op status',
|
||||||
|
'Calendar' => 'Agenda',
|
||||||
|
'Next' => 'Volgende',
|
||||||
|
'#%d' => '%d',
|
||||||
|
'Filter by color' => 'Filter op kleur',
|
||||||
|
'Filter by swimlane' => 'Filter op swimlane',
|
||||||
|
'All swimlanes' => 'Alle swimlanes',
|
||||||
|
'All colors' => 'Alle kleuren',
|
||||||
|
'All status' => 'Alle statussen',
|
||||||
|
'Add a comment logging moving the task between columns' => 'Voeg een commentaar toe bij het verplaatsen van een taak tussen kolommen',
|
||||||
|
'Moved to column %s' => 'Verplaatst naar kolom',
|
||||||
|
'Change description' => 'Verandering omschrijving',
|
||||||
|
'User dashboard' => 'Gebruiker dashboard',
|
||||||
|
'Allow only one subtask in progress at the same time for a user' => 'Sta maximaal één subtaak in behandeling toe per gebruiker',
|
||||||
|
'Edit column "%s"' => 'Kolom « %s » aanpassen',
|
||||||
|
'Enable time tracking for subtasks' => 'Activeer tijdschrijven voor subtaken',
|
||||||
|
'Select the new status of the subtask: "%s"' => 'Selecteer nieuwe status voor subtaak : « %s »',
|
||||||
|
'Subtask timesheet' => 'Subtaak timesheet',
|
||||||
|
'There is nothing to show.' => 'Er is niets om te laten zijn.',
|
||||||
|
'Time Tracking' => 'Tijdschrijven',
|
||||||
|
'You already have one subtask in progress' => 'U heeft al een subtaak in behandeling',
|
||||||
|
'Which parts of the project do you want to duplicate?' => 'Welke onderdelen van het project wilt u dupliceren?',
|
||||||
|
'Change dashboard view' => 'Pas dashboard aan',
|
||||||
|
'Show/hide activities' => 'Toon/verberg activiteiten',
|
||||||
|
'Show/hide projects' => 'Toon/verberg projecten',
|
||||||
|
'Show/hide subtasks' => 'Toon/verberg subtaken',
|
||||||
|
'Show/hide tasks' => 'Toon/verberg taken',
|
||||||
|
'Disable login form' => 'Schakel login scherm uit',
|
||||||
|
'Show/hide calendar' => 'Toon/verberg agenda',
|
||||||
|
'User calendar' => 'Agenda gebruiker',
|
||||||
|
'Bitbucket commit received' => 'Bitbucket commit ontvangen',
|
||||||
|
'Bitbucket webhooks' => 'Bitbucket webhooks',
|
||||||
|
'Help on Bitbucket webhooks' => 'Help bij Bitbucket webhooks',
|
||||||
|
'Start' => 'Start',
|
||||||
|
'End' => 'Eind',
|
||||||
|
'Task age in days' => 'Leeftijd taak in dagen',
|
||||||
|
'Days in this column' => 'Dagen in deze kolom',
|
||||||
|
'%dd' => '%dj',
|
||||||
|
'Add a link' => 'Link toevoegen',
|
||||||
|
'Add a new link' => 'Nieuwe link toevoegen',
|
||||||
|
'Do you really want to remove this link: "%s"?' => 'Weet u zeker dat u deze link wil verwijderen : « %s » ?',
|
||||||
|
'Do you really want to remove this link with task #%d?' => 'Weet u zeker dat u deze link met taak %d wil verwijderen?',
|
||||||
|
'Field required' => 'Veld verplicht',
|
||||||
|
'Link added successfully.' => 'Link succesvol toegevoegd.',
|
||||||
|
'Link updated successfully.' => 'Link succesvol aangepast.',
|
||||||
|
'Link removed successfully.' => 'Link succesvol verwijderd.',
|
||||||
|
'Link labels' => 'Link labels',
|
||||||
|
'Link modification' => 'Link aanpassing',
|
||||||
|
'Links' => 'Links',
|
||||||
|
'Link settings' => 'Link instellingen',
|
||||||
|
'Opposite label' => 'Tegenovergesteld label',
|
||||||
|
'Remove a link' => 'Link verwijderen',
|
||||||
|
'Task\'s links' => 'Links van taak',
|
||||||
|
'The labels must be different' => 'De labels moeten verschillend zijn',
|
||||||
|
'There is no link.' => 'Er is geen link.',
|
||||||
|
'This label must be unique' => 'Dit label moet uniek zijn',
|
||||||
|
'Unable to create your link.' => 'Link aanmaken niet gelukt.',
|
||||||
|
'Unable to update your link.' => 'Link aanpassen niet gelukt.',
|
||||||
|
'Unable to remove this link.' => 'Link verwijderen niet gelukt.',
|
||||||
|
'relates to' => 'is gerelateerd aan',
|
||||||
|
'blocks' => 'blokkeert',
|
||||||
|
'is blocked by' => 'is geblokkeerd door',
|
||||||
|
'duplicates' => 'dupliceert',
|
||||||
|
'is duplicated by' => 'is gedupliceerd',
|
||||||
|
'is a child of' => 'is een kind van',
|
||||||
|
'is a parent of' => 'is een ouder van',
|
||||||
|
'targets milestone' => 'is nodig voor milestone',
|
||||||
|
'is a milestone of' => 'is een milestone voor',
|
||||||
|
'fixes' => 'corrigeert',
|
||||||
|
'is fixed by' => 'word gecorrigeerd door',
|
||||||
|
'This task' => 'Deze taal',
|
||||||
|
'<1h' => '<1h',
|
||||||
|
'%dh' => '%dh',
|
||||||
|
'%b %e' => '%e %b',
|
||||||
|
'Expand tasks' => 'Taken uitklappen',
|
||||||
|
'Collapse tasks' => 'Taken inklappen',
|
||||||
|
'Expand/collapse tasks' => 'Taken in/uiklappen',
|
||||||
|
'Close dialog box' => 'Venster sluiten',
|
||||||
|
'Submit a form' => 'Formulier insturen',
|
||||||
|
'Board view' => 'Bord weergave',
|
||||||
|
'Keyboard shortcuts' => 'Keyboard snelkoppelingen',
|
||||||
|
'Open board switcher' => 'Open bord switcher',
|
||||||
|
'Application' => 'Applicatie',
|
||||||
|
'Filter recently updated' => 'Filter recent aangepast',
|
||||||
|
'since %B %e, %Y at %k:%M %p' => 'sinds %d/%m/%Y à %H:%M',
|
||||||
|
'More filters' => 'Meer filters',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
|
);
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Brak',
|
'None' => 'Brak',
|
||||||
'edit' => 'edytuj',
|
'edit' => 'edytuj',
|
||||||
'Edit' => 'Edytuj',
|
'Edit' => 'Edytuj',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'number.decimals_separator' => ',',
|
||||||
|
'number.thousands_separator' => ' ',
|
||||||
'None' => 'Nenhum',
|
'None' => 'Nenhum',
|
||||||
'edit' => 'editar',
|
'edit' => 'editar',
|
||||||
'Edit' => 'Editar',
|
'Edit' => 'Editar',
|
||||||
|
@ -719,19 +721,129 @@ return array(
|
||||||
'fixes' => 'corrige',
|
'fixes' => 'corrige',
|
||||||
'is fixed by' => 'foi corrigido por',
|
'is fixed by' => 'foi corrigido por',
|
||||||
'This task' => 'Esta tarefa',
|
'This task' => 'Esta tarefa',
|
||||||
// '<1h' => '',
|
'<1h' => '<1h',
|
||||||
// '%dh' => '',
|
'%dh' => '%dh',
|
||||||
// '%b %e' => '',
|
'%b %e' => '%e %b',
|
||||||
'Expand tasks' => 'Expandir tarefas',
|
'Expand tasks' => 'Expandir tarefas',
|
||||||
'Collapse tasks' => 'Contrair tarefas',
|
'Collapse tasks' => 'Contrair tarefas',
|
||||||
'Expand/collapse tasks' => 'Expandir/Contrair tarefas',
|
'Expand/collapse tasks' => 'Expandir/Contrair tarefas',
|
||||||
// 'Close dialog box' => '',
|
'Close dialog box' => 'Fechar a caixa de diálogo',
|
||||||
'Submit a form' => 'Envia o formulário',
|
'Submit a form' => 'Envia o formulário',
|
||||||
// 'Board view' => '',
|
'Board view' => 'Página do painel',
|
||||||
// 'Keyboard shortcuts' => '',
|
'Keyboard shortcuts' => 'Atalhos de teclado',
|
||||||
// 'Open board switcher' => '',
|
'Open board switcher' => 'Abrir o comutador de painel',
|
||||||
'Application' => 'Aplicação',
|
'Application' => 'Aplicação',
|
||||||
'Filter recently updated' => 'Filtro recentemente atualizado',
|
'Filter recently updated' => 'Filtro recentemente atualizado',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
'since %B %e, %Y at %k:%M %p' => 'desde o %d/%m/%Y às %H:%M',
|
||||||
'More filters' => 'Mais filtros',
|
'More filters' => 'Mais filtros',
|
||||||
|
'Compact view' => 'Vista reduzida',
|
||||||
|
'Horizontal scrolling' => 'Rolagem horizontal',
|
||||||
|
'Compact/wide view' => 'Alternar entre a vista compacta e ampliada',
|
||||||
|
'No results match:' => 'Nenhum resultado:',
|
||||||
|
'Remove hourly rate' => 'Retirar taxa horária',
|
||||||
|
'Do you really want to remove this hourly rate?' => 'Você deseja realmente remover esta taxa horária?',
|
||||||
|
'Hourly rates' => 'Taxas horárias',
|
||||||
|
'Hourly rate' => 'Taxa horária',
|
||||||
|
'Currency' => 'Moeda',
|
||||||
|
'Effective date' => 'Data efetiva',
|
||||||
|
'Add new rate' => 'Adicionar nova taxa',
|
||||||
|
'Rate removed successfully.' => 'Taxa removido com sucesso.',
|
||||||
|
'Unable to remove this rate.' => 'Impossível de remover esta taxa.',
|
||||||
|
'Unable to save the hourly rate.' => 'Impossível salvar a taxa horária.',
|
||||||
|
'Hourly rate created successfully.' => 'Taxa horária criada com sucesso.',
|
||||||
|
'Start time' => 'Horário de início',
|
||||||
|
'End time' => 'Horário de término',
|
||||||
|
'Comment' => 'comentário',
|
||||||
|
'All day' => 'Dia inteiro',
|
||||||
|
'Day' => 'Dia',
|
||||||
|
'Manage timetable' => 'Gestão dos horários',
|
||||||
|
'Overtime timetable' => 'Horas extras',
|
||||||
|
'Time off timetable' => 'Horas de ausência',
|
||||||
|
'Timetable' => 'Horários',
|
||||||
|
'Work timetable' => 'Horas trabalhadas',
|
||||||
|
'Week timetable' => 'Horário da semana',
|
||||||
|
'Day timetable' => 'Horário de un dia',
|
||||||
|
'From' => 'Desde',
|
||||||
|
'To' => 'A',
|
||||||
|
'Time slot created successfully.' => 'Intervalo de tempo criado com sucesso.',
|
||||||
|
'Unable to save this time slot.' => 'Impossível de guardar este intervalo de tempo.',
|
||||||
|
'Time slot removed successfully.' => 'Intervalo de tempo removido com sucesso.',
|
||||||
|
'Unable to remove this time slot.' => 'Impossível de remover esse intervalo de tempo.',
|
||||||
|
'Do you really want to remove this time slot?' => 'Você deseja realmente remover este intervalo de tempo?',
|
||||||
|
'Remove time slot' => 'Remover um intervalo de tempo',
|
||||||
|
'Add new time slot' => 'Adicionar um intervalo de tempo',
|
||||||
|
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Esses horários são usados quando a caixa de seleção "Dia inteiro" está marcada para Horas de ausência ou Extras',
|
||||||
|
'Files' => 'Arquivos',
|
||||||
|
'Images' => 'Imagens',
|
||||||
|
'Private project' => 'Projeto privado',
|
||||||
|
'Amount' => 'Quantia',
|
||||||
|
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
||||||
|
'Budget' => 'Orçamento',
|
||||||
|
'Budget line' => 'Rubrica orçamental',
|
||||||
|
'Budget line removed successfully.' => 'Rubrica orçamental removida com sucesso',
|
||||||
|
'Budget lines' => 'Rubricas orçamentais',
|
||||||
|
'CAD - Canadian Dollar' => 'CAD - Dólar canadense',
|
||||||
|
'CHF - Swiss Francs' => 'CHF - Francos Suíços',
|
||||||
|
'Cost' => 'Custo',
|
||||||
|
'Cost breakdown' => 'Repartição dos custos',
|
||||||
|
'Custom Stylesheet' => 'Folha de estilo personalizado',
|
||||||
|
'download' => 'baixar',
|
||||||
|
'Do you really want to remove this budget line?' => 'Você deseja realmente remover esta rubrica orçamental?',
|
||||||
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
|
'Expenses' => 'Despesas',
|
||||||
|
'GBP - British Pound' => 'GBP - Libra Esterlina',
|
||||||
|
'INR - Indian Rupee' => 'INR - Rúpia indiana',
|
||||||
|
'JPY - Japanese Yen' => 'JPY - Iene japonês',
|
||||||
|
'New budget line' => 'Nova rubrica orçamental',
|
||||||
|
'NZD - New Zealand Dollar' => 'NZD - Dólar Neozelandês',
|
||||||
|
'Remove a budget line' => 'Remover uma rubrica orçamental',
|
||||||
|
'Remove budget line' => 'Remover uma rubrica orçamental',
|
||||||
|
'RSD - Serbian dinar' => 'RSD - Dinar sérvio',
|
||||||
|
'The budget line have been created successfully.' => 'A rubrica orçamental foi criada com sucesso.',
|
||||||
|
'Unable to create the budget line.' => 'Impossível de adicionar esta rubrica orçamental.',
|
||||||
|
'Unable to remove this budget line.' => 'Impossível de remover esta rubrica orçamental.',
|
||||||
|
'USD - US Dollar' => 'USD - Dólar norte-americano',
|
||||||
|
'Remaining' => 'Restante',
|
||||||
|
'Destination column' => 'Coluna de destino',
|
||||||
|
'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um usuário',
|
||||||
|
'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída',
|
||||||
|
'Source column' => 'Coluna de origem',
|
||||||
|
'Show subtask estimates in the user calendar' => 'Mostrar o tempo estimado das subtarefas no calendário do usuário',
|
||||||
|
'Transitions' => 'Transições',
|
||||||
|
'Executer' => 'Executor(a)',
|
||||||
|
'Time spent in the column' => 'Tempo gasto na coluna',
|
||||||
|
'Task transitions' => 'Transições das tarefas',
|
||||||
|
'Task transitions export' => 'Exportação das transições das tarefas',
|
||||||
|
'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => 'Este relatório contém todos os movimentos de coluna para cada tarefa com a data, o usuário e o tempo gasto para cada transição.',
|
||||||
|
'Currency rates' => 'Taxas de câmbio das moedas estrangeiras',
|
||||||
|
'Rate' => 'Taxa',
|
||||||
|
'Change reference currency' => 'Mudar a moeda de referência',
|
||||||
|
'Add a new currency rate' => 'Adicionar uma nova taxa para uma moeda',
|
||||||
|
'Currency rates are used to calculate project budget.' => 'As taxas de câmbio são utilizadas para calcular o orçamento do projeto.',
|
||||||
|
'Reference currency' => 'Moeda de Referência',
|
||||||
|
'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.',
|
||||||
|
'Unable to add this currency rate.' => 'Impossível de adicionar essa taxa de câmbio.',
|
||||||
|
'Send notifications to a Slack channel' => 'Enviar as notificações em um canal Slack',
|
||||||
|
'Webhook URL' => 'URL do webhook',
|
||||||
|
'Help on Slack integration' => 'Ajuda na integração com o Slack',
|
||||||
|
'%s remove the assignee of the task %s' => '%s removeu a pessoa designada para a tarefa %s',
|
||||||
|
'Send notifications to Hipchat' => 'Enviar as notificações para o Hipchat',
|
||||||
|
'API URL' => 'URL da API',
|
||||||
|
'Room API ID or name' => 'Nome ou ID da sala de discussão',
|
||||||
|
'Room notification token' => 'Código de segurança da sala de discussão',
|
||||||
|
'Help on Hipchat integration' => 'Ajuda na integração com o Hipchat',
|
||||||
|
'Enable Gravatar images' => 'Ativar imagem Gravatar',
|
||||||
|
'Information' => 'Informações',
|
||||||
|
'Check two factor authentication code' => 'Verificação do código de autenticação à fator duplo',
|
||||||
|
'The two factor authentication code is not valid.' => 'O código de autenticação à fator duplo não é válido',
|
||||||
|
'The two factor authentication code is valid.' => 'O código de autenticação à fator duplo é válido',
|
||||||
|
'Code' => 'Código',
|
||||||
|
'Two factor authentication' => 'Autenticação à fator duplo',
|
||||||
|
'Enable/disable two factor authentication' => 'Ativar/Desativar autenticação à fator duplo',
|
||||||
|
'This QR code contains the key URI: ' => 'Este Código QR contém a chave URI:',
|
||||||
|
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Salve esta chave secreta no seu software TOTP (por exemplo Google Authenticator ou FreeOTP).',
|
||||||
|
'Check my code' => 'Verifique o meu código',
|
||||||
|
'Secret key: ' => 'Chave secreta:',
|
||||||
|
'Test your device' => 'Teste o seu dispositivo',
|
||||||
|
'Assign a color when the task is moved to a specific column' => 'Atribuir uma cor quando a tarefa é movida em uma coluna específica',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Отсутствует',
|
'None' => 'Отсутствует',
|
||||||
'edit' => 'изменить',
|
'edit' => 'изменить',
|
||||||
'Edit' => 'Изменить',
|
'Edit' => 'Изменить',
|
||||||
|
@ -63,7 +65,7 @@ return array(
|
||||||
'Disable' => 'Деактивировать',
|
'Disable' => 'Деактивировать',
|
||||||
'Enable' => 'Активировать',
|
'Enable' => 'Активировать',
|
||||||
'New project' => 'Новый проект',
|
'New project' => 'Новый проект',
|
||||||
'Do you really want to remove this project: "%s"?' => 'Вы точно хотите удалить этот проект? : « %s » ?',
|
'Do you really want to remove this project: "%s"?' => 'Вы точно хотите удалить проект: « %s » ?',
|
||||||
'Remove project' => 'Удалить проект',
|
'Remove project' => 'Удалить проект',
|
||||||
'Boards' => 'Доски',
|
'Boards' => 'Доски',
|
||||||
'Edit the board for "%s"' => 'Изменить доску для « %s »',
|
'Edit the board for "%s"' => 'Изменить доску для « %s »',
|
||||||
|
@ -119,7 +121,7 @@ return array(
|
||||||
'The password is required' => 'Требуется пароль',
|
'The password is required' => 'Требуется пароль',
|
||||||
'This value must be an integer' => 'Это значение должно быть целым',
|
'This value must be an integer' => 'Это значение должно быть целым',
|
||||||
'The username must be unique' => 'Требуется уникальное имя пользователя',
|
'The username must be unique' => 'Требуется уникальное имя пользователя',
|
||||||
'The username must be alphanumeric' => 'Имя пользователя должно быть букво-цифровым',
|
'The username must be alphanumeric' => 'Имя пользователя должно быть буквенно-цифровым',
|
||||||
'The user id is required' => 'Требуется ID пользователя',
|
'The user id is required' => 'Требуется ID пользователя',
|
||||||
'Passwords don\'t match' => 'Пароли не совпадают',
|
'Passwords don\'t match' => 'Пароли не совпадают',
|
||||||
'The confirmation is required' => 'Требуется подтверждение',
|
'The confirmation is required' => 'Требуется подтверждение',
|
||||||
|
@ -144,13 +146,13 @@ return array(
|
||||||
'Project removed successfully.' => 'Проект удален.',
|
'Project removed successfully.' => 'Проект удален.',
|
||||||
'Project activated successfully.' => 'Проект активирован.',
|
'Project activated successfully.' => 'Проект активирован.',
|
||||||
'Unable to activate this project.' => 'Невозможно активировать проект.',
|
'Unable to activate this project.' => 'Невозможно активировать проект.',
|
||||||
'Project disabled successfully.' => 'Проект успешно выключен.',
|
'Project disabled successfully.' => 'Проект успешно деактивирован.',
|
||||||
'Unable to disable this project.' => 'Не удалось выключить проект.',
|
'Unable to disable this project.' => 'Не удалось деактивировать проект.',
|
||||||
'Unable to open this task.' => 'Не удалось открыть задачу.',
|
'Unable to open this task.' => 'Не удалось открыть задачу.',
|
||||||
'Task opened successfully.' => 'Задача открыта.',
|
'Task opened successfully.' => 'Задача открыта.',
|
||||||
'Unable to close this task.' => 'Не удалось закрыть задачу.',
|
'Unable to close this task.' => 'Не удалось закрыть задачу.',
|
||||||
'Task closed successfully.' => 'Задача закрыта.',
|
'Task closed successfully.' => 'Задача закрыта.',
|
||||||
'Unable to update your task.' => 'Не удалось обновить вашу задачу.',
|
'Unable to update your task.' => 'Не удалось обновить задачу.',
|
||||||
'Task updated successfully.' => 'Задача обновлена.',
|
'Task updated successfully.' => 'Задача обновлена.',
|
||||||
'Unable to create your task.' => 'Не удалось создать задачу.',
|
'Unable to create your task.' => 'Не удалось создать задачу.',
|
||||||
'Task created successfully.' => 'Задача создана.',
|
'Task created successfully.' => 'Задача создана.',
|
||||||
|
@ -160,7 +162,7 @@ return array(
|
||||||
'Unable to update your user.' => 'Не удалось обновить пользователя.',
|
'Unable to update your user.' => 'Не удалось обновить пользователя.',
|
||||||
'User removed successfully.' => 'Пользователь удален.',
|
'User removed successfully.' => 'Пользователь удален.',
|
||||||
'Unable to remove this user.' => 'Не удалось удалить пользователя.',
|
'Unable to remove this user.' => 'Не удалось удалить пользователя.',
|
||||||
'Board updated successfully.' => 'Доска обновлена.',
|
'Board updated successfully.' => 'Доска успешно обновлена.',
|
||||||
'Ready' => 'Готовые',
|
'Ready' => 'Готовые',
|
||||||
'Backlog' => 'Ожидающие',
|
'Backlog' => 'Ожидающие',
|
||||||
'Work in progress' => 'В процессе',
|
'Work in progress' => 'В процессе',
|
||||||
|
@ -174,9 +176,9 @@ return array(
|
||||||
'No task' => 'Нет задачи',
|
'No task' => 'Нет задачи',
|
||||||
'Completed tasks' => 'Завершенные задачи',
|
'Completed tasks' => 'Завершенные задачи',
|
||||||
'List of projects' => 'Список проектов',
|
'List of projects' => 'Список проектов',
|
||||||
'Completed tasks for "%s"' => 'Задачи завершенные для « %s »',
|
'Completed tasks for "%s"' => 'Завершенные задачи для « %s »',
|
||||||
'%d closed tasks' => '%d завершенных задач',
|
'%d closed tasks' => '%d завершенных задач',
|
||||||
'No task for this project' => 'нет задач для этого проекта',
|
'No task for this project' => 'Нет задач для этого проекта',
|
||||||
'Public link' => 'Ссылка для просмотра',
|
'Public link' => 'Ссылка для просмотра',
|
||||||
'There is no column in your project!' => 'Нет колонки в вашем проекте!',
|
'There is no column in your project!' => 'Нет колонки в вашем проекте!',
|
||||||
'Change assignee' => 'Сменить назначенного',
|
'Change assignee' => 'Сменить назначенного',
|
||||||
|
@ -193,18 +195,18 @@ return array(
|
||||||
'Edit users access' => 'Изменить доступ пользователей',
|
'Edit users access' => 'Изменить доступ пользователей',
|
||||||
'Allow this user' => 'Разрешить этого пользователя',
|
'Allow this user' => 'Разрешить этого пользователя',
|
||||||
'Only those users have access to this project:' => 'Только эти пользователи имеют доступ к проекту:',
|
'Only those users have access to this project:' => 'Только эти пользователи имеют доступ к проекту:',
|
||||||
'Don\'t forget that administrators have access to everything.' => 'Помните, администратор имеет доступ ко всему.',
|
'Don\'t forget that administrators have access to everything.' => 'Помните, администратор имеет неограниченные права.',
|
||||||
'Revoke' => 'отозвать',
|
'Revoke' => 'Отозвать',
|
||||||
'List of authorized users' => 'Список авторизованных пользователей',
|
'List of authorized users' => 'Список авторизованных пользователей',
|
||||||
'User' => 'Пользователь',
|
'User' => 'Пользователь',
|
||||||
'Nobody have access to this project.' => 'Ни у кого нет доступа к этому проекту',
|
'Nobody have access to this project.' => 'Ни у кого нет доступа к этому проекту',
|
||||||
'You are not allowed to access to this project.' => 'Вам запрешен доступ к этому проекту.',
|
'You are not allowed to access to this project.' => 'Вам запрещен доступ к этому проекту.',
|
||||||
'Comments' => 'Комментарии',
|
'Comments' => 'Комментарии',
|
||||||
'Post comment' => 'Оставить комментарий',
|
'Post comment' => 'Оставить комментарий',
|
||||||
'Write your text in Markdown' => 'Справка по синтаксису Markdown',
|
'Write your text in Markdown' => 'Справка по синтаксису Markdown',
|
||||||
'Leave a comment' => 'Оставить комментарий 2',
|
'Leave a comment' => 'Оставить комментарий 2',
|
||||||
'Comment is required' => 'Нужен комментарий',
|
'Comment is required' => 'Нужен комментарий',
|
||||||
'Leave a description' => 'Оставьте описание',
|
'Leave a description' => 'Напишите описание',
|
||||||
'Comment added successfully.' => 'Комментарий успешно добавлен.',
|
'Comment added successfully.' => 'Комментарий успешно добавлен.',
|
||||||
'Unable to create your comment.' => 'Невозможно создать комментарий.',
|
'Unable to create your comment.' => 'Невозможно создать комментарий.',
|
||||||
'The description is required' => 'Требуется описание',
|
'The description is required' => 'Требуется описание',
|
||||||
|
@ -215,7 +217,7 @@ return array(
|
||||||
'%B %e, %Y' => '%d/%m/%Y',
|
'%B %e, %Y' => '%d/%m/%Y',
|
||||||
// '%b %e, %Y' => '',
|
// '%b %e, %Y' => '',
|
||||||
'Automatic actions' => 'Автоматические действия',
|
'Automatic actions' => 'Автоматические действия',
|
||||||
'Your automatic action have been created successfully.' => 'Автоматика настроена.',
|
'Your automatic action have been created successfully.' => 'Автоматика успешно настроена.',
|
||||||
'Unable to create your automatic action.' => 'Не удалось создать автоматизированное действие.',
|
'Unable to create your automatic action.' => 'Не удалось создать автоматизированное действие.',
|
||||||
'Remove an action' => 'Удалить действие',
|
'Remove an action' => 'Удалить действие',
|
||||||
'Unable to remove this action.' => 'Не удалось удалить действие',
|
'Unable to remove this action.' => 'Не удалось удалить действие',
|
||||||
|
@ -259,7 +261,7 @@ return array(
|
||||||
'Comment removed successfully.' => 'Комментарий удален.',
|
'Comment removed successfully.' => 'Комментарий удален.',
|
||||||
'Unable to remove this comment.' => 'Не удалось удалить этот комментарий.',
|
'Unable to remove this comment.' => 'Не удалось удалить этот комментарий.',
|
||||||
'Do you really want to remove this comment?' => 'Вы точно хотите удалить этот комментарий?',
|
'Do you really want to remove this comment?' => 'Вы точно хотите удалить этот комментарий?',
|
||||||
'Only administrators or the creator of the comment can access to this page.' => 'Только администратор или автор комментарий могут получить доступ.',
|
'Only administrators or the creator of the comment can access to this page.' => 'Только администратор и автор комментария имеют доступ к этой странице.',
|
||||||
'Details' => 'Подробности',
|
'Details' => 'Подробности',
|
||||||
'Current password for the user "%s"' => 'Текущий пароль для пользователя « %s »',
|
'Current password for the user "%s"' => 'Текущий пароль для пользователя « %s »',
|
||||||
'The current password is required' => 'Требуется текущий пароль',
|
'The current password is required' => 'Требуется текущий пароль',
|
||||||
|
@ -278,7 +280,7 @@ return array(
|
||||||
'Remember Me' => 'Запомнить меня',
|
'Remember Me' => 'Запомнить меня',
|
||||||
'Creation date' => 'Дата создания',
|
'Creation date' => 'Дата создания',
|
||||||
'Filter by user' => 'Фильтр по пользователям',
|
'Filter by user' => 'Фильтр по пользователям',
|
||||||
'Filter by due date' => 'Фильтр по сроку',
|
'Filter by due date' => 'Фильтр по дате',
|
||||||
'Everybody' => 'Все',
|
'Everybody' => 'Все',
|
||||||
'Open' => 'Открытый',
|
'Open' => 'Открытый',
|
||||||
'Closed' => 'Закрытый',
|
'Closed' => 'Закрытый',
|
||||||
|
@ -290,13 +292,13 @@ return array(
|
||||||
'Description' => 'Описание',
|
'Description' => 'Описание',
|
||||||
'%d comments' => '%d комментариев',
|
'%d comments' => '%d комментариев',
|
||||||
'%d comment' => '%d комментарий',
|
'%d comment' => '%d комментарий',
|
||||||
'Email address invalid' => 'Adresse email invalide',
|
'Email address invalid' => 'Некорректный e-mail адрес',
|
||||||
'Your Google Account is not linked anymore to your profile.' => 'Ваш аккаунт в Google больше не привязан к вашему профилю.',
|
'Your Google Account is not linked anymore to your profile.' => 'Ваш аккаунт в Google больше не привязан к вашему профилю.',
|
||||||
'Unable to unlink your Google Account.' => 'Не удалось отвязать ваш профиль от Google.',
|
'Unable to unlink your Google Account.' => 'Не удалось отвязать ваш профиль от Google.',
|
||||||
'Google authentication failed' => 'Аутентификация Google не удалась',
|
'Google authentication failed' => 'Аутентификация Google не удалась',
|
||||||
'Unable to link your Google Account.' => 'Не удалось привязать ваш профиль к Google.',
|
'Unable to link your Google Account.' => 'Не удалось привязать ваш профиль к Google.',
|
||||||
'Your Google Account is linked to your profile successfully.' => 'Ваш профиль успешно привязан к Google.',
|
'Your Google Account is linked to your profile successfully.' => 'Ваш профиль успешно привязан к Google.',
|
||||||
'Email' => 'Email',
|
'Email' => 'E-mail',
|
||||||
'Link my Google Account' => 'Привязать мой профиль к Google',
|
'Link my Google Account' => 'Привязать мой профиль к Google',
|
||||||
'Unlink my Google Account' => 'Отвязать мой профиль от Google',
|
'Unlink my Google Account' => 'Отвязать мой профиль от Google',
|
||||||
'Login with my Google Account' => 'Аутентификация через Google',
|
'Login with my Google Account' => 'Аутентификация через Google',
|
||||||
|
@ -369,7 +371,7 @@ return array(
|
||||||
'Unable to upload the file.' => 'Не удалось загрузить файл.',
|
'Unable to upload the file.' => 'Не удалось загрузить файл.',
|
||||||
'Display another project' => 'Показать другой проект',
|
'Display another project' => 'Показать другой проект',
|
||||||
'Your GitHub account was successfully linked to your profile.' => 'Ваш GitHub привязан к вашему профилю.',
|
'Your GitHub account was successfully linked to your profile.' => 'Ваш GitHub привязан к вашему профилю.',
|
||||||
'Unable to link your GitHub Account.' => 'Не удалось привязать ваш профиль к Github.',
|
'Unable to link your GitHub Account.' => 'Не удалось привязать ваш профиль к GitHub.',
|
||||||
'GitHub authentication failed' => 'Аутентификация в GitHub не удалась',
|
'GitHub authentication failed' => 'Аутентификация в GitHub не удалась',
|
||||||
'Your GitHub account is no longer linked to your profile.' => 'Ваш GitHub отвязан от вашего профиля.',
|
'Your GitHub account is no longer linked to your profile.' => 'Ваш GitHub отвязан от вашего профиля.',
|
||||||
'Unable to unlink your GitHub Account.' => 'Не удалось отвязать ваш профиль от GitHub.',
|
'Unable to unlink your GitHub Account.' => 'Не удалось отвязать ваш профиль от GitHub.',
|
||||||
|
@ -393,8 +395,8 @@ return array(
|
||||||
'Clone Project' => 'Клонировать проект',
|
'Clone Project' => 'Клонировать проект',
|
||||||
'Project cloned successfully.' => 'Проект клонирован.',
|
'Project cloned successfully.' => 'Проект клонирован.',
|
||||||
'Unable to clone this project.' => 'Не удалось клонировать проект.',
|
'Unable to clone this project.' => 'Не удалось клонировать проект.',
|
||||||
'Email notifications' => 'Уведомления по email',
|
'Email notifications' => 'Уведомления по e-mail',
|
||||||
'Enable email notifications' => 'Включить уведомления по email',
|
'Enable email notifications' => 'Включить уведомления по e-mail',
|
||||||
'Task position:' => 'Позиция задачи:',
|
'Task position:' => 'Позиция задачи:',
|
||||||
'The task #%d have been opened.' => 'Задача #%d была открыта.',
|
'The task #%d have been opened.' => 'Задача #%d была открыта.',
|
||||||
'The task #%d have been closed.' => 'Задача #%d была закрыта.',
|
'The task #%d have been closed.' => 'Задача #%d была закрыта.',
|
||||||
|
@ -428,9 +430,9 @@ return array(
|
||||||
'Active projects' => 'Активные проекты',
|
'Active projects' => 'Активные проекты',
|
||||||
'Inactive projects' => 'Неактивные проекты',
|
'Inactive projects' => 'Неактивные проекты',
|
||||||
'Public access disabled' => 'Общий доступ отключен',
|
'Public access disabled' => 'Общий доступ отключен',
|
||||||
'Do you really want to disable this project: "%s"?' => 'Вы точно хотите отключить проект: "%s"?',
|
'Do you really want to disable this project: "%s"?' => 'Вы точно хотите деактивировать проект: "%s"?',
|
||||||
'Do you really want to duplicate this project: "%s"?' => 'Вы точно хотите клонировать проект: "%s"?',
|
'Do you really want to duplicate this project: "%s"?' => 'Вы точно хотите клонировать проект: "%s"?',
|
||||||
'Do you really want to enable this project: "%s"?' => 'Вы точно хотите включить проект: "%s"?',
|
'Do you really want to enable this project: "%s"?' => 'Вы точно хотите активировать проект: "%s"?',
|
||||||
'Project activation' => 'Активация проекта',
|
'Project activation' => 'Активация проекта',
|
||||||
'Move the task to another project' => 'Переместить задачу в другой проект',
|
'Move the task to another project' => 'Переместить задачу в другой проект',
|
||||||
'Move to another project' => 'Переместить в другой проект',
|
'Move to another project' => 'Переместить в другой проект',
|
||||||
|
@ -446,7 +448,7 @@ return array(
|
||||||
'Github account linked' => 'Профиль GitHub связан',
|
'Github account linked' => 'Профиль GitHub связан',
|
||||||
'Username:' => 'Имя пользователя:',
|
'Username:' => 'Имя пользователя:',
|
||||||
'Name:' => 'Имя:',
|
'Name:' => 'Имя:',
|
||||||
'Email:' => 'Email:',
|
'Email:' => 'E-mail:',
|
||||||
'Default project:' => 'Проект по умолчанию:',
|
'Default project:' => 'Проект по умолчанию:',
|
||||||
'Notifications:' => 'Уведомления:',
|
'Notifications:' => 'Уведомления:',
|
||||||
'Notifications' => 'Уведомления',
|
'Notifications' => 'Уведомления',
|
||||||
|
@ -483,7 +485,7 @@ return array(
|
||||||
'No activity.' => 'Нет активности',
|
'No activity.' => 'Нет активности',
|
||||||
'RSS feed' => 'RSS лента',
|
'RSS feed' => 'RSS лента',
|
||||||
'%s updated a comment on the task #%d' => '%s обновил комментарий задачи #%d',
|
'%s updated a comment on the task #%d' => '%s обновил комментарий задачи #%d',
|
||||||
'%s commented on the task #%d' => '%s откомментировал задачу #%d',
|
'%s commented on the task #%d' => '%s прокомментировал задачу #%d',
|
||||||
'%s updated a subtask for the task #%d' => '%s обновил подзадачу задачи #%d',
|
'%s updated a subtask for the task #%d' => '%s обновил подзадачу задачи #%d',
|
||||||
'%s created a subtask for the task #%d' => '%s создал подзадачу для задачи #%d',
|
'%s created a subtask for the task #%d' => '%s создал подзадачу для задачи #%d',
|
||||||
'%s updated the task #%d' => '%s обновил задачу #%d',
|
'%s updated the task #%d' => '%s обновил задачу #%d',
|
||||||
|
@ -501,14 +503,14 @@ return array(
|
||||||
// 'Column Change' => '',
|
// 'Column Change' => '',
|
||||||
// 'Position Change' => '',
|
// 'Position Change' => '',
|
||||||
// 'Assignee Change' => '',
|
// 'Assignee Change' => '',
|
||||||
'New password for the user "%s"' => 'Новый пароль для пользователя %s"',
|
'New password for the user "%s"' => 'Новый пароль для пользователя "%s"',
|
||||||
'Choose an event' => 'Выберите событие',
|
'Choose an event' => 'Выберите событие',
|
||||||
'Github commit received' => 'Github: коммит получен',
|
'Github commit received' => 'GitHub: коммит получен',
|
||||||
'Github issue opened' => 'Github: новая проблема',
|
'Github issue opened' => 'GitHub: новая проблема',
|
||||||
'Github issue closed' => 'Github: проблема закрыта',
|
'Github issue closed' => 'GitHub: проблема закрыта',
|
||||||
'Github issue reopened' => 'Github: проблема переоткрыта',
|
'Github issue reopened' => 'GitHub: проблема переоткрыта',
|
||||||
'Github issue assignee change' => 'Github: сменить ответственного за проблему',
|
'Github issue assignee change' => 'GitHub: сменить ответственного за проблему',
|
||||||
'Github issue label change' => 'Github: ярлык проблемы изменен',
|
'Github issue label change' => 'GitHub: ярлык проблемы изменен',
|
||||||
'Create a task from an external provider' => 'Создать задачу из внешнего источника',
|
'Create a task from an external provider' => 'Создать задачу из внешнего источника',
|
||||||
'Change the assignee based on an external username' => 'Изменить назначенного основываясь на внешнем имени пользователя',
|
'Change the assignee based on an external username' => 'Изменить назначенного основываясь на внешнем имени пользователя',
|
||||||
'Change the category based on an external label' => 'Изменить категорию основываясь на внешнем ярлыке',
|
'Change the category based on an external label' => 'Изменить категорию основываясь на внешнем ярлыке',
|
||||||
|
@ -560,9 +562,9 @@ return array(
|
||||||
// 'Github issue comment created' => '',
|
// 'Github issue comment created' => '',
|
||||||
// 'Configure' => '',
|
// 'Configure' => '',
|
||||||
// 'Project management' => '',
|
// 'Project management' => '',
|
||||||
// 'My projects' => '',
|
'My projects' => 'Мои проекты',
|
||||||
// 'Columns' => '',
|
'Columns' => 'Колонки',
|
||||||
// 'Task' => '',
|
'Task' => 'Задача',
|
||||||
// 'Your are not member of any project.' => '',
|
// 'Your are not member of any project.' => '',
|
||||||
// 'Percentage' => '',
|
// 'Percentage' => '',
|
||||||
// 'Number of tasks' => '',
|
// 'Number of tasks' => '',
|
||||||
|
@ -570,8 +572,8 @@ return array(
|
||||||
// 'Reportings' => '',
|
// 'Reportings' => '',
|
||||||
// 'Task repartition for "%s"' => '',
|
// 'Task repartition for "%s"' => '',
|
||||||
// 'Analytics' => '',
|
// 'Analytics' => '',
|
||||||
// 'Subtask' => '',
|
'Subtask' => 'Подзадача',
|
||||||
// 'My subtasks' => '',
|
'My subtasks' => 'Мои подзадачи',
|
||||||
// 'User repartition' => '',
|
// 'User repartition' => '',
|
||||||
// 'User repartition for "%s"' => '',
|
// 'User repartition for "%s"' => '',
|
||||||
// 'Clone this project' => '',
|
// 'Clone this project' => '',
|
||||||
|
@ -646,10 +648,10 @@ return array(
|
||||||
// 'Language:' => '',
|
// 'Language:' => '',
|
||||||
// 'Timezone:' => '',
|
// 'Timezone:' => '',
|
||||||
// 'All columns' => '',
|
// 'All columns' => '',
|
||||||
// 'Calendar for "%s"' => '',
|
'Calendar for "%s"' => 'Календарь для "%s"',
|
||||||
// 'Filter by column' => '',
|
'Filter by column' => 'Фильтр по колонке',
|
||||||
// 'Filter by status' => '',
|
'Filter by status' => 'Фильтр по статусу',
|
||||||
// 'Calendar' => '',
|
'Calendar' => 'Календарь',
|
||||||
// 'Next' => '',
|
// 'Next' => '',
|
||||||
// '#%d' => '',
|
// '#%d' => '',
|
||||||
// 'Filter by color' => '',
|
// 'Filter by color' => '',
|
||||||
|
@ -686,18 +688,18 @@ return array(
|
||||||
// 'Task age in days' => '',
|
// 'Task age in days' => '',
|
||||||
// 'Days in this column' => '',
|
// 'Days in this column' => '',
|
||||||
// '%dd' => '',
|
// '%dd' => '',
|
||||||
// 'Add a link' => '',
|
'Add a link' => 'Добавить ссылку на другие задачи',
|
||||||
// 'Add a new link' => '',
|
'Add a new link' => 'Добавление новой ссылки',
|
||||||
// 'Do you really want to remove this link: "%s"?' => '',
|
'Do you really want to remove this link: "%s"?' => 'Вы уверены что хотите удалить ссылку: "%s"?',
|
||||||
// 'Do you really want to remove this link with task #%d?' => '',
|
'Do you really want to remove this link with task #%d?' => 'Вы уверены что хотите удалить ссылку вместе с задачей #%d?',
|
||||||
// 'Field required' => '',
|
'Field required' => 'Поле обязательно для заполнения',
|
||||||
// 'Link added successfully.' => '',
|
'Link added successfully.' => 'Ссылка успешно добавлена',
|
||||||
// 'Link updated successfully.' => '',
|
'Link updated successfully.' => 'Ссылка успешно обновлена',
|
||||||
// 'Link removed successfully.' => '',
|
'Link removed successfully.' => 'Ссылка успешно удалена',
|
||||||
// 'Link labels' => '',
|
'Link labels' => 'Метки для ссылки',
|
||||||
// 'Link modification' => '',
|
'Link modification' => 'Обновление ссылки',
|
||||||
// 'Links' => '',
|
'Links' => 'Ссылки',
|
||||||
// 'Link settings' => '',
|
'Link settings' => 'Настройки ссылки',
|
||||||
// 'Opposite label' => '',
|
// 'Opposite label' => '',
|
||||||
// 'Remove a link' => '',
|
// 'Remove a link' => '',
|
||||||
// 'Task\'s links' => '',
|
// 'Task\'s links' => '',
|
||||||
|
@ -707,31 +709,141 @@ return array(
|
||||||
// 'Unable to create your link.' => '',
|
// 'Unable to create your link.' => '',
|
||||||
// 'Unable to update your link.' => '',
|
// 'Unable to update your link.' => '',
|
||||||
// 'Unable to remove this link.' => '',
|
// 'Unable to remove this link.' => '',
|
||||||
// 'relates to' => '',
|
'relates to' => 'связана с',
|
||||||
// 'blocks' => '',
|
'blocks' => 'блокирует',
|
||||||
// 'is blocked by' => '',
|
'is blocked by' => 'заблокирована в',
|
||||||
// 'duplicates' => '',
|
'duplicates' => 'дублирует',
|
||||||
// 'is duplicated by' => '',
|
'is duplicated by' => 'дублирована в',
|
||||||
// 'is a child of' => '',
|
'is a child of' => 'наследник',
|
||||||
// 'is a parent of' => '',
|
'is a parent of' => 'родитель',
|
||||||
// 'targets milestone' => '',
|
'targets milestone' => 'часть этапа',
|
||||||
// 'is a milestone of' => '',
|
'is a milestone of' => '',
|
||||||
// 'fixes' => '',
|
'fixes' => 'исправляет',
|
||||||
// 'is fixed by' => '',
|
'is fixed by' => 'исправлено в',
|
||||||
// 'This task' => '',
|
'This task' => 'Эта задача',
|
||||||
// '<1h' => '',
|
// '<1h' => '',
|
||||||
// '%dh' => '',
|
// '%dh' => '',
|
||||||
// '%b %e' => '',
|
// '%b %e' => '',
|
||||||
// 'Expand tasks' => '',
|
'Expand tasks' => 'Развернуть задачи',
|
||||||
// 'Collapse tasks' => '',
|
'Collapse tasks' => 'Свернуть задачи',
|
||||||
// 'Expand/collapse tasks' => '',
|
'Expand/collapse tasks' => 'Развернуть/свернуть задачи',
|
||||||
// 'Close dialog box' => '',
|
'Close dialog box' => 'Закрыть диалог',
|
||||||
// 'Submit a form' => '',
|
'Submit a form' => 'Отправить форму',
|
||||||
// 'Board view' => '',
|
'Board view' => 'Просмотр доски',
|
||||||
// 'Keyboard shortcuts' => '',
|
'Keyboard shortcuts' => 'Горячие клавиши',
|
||||||
// 'Open board switcher' => '',
|
'Open board switcher' => 'Открыть переключатель доски',
|
||||||
// 'Application' => '',
|
'Application' => 'Приложение',
|
||||||
// 'Filter recently updated' => '',
|
'Filter recently updated' => 'Сортировать по дате обновления',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
'More filters' => 'Использовать фильтры',
|
||||||
|
'Compact view' => 'Компактный вид',
|
||||||
|
'Horizontal scrolling' => 'Горизонтальная прокрутка',
|
||||||
|
'Compact/wide view' => 'Компактный/широкий вид',
|
||||||
|
'No results match:' => 'Отсутствуют результаты:',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
849
sources/app/Locale/sr_Latn_RS/translations.php
Normal file
849
sources/app/Locale/sr_Latn_RS/translations.php
Normal file
|
@ -0,0 +1,849 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
|
'None' => 'None',
|
||||||
|
'edit' => 'izmeni',
|
||||||
|
'Edit' => 'Izmeni',
|
||||||
|
'remove' => 'ukloni',
|
||||||
|
'Remove' => 'Ukloni',
|
||||||
|
'Update' => 'Ažuriraj',
|
||||||
|
'Yes' => 'Da',
|
||||||
|
'No' => 'Ne',
|
||||||
|
'cancel' => 'odustani',
|
||||||
|
'or' => 'ili',
|
||||||
|
'Yellow' => 'Žuta',
|
||||||
|
'Blue' => 'Plava',
|
||||||
|
'Green' => 'Zelena',
|
||||||
|
'Purple' => 'Ljubičasta',
|
||||||
|
'Red' => 'Crvena',
|
||||||
|
'Orange' => 'Narandžasta',
|
||||||
|
'Grey' => 'Siva',
|
||||||
|
'Save' => 'Snimi',
|
||||||
|
'Login' => 'Prijava',
|
||||||
|
'Official website:' => 'Zvanična strana:',
|
||||||
|
'Unassigned' => 'Nedodeljen',
|
||||||
|
'View this task' => 'Pregledaj zadatak',
|
||||||
|
'Remove user' => 'Ukloni korisnika',
|
||||||
|
'Do you really want to remove this user: "%s"?' => 'Da li zaista želiš da ukloniš korisnika: "%s"?',
|
||||||
|
'New user' => 'novi korisnik',
|
||||||
|
'All users' => 'Svi korisnici',
|
||||||
|
'Username' => 'Korisnik',
|
||||||
|
'Password' => 'Lozinka',
|
||||||
|
'Default project' => 'Podrazumevani projekat',
|
||||||
|
'Administrator' => 'Administrator',
|
||||||
|
'Sign in' => 'Odjava',
|
||||||
|
'Users' => 'Korisnik',
|
||||||
|
'No user' => 'Ne',
|
||||||
|
'Forbidden' => 'Zabranjeno',
|
||||||
|
'Access Forbidden' => 'Zabranjen prostup',
|
||||||
|
'Only administrators can access to this page.' => 'Samo administrator može videti ovu stranu.',
|
||||||
|
'Edit user' => 'Izmeni korisnika',
|
||||||
|
'Logout' => 'Odjava',
|
||||||
|
'Bad username or password' => 'Loše korisničko ime ili lozinka',
|
||||||
|
'users' => 'korisnici',
|
||||||
|
'projects' => 'projekti',
|
||||||
|
'Edit project' => 'Izmeni projekat',
|
||||||
|
'Name' => 'Ime',
|
||||||
|
'Activated' => 'Aktiviran',
|
||||||
|
'Projects' => 'Projekti',
|
||||||
|
'No project' => 'Bez projekta',
|
||||||
|
'Project' => 'Projekat',
|
||||||
|
'Status' => 'Status',
|
||||||
|
'Tasks' => 'Zadatak',
|
||||||
|
'Board' => 'Tabla',
|
||||||
|
'Actions' => 'Akcje',
|
||||||
|
'Inactive' => 'Neaktivan',
|
||||||
|
'Active' => 'Aktivan',
|
||||||
|
'Column %d' => 'Kolona %d',
|
||||||
|
'Add this column' => 'Dodaj kolonu',
|
||||||
|
'%d tasks on the board' => '%d zadataka na tabli',
|
||||||
|
'%d tasks in total' => '%d zadataka ukupno',
|
||||||
|
'Unable to update this board.' => 'Nemogu da ažuriram ovu tablu.',
|
||||||
|
'Edit board' => 'Izmeni tablu',
|
||||||
|
'Disable' => 'Onemogući',
|
||||||
|
'Enable' => 'Omogući',
|
||||||
|
'New project' => 'Novi projekat',
|
||||||
|
'Do you really want to remove this project: "%s"?' => 'Da li želiš da ukloniš projekat: "%s"?',
|
||||||
|
'Remove project' => 'Ukloni projekat',
|
||||||
|
'Boards' => 'Table',
|
||||||
|
'Edit the board for "%s"' => 'Izmeni tablu za "%s"',
|
||||||
|
'All projects' => 'Svi projekti',
|
||||||
|
'Change columns' => 'Zameni kolonu',
|
||||||
|
'Add a new column' => 'Dodaj novu kolonu',
|
||||||
|
'Title' => 'Naslov',
|
||||||
|
'Add Column' => 'Dodaj kolunu',
|
||||||
|
'Project "%s"' => 'Projekt "%s"',
|
||||||
|
'Nobody assigned' => 'Niko nije dodeljen',
|
||||||
|
'Assigned to %s' => 'Dodeljen korisniku %s',
|
||||||
|
'Remove a column' => 'Ukloni kolonu',
|
||||||
|
'Remove a column from a board' => 'Ukloni kolonu sa table',
|
||||||
|
'Unable to remove this column.' => 'Nemoguće uklanjanje kolone.',
|
||||||
|
'Do you really want to remove this column: "%s"?' => 'Da li zaista želiš da ukoniš ovu kolonu: "%s"?',
|
||||||
|
'This action will REMOVE ALL TASKS associated to this column!' => 'Ova akcija BRIŠE SVE ZADATKE vezane za ovu kolonu!',
|
||||||
|
'Settings' => 'Podešavanja',
|
||||||
|
'Application settings' => 'Podešavanja aplikacije',
|
||||||
|
'Language' => 'Jezik',
|
||||||
|
'Webhook token:' => 'Token :',
|
||||||
|
'API token:' => 'Token za API',
|
||||||
|
'More information' => 'Još informacja',
|
||||||
|
'Database size:' => 'Veličina baze :',
|
||||||
|
'Download the database' => 'Preuzmi bazu',
|
||||||
|
'Optimize the database' => 'Optimizuj bazu',
|
||||||
|
'(VACUUM command)' => '(komanda VACUUM)',
|
||||||
|
'(Gzip compressed Sqlite file)' => '(Sqlite baza spakovana Gzip-om)',
|
||||||
|
'User settings' => 'Korisnička podešavanja',
|
||||||
|
'My default project:' => 'Moj podrazumevani projekat:',
|
||||||
|
'Close a task' => 'Zatvori zadatak',
|
||||||
|
'Do you really want to close this task: "%s"?' => 'Da li zaista želiš da zatvoriš ovaj zadatak: "%s"?',
|
||||||
|
'Edit a task' => 'Izmeni zadatak',
|
||||||
|
'Column' => 'Kolona',
|
||||||
|
'Color' => 'Boja',
|
||||||
|
'Assignee' => 'Dodeli',
|
||||||
|
'Create another task' => 'Dodaj zadatak',
|
||||||
|
'New task' => 'Novi zadatak',
|
||||||
|
'Open a task' => 'Otvori zadatak',
|
||||||
|
'Do you really want to open this task: "%s"?' => 'Da li zaista želiš da otvoriš zadatak: "%s"?',
|
||||||
|
'Back to the board' => 'Nazad na tablu',
|
||||||
|
'Created on %B %e, %Y at %k:%M %p' => 'Kreiran %e %B %Y o %k:%M',
|
||||||
|
'There is nobody assigned' => 'Niko nije dodeljen!',
|
||||||
|
'Column on the board:' => 'Kolona na tabli:',
|
||||||
|
'Status is open' => 'Status otvoren',
|
||||||
|
'Status is closed' => 'Status zatvoren',
|
||||||
|
'Close this task' => 'Zatvori ovaj zadatak',
|
||||||
|
'Open this task' => 'Otvori ovaj zadatak',
|
||||||
|
'There is no description.' => 'Bez opisa.',
|
||||||
|
'Add a new task' => 'Dodaj zadatak',
|
||||||
|
'The username is required' => 'Korisničko ime je obavezno',
|
||||||
|
'The maximum length is %d characters' => 'Maksimalna dužina je %d znakova',
|
||||||
|
'The minimum length is %d characters' => 'Minimalna dužina je %d znakova',
|
||||||
|
'The password is required' => 'Lozinka je obavezna',
|
||||||
|
'This value must be an integer' => 'Mora biti ceo broj',
|
||||||
|
'The username must be unique' => 'Korisničko ime mora biti jedinstveno',
|
||||||
|
'The username must be alphanumeric' => 'Korisničko ime sme sadržati samo brojeve i slova',
|
||||||
|
'The user id is required' => 'ID korisnika je obavezan',
|
||||||
|
'Passwords don\'t match' => 'Lozinke se ne podudaraju',
|
||||||
|
'The confirmation is required' => 'Potvrda je obavezna',
|
||||||
|
'The column is required' => 'Kolona je obavezna',
|
||||||
|
'The project is required' => 'Projekat je obavezan',
|
||||||
|
'The color is required' => 'Boja je obavezna',
|
||||||
|
'The id is required' => 'ID je obavezan',
|
||||||
|
'The project id is required' => 'ID projekta je obavezan',
|
||||||
|
'The project name is required' => 'Naziv projekta je obavezan',
|
||||||
|
'This project must be unique' => 'Projekat mora biti jedinstven',
|
||||||
|
'The title is required' => 'Naslov je obavezan',
|
||||||
|
'The language is required' => 'Jezik je obavezan',
|
||||||
|
'There is no active project, the first step is to create a new project.' => 'Nema aktivnih projekata. Potrebno je prvo napraviti novi projekat.',
|
||||||
|
'Settings saved successfully.' => 'Podešavanja uspešno snimljena.',
|
||||||
|
'Unable to save your settings.' => 'Nemoguće snimanje podešavanja.',
|
||||||
|
'Database optimization done.' => 'Optimizacija baze je završena.',
|
||||||
|
'Your project have been created successfully.' => 'Projekat je uspešno napravljen.',
|
||||||
|
'Unable to create your project.' => 'Nemoguće kreiranje projekta.',
|
||||||
|
'Project updated successfully.' => 'Projekt je uspešno ažuriran.',
|
||||||
|
'Unable to update this project.' => 'Nemoguće ažuriranje projekta.',
|
||||||
|
'Unable to remove this project.' => 'Nemoguće uklanjanje projekta.',
|
||||||
|
'Project removed successfully.' => 'Projekat uspešno uklonjen.',
|
||||||
|
'Project activated successfully.' => 'Projekt uspešno aktiviran.',
|
||||||
|
'Unable to activate this project.' => 'Nemoguće aktiviranje projekta.',
|
||||||
|
'Project disabled successfully.' => 'Projekat uspešno deaktiviran.',
|
||||||
|
'Unable to disable this project.' => 'nemoguće deaktiviranje projekta.',
|
||||||
|
'Unable to open this task.' => 'Nemoguće otvaranje zadatka.',
|
||||||
|
'Task opened successfully.' => 'Zadatak uspešno otvoren.',
|
||||||
|
'Unable to close this task.' => 'Nije moguće zatvaranje ovog zadatka.',
|
||||||
|
'Task closed successfully.' => 'Zadatak uspešno zatvoren.',
|
||||||
|
'Unable to update your task.' => 'Nije moguće ažuriranje zadatka.',
|
||||||
|
'Task updated successfully.' => 'Zadatak uspešno ažuriran.',
|
||||||
|
'Unable to create your task.' => 'Nije moguće kreiranje zadatka.',
|
||||||
|
'Task created successfully.' => 'Zadatak uspešno kreiran.',
|
||||||
|
'User created successfully.' => 'Korisnik uspešno kreiran',
|
||||||
|
'Unable to create your user.' => 'Nije uspelo kreiranje korisnika.',
|
||||||
|
'User updated successfully.' => 'Korisnik uspešno ažuriran.',
|
||||||
|
'Unable to update your user.' => 'Nije moguće ažuriranje korisnika.',
|
||||||
|
'User removed successfully.' => 'Korisnik uspešno uklonjen.',
|
||||||
|
'Unable to remove this user.' => 'Nije moguće uklanjanje korisnika.',
|
||||||
|
'Board updated successfully.' => 'Tabla uspešno ažurirana.',
|
||||||
|
'Ready' => 'Spreman',
|
||||||
|
'Backlog' => 'Log',
|
||||||
|
'Work in progress' => 'U radu',
|
||||||
|
'Done' => 'Gotovo',
|
||||||
|
'Application version:' => 'Verzija aplikacije:',
|
||||||
|
'Completed on %B %e, %Y at %k:%M %p' => 'Završeno u %e %B %Y o %k:%M',
|
||||||
|
'%B %e, %Y at %k:%M %p' => '%e %B %Y o %k:%M',
|
||||||
|
'Date created' => 'Kreiran dana',
|
||||||
|
'Date completed' => 'Završen dana',
|
||||||
|
'Id' => 'Id',
|
||||||
|
'No task' => 'bez zadataka',
|
||||||
|
'Completed tasks' => 'Zatvoreni zadaci',
|
||||||
|
'List of projects' => 'Spisak projekata',
|
||||||
|
'Completed tasks for "%s"' => 'zatvoreni zadaci za "%s"',
|
||||||
|
'%d closed tasks' => '%d zatvorenih zadataka',
|
||||||
|
'No task for this project' => 'Nema dodeljenih zadataka ovom projektu',
|
||||||
|
'Public link' => 'Javni link',
|
||||||
|
'There is no column in your project!' => 'Nema dodeljenih kolona ovom projektu',
|
||||||
|
'Change assignee' => 'Izmeni dodelu',
|
||||||
|
'Change assignee for the task "%s"' => 'Izmeni dodelu za ovaj zadatak "%s"',
|
||||||
|
'Timezone' => 'Vremenska zona',
|
||||||
|
'Sorry, I didn\'t find this information in my database!' => 'Na žalost, nije pronađena informacija u bazi',
|
||||||
|
'Page not found' => 'Strana nije pronađena',
|
||||||
|
'Complexity' => 'Složenost',
|
||||||
|
'limit' => 'ograničenje',
|
||||||
|
'Task limit' => 'Ograničenje zadatka',
|
||||||
|
'Task count' => 'Broj zadataka',
|
||||||
|
'This value must be greater than %d' => 'Vrednost mora biti veća od %d',
|
||||||
|
'Edit project access list' => 'Izmeni prava pristupa projektu',
|
||||||
|
'Edit users access' => 'Izmeni korisnička prava',
|
||||||
|
'Allow this user' => 'Dozvoli ovog korisnika',
|
||||||
|
'Only those users have access to this project:' => 'Samo ovi korisnici imaju pristup projektu:',
|
||||||
|
'Don\'t forget that administrators have access to everything.' => 'Zapamti: Administrator može pristupiti svemu!',
|
||||||
|
'Revoke' => 'Povuci',
|
||||||
|
'List of authorized users' => 'Spisak odobrenih korisnika',
|
||||||
|
'User' => 'Korisnik',
|
||||||
|
'Nobody have access to this project.' => 'Niko nema pristup ovom projektu',
|
||||||
|
'You are not allowed to access to this project.' => 'Nije ti dozvoljen pristup ovom projektu.',
|
||||||
|
'Comments' => 'Komentari',
|
||||||
|
'Post comment' => 'Dodaj komentar',
|
||||||
|
'Write your text in Markdown' => 'Pisanje teksta pomoću Markdown',
|
||||||
|
'Leave a comment' => 'Ostavi komentar',
|
||||||
|
'Comment is required' => 'Komentar je obavezan',
|
||||||
|
'Leave a description' => 'Dodaj opis',
|
||||||
|
'Comment added successfully.' => 'Komentar uspešno ostavljen',
|
||||||
|
'Unable to create your comment.' => 'Nemoguće kreiranje komentara',
|
||||||
|
'The description is required' => 'Opis je obavezan',
|
||||||
|
'Edit this task' => 'Izmeni ovaj zadatak',
|
||||||
|
'Due Date' => 'Termin',
|
||||||
|
'Invalid date' => 'Loš datum',
|
||||||
|
'Must be done before %B %e, %Y' => 'Termin do %e %B %Y',
|
||||||
|
'%B %e, %Y' => '%e %B %Y',
|
||||||
|
// '%b %e, %Y' => '',
|
||||||
|
'Automatic actions' => 'Automatske akcije',
|
||||||
|
'Your automatic action have been created successfully.' => 'Uspešno kreirana automatska akcija',
|
||||||
|
'Unable to create your automatic action.' => 'Nemoguće kreiranje automatske akcije',
|
||||||
|
'Remove an action' => 'Obriši akciju',
|
||||||
|
'Unable to remove this action.' => 'Nije moguće obrisati akciju',
|
||||||
|
'Action removed successfully.' => 'Akcija obrisana',
|
||||||
|
'Automatic actions for the project "%s"' => 'Akcje za automatizaciju projekta "%s"',
|
||||||
|
'Defined actions' => 'Definisane akcje',
|
||||||
|
'Add an action' => 'dodaj akcju',
|
||||||
|
'Event name' => 'Naziv događaja',
|
||||||
|
'Action name' => 'Naziv akcije',
|
||||||
|
'Action parameters' => 'Parametri akcije',
|
||||||
|
'Action' => 'Akcija',
|
||||||
|
'Event' => 'Događaj',
|
||||||
|
'When the selected event occurs execute the corresponding action.' => 'Kad se događaj desi izvrši odgovarajuću akciju',
|
||||||
|
'Next step' => 'Sledeći korak',
|
||||||
|
'Define action parameters' => 'Definiši parametre akcije',
|
||||||
|
'Save this action' => 'Snimi akciju',
|
||||||
|
'Do you really want to remove this action: "%s"?' => 'Da li da obrišem akciju "%s"?',
|
||||||
|
'Remove an automatic action' => 'Obriši automatsku akciju',
|
||||||
|
'Close the task' => 'Zatvori zadatak',
|
||||||
|
'Assign the task to a specific user' => 'Dodeli zadatak određenom korisniku',
|
||||||
|
'Assign the task to the person who does the action' => 'Dodeli zadatak korisniku koji je izvršio akciju',
|
||||||
|
'Duplicate the task to another project' => 'Kopiraj akciju u drugi projekat',
|
||||||
|
'Move a task to another column' => 'Premesti zadatak u drugu kolonu',
|
||||||
|
'Move a task to another position in the same column' => 'Promeni poziciju zadatka u istoj koloni',
|
||||||
|
'Task modification' => 'Izman zadatka',
|
||||||
|
'Task creation' => 'Kreiranje zadatka',
|
||||||
|
'Open a closed task' => 'Otvori zatvoreni zadatak',
|
||||||
|
'Closing a task' => 'Zatvaranja zadatka',
|
||||||
|
'Assign a color to a specific user' => 'Dodeli boju korisniku',
|
||||||
|
'Column title' => 'Naslov kolone',
|
||||||
|
'Position' => 'Pozicija',
|
||||||
|
'Move Up' => 'Podigni',
|
||||||
|
'Move Down' => 'Spusti',
|
||||||
|
'Duplicate to another project' => 'Kopiraj u drugi projekat',
|
||||||
|
'Duplicate' => 'Napravi kopiju',
|
||||||
|
'link' => 'link',
|
||||||
|
'Update this comment' => 'Ažuriraj komentar',
|
||||||
|
'Comment updated successfully.' => 'Komentar uspešno ažuriran.',
|
||||||
|
'Unable to update your comment.' => 'Neuspešno ažuriranje komentara.',
|
||||||
|
'Remove a comment' => 'Obriši komentar',
|
||||||
|
'Comment removed successfully.' => 'Komentar je uspešno obrisan.',
|
||||||
|
'Unable to remove this comment.' => 'Neuspešno brisanje komentara.',
|
||||||
|
'Do you really want to remove this comment?' => 'Da li da obrišem ovaj komentar?',
|
||||||
|
'Only administrators or the creator of the comment can access to this page.' => 'Samo administrator i kreator komentara mogu ga obrisati.',
|
||||||
|
'Details' => 'Detalji',
|
||||||
|
'Current password for the user "%s"' => 'Trenutna lozinka za korisnika "%s"',
|
||||||
|
'The current password is required' => 'Trenutna lozinka je obavezna',
|
||||||
|
'Wrong password' => 'Pogrešna lozinka',
|
||||||
|
'Reset all tokens' => 'Resetuj tokene',
|
||||||
|
'All tokens have been regenerated.' => 'Svi tokeni su ponovo generisani.',
|
||||||
|
'Unknown' => 'Nepoznat',
|
||||||
|
'Last logins' => 'Poslednja prijava',
|
||||||
|
'Login date' => 'Datum prijave',
|
||||||
|
'Authentication method' => 'Metod autentikacije',
|
||||||
|
'IP address' => 'IP adresa',
|
||||||
|
'User agent' => 'Browser',
|
||||||
|
'Persistent connections' => 'Stalna konekcija',
|
||||||
|
'No session.' => 'Bez sesjie',
|
||||||
|
'Expiration date' => 'Ističe',
|
||||||
|
'Remember Me' => 'Zapamti me',
|
||||||
|
'Creation date' => 'Datum kreiranja',
|
||||||
|
'Filter by user' => 'Po korisniku',
|
||||||
|
'Filter by due date' => 'Po terminu',
|
||||||
|
'Everybody' => 'Svi',
|
||||||
|
'Open' => 'Otvoreni',
|
||||||
|
'Closed' => 'Zatvoreni',
|
||||||
|
'Search' => 'Traži',
|
||||||
|
'Nothing found.' => 'Ništa nije pronađeno',
|
||||||
|
'Search in the project "%s"' => 'Traži u prijektu "%s"',
|
||||||
|
'Due date' => 'Termin',
|
||||||
|
'Others formats accepted: %s and %s' => 'Ostali formati: %s i %s',
|
||||||
|
'Description' => 'Opis',
|
||||||
|
'%d comments' => '%d Komentara',
|
||||||
|
'%d comment' => '%d Komentar',
|
||||||
|
'Email address invalid' => 'Pogrešan e-mail',
|
||||||
|
'Your Google Account is not linked anymore to your profile.' => 'Tvoj google nalog više nije povezan sa profilom',
|
||||||
|
'Unable to unlink your Google Account.' => 'Neuspešno ukidanje veze od Google naloga',
|
||||||
|
'Google authentication failed' => 'Neuspešna Google autentikacija',
|
||||||
|
'Unable to link your Google Account.' => 'Neuspešno povezivanje sa Google nalogom',
|
||||||
|
'Your Google Account is linked to your profile successfully.' => 'Vaš Google nalog je uspešno povezan sa vašim profilom',
|
||||||
|
'Email' => 'E-mail',
|
||||||
|
'Link my Google Account' => 'Poveži sa Google nalogom',
|
||||||
|
'Unlink my Google Account' => 'Ukini vezu sa Google nalogom',
|
||||||
|
'Login with my Google Account' => 'Prijavi se preko Google naloga',
|
||||||
|
'Project not found.' => 'Projekat nije pronađen.',
|
||||||
|
'Task #%d' => 'Zadatak #%d',
|
||||||
|
'Task removed successfully.' => 'Zadatak uspešno uklonjen.',
|
||||||
|
'Unable to remove this task.' => 'Nemoguće uklanjanje zadatka.',
|
||||||
|
'Remove a task' => 'Ukloni zadatak',
|
||||||
|
'Do you really want to remove this task: "%s"?' => 'Da li da obrišem zadatak "%s"?',
|
||||||
|
'Assign automatically a color based on a category' => 'Automatski dodeli boju po kategoriji',
|
||||||
|
'Assign automatically a category based on a color' => 'Automatski dodeli kategoriju po boji',
|
||||||
|
'Task creation or modification' => 'Kreiranje ili izmena zadatka',
|
||||||
|
'Category' => 'Kategorija',
|
||||||
|
'Category:' => 'Kategorija:',
|
||||||
|
'Categories' => 'Kategorije',
|
||||||
|
'Category not found.' => 'Kategorija nije pronađena',
|
||||||
|
'Your category have been created successfully.' => 'Uspešno kreirana kategorija.',
|
||||||
|
'Unable to create your category.' => 'Nije moguće kreirati kategoriju.',
|
||||||
|
'Your category have been updated successfully.' => 'Kategorija je uspešno izmenjena',
|
||||||
|
'Unable to update your category.' => 'Nemoguće izmeniti kategoriju',
|
||||||
|
'Remove a category' => 'Obriši kategoriju',
|
||||||
|
'Category removed successfully.' => 'Kategorija uspešno uklonjena.',
|
||||||
|
'Unable to remove this category.' => 'Nije moguće ukloniti kategoriju.',
|
||||||
|
'Category modification for the project "%s"' => 'Izmena kategorije za projekat "%s"',
|
||||||
|
'Category Name' => 'Naziv kategorije',
|
||||||
|
'Categories for the project "%s"' => 'Kategorije u projektu',
|
||||||
|
'Add a new category' => 'Dodaj novu kategoriju',
|
||||||
|
'Do you really want to remove this category: "%s"?' => 'Da li zaista želiš da ukloniš kategoriju: "%s"?',
|
||||||
|
'Filter by category' => 'Po kategoriji',
|
||||||
|
'All categories' => 'Sve kategorije',
|
||||||
|
'No category' => 'Bez kategorije',
|
||||||
|
'The name is required' => 'Naziv je obavezan',
|
||||||
|
'Remove a file' => 'Ukloni fajl',
|
||||||
|
'Unable to remove this file.' => 'Fajl nije moguće ukloniti.',
|
||||||
|
'File removed successfully.' => 'Uspešno uklonjen fajl.',
|
||||||
|
'Attach a document' => 'Prikači dokument',
|
||||||
|
'Do you really want to remove this file: "%s"?' => 'Da li da uklonim fajl: "%s"?',
|
||||||
|
'open' => 'otvori',
|
||||||
|
'Attachments' => 'Prilozi',
|
||||||
|
'Edit the task' => 'Izmena Zadatka',
|
||||||
|
'Edit the description' => 'Izmena opisa',
|
||||||
|
'Add a comment' => 'Dodaj komentar',
|
||||||
|
'Edit a comment' => 'Izmeni komentar',
|
||||||
|
'Summary' => 'Pregled',
|
||||||
|
'Time tracking' => 'Praćenje vremena',
|
||||||
|
'Estimate:' => 'Procena:',
|
||||||
|
'Spent:' => 'Potrošeno:',
|
||||||
|
'Do you really want to remove this sub-task?' => 'Da li da uklonim pod-zdadatak?',
|
||||||
|
'Remaining:' => 'Preostalo:',
|
||||||
|
'hours' => 'sati',
|
||||||
|
'spent' => 'potrošeno',
|
||||||
|
'estimated' => 'procenjeno',
|
||||||
|
'Sub-Tasks' => 'Pod-zadaci',
|
||||||
|
'Add a sub-task' => 'Dodaj pod-zadatak',
|
||||||
|
'Original estimate' => 'Originalna procena',
|
||||||
|
'Create another sub-task' => 'Dodaj novi pod-zadatak',
|
||||||
|
'Time spent' => 'Utrošeno vreme',
|
||||||
|
'Edit a sub-task' => 'Izmeni pod-zadatak',
|
||||||
|
'Remove a sub-task' => 'Ukloni pod-zadatak',
|
||||||
|
'The time must be a numeric value' => 'Vreme mora biti broj',
|
||||||
|
'Todo' => 'Za rad',
|
||||||
|
'In progress' => 'U radu',
|
||||||
|
'Sub-task removed successfully.' => 'Pod-zadatak uspešno uklonjen.',
|
||||||
|
'Unable to remove this sub-task.' => 'Nie można usunąć tego pod-zadania.',
|
||||||
|
'Sub-task updated successfully.' => 'Pod-zadatak zaktualizowane pomyślnie.',
|
||||||
|
'Unable to update your sub-task.' => 'Nie można zaktalizować tego pod-zadania.',
|
||||||
|
'Unable to create your sub-task.' => 'Nie można utworzyć tego pod-zadania.',
|
||||||
|
'Sub-task added successfully.' => 'Pod-zadatak utworzone pomyślnie',
|
||||||
|
'Maximum size: ' => 'Maksimalna veličina: ',
|
||||||
|
'Unable to upload the file.' => 'Nije moguće snimiti fajl.',
|
||||||
|
'Display another project' => 'Prikaži drugi projekat',
|
||||||
|
'Your GitHub account was successfully linked to your profile.' => 'Konto Github podłączone pomyślnie.',
|
||||||
|
'Unable to link your GitHub Account.' => 'Nie można połączyć z kontem Github.',
|
||||||
|
'GitHub authentication failed' => 'Autentykacja Github nieudana',
|
||||||
|
'Your GitHub account is no longer linked to your profile.' => 'Konto Github nie jest już podłączone do twojego profilu.',
|
||||||
|
'Unable to unlink your GitHub Account.' => 'Nie można odłączyć konta Github.',
|
||||||
|
'Login with my GitHub Account' => 'Zaloguj przy użyciu konta Github',
|
||||||
|
'Link my GitHub Account' => 'Podłącz konto Github',
|
||||||
|
'Unlink my GitHub Account' => 'Odłącz konto Github',
|
||||||
|
'Created by %s' => 'Kreirao %s',
|
||||||
|
'Last modified on %B %e, %Y at %k:%M %p' => 'Poslednja izmena %e %B %Y o %k:%M',
|
||||||
|
'Tasks Export' => 'Izvoz zadataka',
|
||||||
|
'Tasks exportation for "%s"' => 'Izvoz zadataka za "%s"',
|
||||||
|
'Start Date' => 'Početni datum',
|
||||||
|
'End Date' => 'Krajni datum',
|
||||||
|
'Execute' => 'Izvrši',
|
||||||
|
'Task Id' => 'Identifikator Zadatka',
|
||||||
|
'Creator' => 'Autor',
|
||||||
|
'Modification date' => 'Datum izmene',
|
||||||
|
'Completion date' => 'Datum kompletiranja',
|
||||||
|
'Webhook URL for task creation' => 'Webhook URL zadatka za kreiranje',
|
||||||
|
'Webhook URL for task modification' => 'Webhook URL zadatka za izmenu',
|
||||||
|
'Clone' => 'Iskopiraj',
|
||||||
|
'Clone Project' => 'Iskopiraj projekat',
|
||||||
|
'Project cloned successfully.' => 'Projekat uspešno iskopiran.',
|
||||||
|
'Unable to clone this project.' => 'Nije moguće iskopirati projekat.',
|
||||||
|
'Email notifications' => 'Obaveštenje e-mailom',
|
||||||
|
'Enable email notifications' => 'Omogući obaveštenja e-mailom',
|
||||||
|
'Task position:' => 'Pozicija zadatka:',
|
||||||
|
'The task #%d have been opened.' => 'Zadatak #%d je otvoren.',
|
||||||
|
'The task #%d have been closed.' => 'Zadatak #$d je zatvoren.',
|
||||||
|
'Sub-task updated' => 'Pod-zadatak izmenjen',
|
||||||
|
'Title:' => 'Naslov:',
|
||||||
|
// 'Status:' => '',
|
||||||
|
'Assignee:' => 'Dodeli:',
|
||||||
|
'Time tracking:' => 'Praćenje vremena: ',
|
||||||
|
'New sub-task' => 'Novi Pod-zadatak',
|
||||||
|
'New attachment added "%s"' => 'Novi prilog ubačen "%s"',
|
||||||
|
'Comment updated' => 'Komentar izmenjen',
|
||||||
|
'New comment posted by %s' => 'Novi komentar ostavio %s',
|
||||||
|
'List of due tasks for the project "%s"' => 'Spisak dospelih zadataka za projekat "%s"',
|
||||||
|
// 'New attachment' => '',
|
||||||
|
// 'New comment' => '',
|
||||||
|
// 'New subtask' => '',
|
||||||
|
// 'Subtask updated' => '',
|
||||||
|
// 'Task updated' => '',
|
||||||
|
'Task closed' => 'Zadatak je zatvoren',
|
||||||
|
'Task opened' => 'Zadatak je otvoren',
|
||||||
|
'[%s][Due tasks]' => '[%s][Dospeli zadaci]',
|
||||||
|
'[Kanboard] Notification' => '[Kanboard] Obaveštenja',
|
||||||
|
'I want to receive notifications only for those projects:' => 'Želim obaveštenja samo za ovaj projekat:',
|
||||||
|
'view the task on Kanboard' => 'Pregledaj zadatke',
|
||||||
|
'Public access' => 'Javni pristup',
|
||||||
|
'Category management' => 'Uređivanje kategorija',
|
||||||
|
'User management' => 'Uređivanje korisnika',
|
||||||
|
'Active tasks' => 'Aktivni zadaci',
|
||||||
|
'Disable public access' => 'Zabrani javni pristup',
|
||||||
|
'Enable public access' => 'Dozvoli javni pristup',
|
||||||
|
'Active projects' => 'Aktivni projekti',
|
||||||
|
'Inactive projects' => 'Neaktivni projekti',
|
||||||
|
'Public access disabled' => 'Javni pristup onemogućen!',
|
||||||
|
'Do you really want to disable this project: "%s"?' => 'Da li zaista želiš da deaktiviraš projekat: "%s"?',
|
||||||
|
'Do you really want to duplicate this project: "%s"?' => 'Da li da napravim kopiju ovog projekta: "%s"?',
|
||||||
|
'Do you really want to enable this project: "%s"?' => 'Da li zaista želiš da aktiviraš projekat: "%s"?',
|
||||||
|
'Project activation' => 'Aktivacija projekta',
|
||||||
|
'Move the task to another project' => 'Premesti zadatak u drugi projekat',
|
||||||
|
'Move to another project' => 'Premesti u drugi projekat',
|
||||||
|
'Do you really want to duplicate this task?' => 'Da li da napravim kopiju ovog projekta: "%s"?',
|
||||||
|
'Duplicate a task' => 'Kopiraj zadatak',
|
||||||
|
'External accounts' => 'Spoljni nalozi',
|
||||||
|
'Account type' => 'Tip naloga',
|
||||||
|
'Local' => 'Lokalno',
|
||||||
|
'Remote' => 'Udaljno',
|
||||||
|
'Enabled' => 'Omogući',
|
||||||
|
'Disabled' => 'Onemogući',
|
||||||
|
'Google account linked' => 'Połączone konto Google',
|
||||||
|
'Github account linked' => 'Połączone konto Github',
|
||||||
|
'Username:' => 'Korisničko ime:',
|
||||||
|
'Name:' => 'Ime i Prezime',
|
||||||
|
'Email:' => 'Email: ',
|
||||||
|
'Default project:' => 'Osnovni projekat:',
|
||||||
|
'Notifications:' => 'Obaveštenja: ',
|
||||||
|
'Notifications' => 'Obaveštenja',
|
||||||
|
'Group:' => 'Grupa:',
|
||||||
|
'Regular user' => 'Standardni korisnik',
|
||||||
|
'Account type:' => 'Vrsta naloga:',
|
||||||
|
'Edit profile' => 'Izmeni profil',
|
||||||
|
'Change password' => 'Izmeni lozinku',
|
||||||
|
'Password modification' => 'Izmena lozinke',
|
||||||
|
'External authentications' => 'Spoljne akcije',
|
||||||
|
'Google Account' => 'Google nalog',
|
||||||
|
'Github Account' => 'Github nalog',
|
||||||
|
'Never connected.' => 'Bez konekcija.',
|
||||||
|
'No account linked.' => 'Bez povezanih naloga.',
|
||||||
|
'Account linked.' => 'Nalog povezan.',
|
||||||
|
'No external authentication enabled.' => 'Bez omogućenih spoljnih autentikacija.',
|
||||||
|
'Password modified successfully.' => 'Uspešna izmena lozinke.',
|
||||||
|
'Unable to change the password.' => 'Nije moguće izmeniti lozinku.',
|
||||||
|
'Change category for the task "%s"' => 'Izmeni kategoriju zadatka "%s"',
|
||||||
|
'Change category' => 'Izmeni kategoriju',
|
||||||
|
'%s updated the task %s' => '%s izmeni zadatak %s',
|
||||||
|
'%s opened the task %s' => '%s aktivni zadaci %s',
|
||||||
|
'%s moved the task %s to the position #%d in the column "%s"' => '%s premešten zadatak %s na poziciju #%d u koloni "%s"',
|
||||||
|
'%s moved the task %s to the column "%s"' => '%s premešten zadatak %s u kolonu "%s"',
|
||||||
|
'%s created the task %s' => '%s kreirao zadatak %s',
|
||||||
|
'%s closed the task %s' => '%s zatvorio zadatak %s',
|
||||||
|
'%s created a subtask for the task %s' => '%s kreiran pod-zadatak zadatka %s',
|
||||||
|
'%s updated a subtask for the task %s' => '%s izmenjen pod-zadatak zadatka %s',
|
||||||
|
'Assigned to %s with an estimate of %s/%sh' => 'Dodeljen korisniku %s uz procenu vremena %s/%sh',
|
||||||
|
'Not assigned, estimate of %sh' => 'Ne dodeljen, procenjeno vreme %sh',
|
||||||
|
'%s updated a comment on the task %s' => '%s izmenjen komentar zadatka %s',
|
||||||
|
'%s commented the task %s' => '%s komentarisao zadatak %s',
|
||||||
|
'%s\'s activity' => 'Aktivnosti %s',
|
||||||
|
'No activity.' => 'Bez aktivnosti.',
|
||||||
|
'RSS feed' => 'RSS kanal',
|
||||||
|
'%s updated a comment on the task #%d' => '%s izmenjen komentar zadatka #%d',
|
||||||
|
'%s commented on the task #%d' => '%s komentarisao zadatak #%d',
|
||||||
|
'%s updated a subtask for the task #%d' => '%s izmenjen pod-zadatak zadatka #%d',
|
||||||
|
'%s created a subtask for the task #%d' => '%s kreirao pod-zadatak zadatka #%d',
|
||||||
|
'%s updated the task #%d' => '%s izmenjen zadatak #%d',
|
||||||
|
'%s created the task #%d' => '%s kreirao zadatak #%d',
|
||||||
|
'%s closed the task #%d' => '%s zatvorio zadatak #%d',
|
||||||
|
'%s open the task #%d' => '%s otvorio zadatak #%d',
|
||||||
|
'%s moved the task #%d to the column "%s"' => '%s premestio zadatak #%d u kolonu "%s"',
|
||||||
|
'%s moved the task #%d to the position %d in the column "%s"' => '%s premestio zadatak #%d na pozycję %d w kolmnie "%s"',
|
||||||
|
'Activity' => 'Aktivnosti',
|
||||||
|
'Default values are "%s"' => 'Osnovne vrednosti su: "%s"',
|
||||||
|
'Default columns for new projects (Comma-separated)' => 'Osnovne kolone za novi projekat (Odvojeni zarezom)',
|
||||||
|
'Task assignee change' => 'Zmień osobę odpowiedzialną',
|
||||||
|
'%s change the assignee of the task #%d to %s' => '%s zamena dodele za zadatak #%d na %s',
|
||||||
|
'%s changed the assignee of the task %s to %s' => '%s zamena dodele za zadatak %s na %s',
|
||||||
|
// 'Column Change' => '',
|
||||||
|
// 'Position Change' => '',
|
||||||
|
// 'Assignee Change' => '',
|
||||||
|
'New password for the user "%s"' => 'Nova lozinka za korisnika "%s"',
|
||||||
|
'Choose an event' => 'Izaberi događaj',
|
||||||
|
// 'Github commit received' => '',
|
||||||
|
// 'Github issue opened' => '',
|
||||||
|
// 'Github issue closed' => '',
|
||||||
|
// 'Github issue reopened' => '',
|
||||||
|
// 'Github issue assignee change' => '',
|
||||||
|
// 'Github issue label change' => '',
|
||||||
|
'Create a task from an external provider' => 'Kreiraj zadatak preko posrednika',
|
||||||
|
'Change the assignee based on an external username' => 'Zmień osobę odpowiedzialną na podstawie zewnętrznej nazwy użytkownika',
|
||||||
|
'Change the category based on an external label' => 'Zmień kategorię na podstawie zewnętrzenj etykiety',
|
||||||
|
// 'Reference' => '',
|
||||||
|
// 'Reference: %s' => '',
|
||||||
|
'Label' => 'Etikieta',
|
||||||
|
'Database' => 'Baza',
|
||||||
|
'About' => 'Informacje',
|
||||||
|
'Database driver:' => 'Database driver:',
|
||||||
|
'Board settings' => 'Podešavanje table',
|
||||||
|
'URL and token' => 'URL i token',
|
||||||
|
// 'Webhook settings' => '',
|
||||||
|
'URL for task creation:' => 'URL za kreiranje zadataka',
|
||||||
|
'Reset token' => 'Resetuj token',
|
||||||
|
// 'API endpoint:' => '',
|
||||||
|
'Refresh interval for private board' => 'Interval osvežavanja privatnih tabli',
|
||||||
|
'Refresh interval for public board' => 'Interval osvežavanja javnih tabli',
|
||||||
|
'Task highlight period' => 'Task highlight period',
|
||||||
|
// 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => '',
|
||||||
|
// 'Frequency in second (60 seconds by default)' => '',
|
||||||
|
// 'Frequency in second (0 to disable this feature, 10 seconds by default)' => '',
|
||||||
|
'Application URL' => 'Adres URL aplikacji',
|
||||||
|
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Primer: http://example.kanboard.net/ (koristi se u obaveštenjima putem mail-a)',
|
||||||
|
'Token regenerated.' => 'Token wygenerowany ponownie.',
|
||||||
|
'Date format' => 'Format daty',
|
||||||
|
'ISO format is always accepted, example: "%s" and "%s"' => 'Format ISO je uvek prihvatljiv, primer: "%s", "%s"',
|
||||||
|
'New private project' => 'Novi privatni projekat',
|
||||||
|
'This project is private' => 'Ovaj projekat je privatan',
|
||||||
|
'Type here to create a new sub-task' => 'Kucaj ovde za kreiranje novog pod-zadatka',
|
||||||
|
'Add' => 'Dodaj',
|
||||||
|
'Estimated time: %s hours' => 'Procenjeno vreme: %s godzin',
|
||||||
|
'Time spent: %s hours' => 'Utrošeno vreme: %s godzin',
|
||||||
|
'Started on %B %e, %Y' => 'Započeto dana %e %B %Y',
|
||||||
|
'Start date' => 'Datum početka',
|
||||||
|
'Time estimated' => 'Procenjeno vreme',
|
||||||
|
'There is nothing assigned to you.' => 'Ništa vam nije dodeljeno',
|
||||||
|
'My tasks' => 'Moji zadaci',
|
||||||
|
'Activity stream' => 'Spisak aktinosti',
|
||||||
|
'Dashboard' => 'Panel',
|
||||||
|
'Confirmation' => 'Potvrda',
|
||||||
|
'Allow everybody to access to this project' => 'Dozvoli svima pristup projektu',
|
||||||
|
'Everybody have access to this project.' => 'Svima je dozvoljen pristup.',
|
||||||
|
// 'Webhooks' => '',
|
||||||
|
// 'API' => '',
|
||||||
|
'Integration' => 'Integracja',
|
||||||
|
// 'Github webhooks' => '',
|
||||||
|
// 'Help on Github webhooks' => '',
|
||||||
|
// 'Create a comment from an external provider' => '',
|
||||||
|
// 'Github issue comment created' => '',
|
||||||
|
'Configure' => 'Podesi',
|
||||||
|
'Project management' => 'Uređivanje projekata',
|
||||||
|
'My projects' => 'Moji projekti',
|
||||||
|
'Columns' => 'Kolone',
|
||||||
|
'Task' => 'Zadaci',
|
||||||
|
'Your are not member of any project.' => 'Nisi član ni jednog projekta',
|
||||||
|
'Percentage' => 'Procenat',
|
||||||
|
'Number of tasks' => 'Broj zadataka',
|
||||||
|
'Task distribution' => 'Podela zadataka',
|
||||||
|
'Reportings' => 'Izveštaji',
|
||||||
|
'Task repartition for "%s"' => 'Zaduženja zadataka za "%s"',
|
||||||
|
'Analytics' => 'Analiza',
|
||||||
|
'Subtask' => 'Pod-zadatak',
|
||||||
|
'My subtasks' => 'Moji pod-zadaci',
|
||||||
|
'User repartition' => 'Zaduženja korisnika',
|
||||||
|
'User repartition for "%s"' => 'Zaduženja korisnika za "%s"',
|
||||||
|
'Clone this project' => 'Kopiraj projekat',
|
||||||
|
'Column removed successfully.' => 'Kolumna usunięta pomyslnie.',
|
||||||
|
'Edit Project' => 'Izmeni projekat',
|
||||||
|
// 'Github Issue' => '',
|
||||||
|
'Not enough data to show the graph.' => 'Nedovoljno podataka za grafikon.',
|
||||||
|
'Previous' => 'Prethodni',
|
||||||
|
'The id must be an integer' => 'ID musi być liczbą całkowitą',
|
||||||
|
'The project id must be an integer' => 'ID projektu musi być liczbą całkowitą',
|
||||||
|
'The status must be an integer' => 'Status musi być liczbą całkowitą',
|
||||||
|
'The subtask id is required' => 'ID pod-zadatak jest wymagane',
|
||||||
|
'The subtask id must be an integer' => 'ID pod-zadania musi być liczbą całkowitą',
|
||||||
|
'The task id is required' => 'ID zadania jest wymagane',
|
||||||
|
'The task id must be an integer' => 'ID zadatka mora biti broj',
|
||||||
|
'The user id must be an integer' => 'ID korisnika mora biti broj',
|
||||||
|
'This value is required' => 'Vrednost je obavezna',
|
||||||
|
'This value must be numeric' => 'Vrednost mora biti broj',
|
||||||
|
'Unable to create this task.' => 'Nije moguće kreirati zadatak.',
|
||||||
|
'Cumulative flow diagram' => 'Zbirni dijagram toka',
|
||||||
|
'Cumulative flow diagram for "%s"' => 'Zbirni dijagram toka za "%s"',
|
||||||
|
'Daily project summary' => 'Zbirni pregled po danima',
|
||||||
|
'Daily project summary export' => 'Izvoz zbirnog pregleda po danima',
|
||||||
|
'Daily project summary export for "%s"' => 'Izvoz zbirnig pregleda po danima za "%s"',
|
||||||
|
'Exports' => 'Izvoz',
|
||||||
|
// 'This export contains the number of tasks per column grouped per day.' => '',
|
||||||
|
'Nothing to preview...' => 'Ništa za prikazivanje...',
|
||||||
|
'Preview' => 'Pregled',
|
||||||
|
'Write' => 'Piši',
|
||||||
|
'Active swimlanes' => 'Aktivni razdelnik',
|
||||||
|
'Add a new swimlane' => 'Dodaj razdelnik',
|
||||||
|
'Change default swimlane' => 'Zameni osnovni razdelnik',
|
||||||
|
'Default swimlane' => 'Osnovni razdelnik',
|
||||||
|
'Do you really want to remove this swimlane: "%s"?' => 'Da li da uklonim razdelnik: "%s"?',
|
||||||
|
'Inactive swimlanes' => 'Neaktivni razdelniki',
|
||||||
|
'Set project manager' => 'Podesi menadžera projekta',
|
||||||
|
'Set project member' => 'Podesi učesnika projekat',
|
||||||
|
'Remove a swimlane' => 'Ukloni razdelnik',
|
||||||
|
'Rename' => 'Preimenuj',
|
||||||
|
'Show default swimlane' => 'Prikaži osnovni razdelnik',
|
||||||
|
'Swimlane modification for the project "%s"' => 'Izmena razdelnika za projekat "%s"',
|
||||||
|
'Swimlane not found.' => 'Razdelnik nije pronađen.',
|
||||||
|
'Swimlane removed successfully.' => 'Razdelnik uspešno uklonjen.',
|
||||||
|
'Swimlanes' => 'Razdelnici',
|
||||||
|
'Swimlane updated successfully.' => 'Razdelnik zaktualizowany pomyślnie.',
|
||||||
|
// 'The default swimlane have been updated successfully.' => '',
|
||||||
|
// 'Unable to create your swimlane.' => '',
|
||||||
|
// 'Unable to remove this swimlane.' => '',
|
||||||
|
// 'Unable to update this swimlane.' => '',
|
||||||
|
'Your swimlane have been created successfully.' => 'Razdelnik je uspešno kreiran.',
|
||||||
|
'Example: "Bug, Feature Request, Improvement"' => 'Npr: "Greška, Zahtev za izmenama, Poboljšanje"',
|
||||||
|
'Default categories for new projects (Comma-separated)' => 'Osnovne kategorije za projekat',
|
||||||
|
// 'Gitlab commit received' => '',
|
||||||
|
// 'Gitlab issue opened' => '',
|
||||||
|
// 'Gitlab issue closed' => '',
|
||||||
|
// 'Gitlab webhooks' => '',
|
||||||
|
// 'Help on Gitlab webhooks' => '',
|
||||||
|
'Integrations' => 'Integracje',
|
||||||
|
'Integration with third-party services' => 'Integracja sa uslugama spoljnih servisa',
|
||||||
|
'Role for this project' => 'Uloga u ovom projektu',
|
||||||
|
'Project manager' => 'Manadžer projekta',
|
||||||
|
'Project member' => 'Učesnik projekta',
|
||||||
|
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
|
||||||
|
// 'Gitlab Issue' => '',
|
||||||
|
'Subtask Id' => 'ID pod-zadania',
|
||||||
|
'Subtasks' => 'Pod-zadataka',
|
||||||
|
'Subtasks Export' => 'Eksport pod-zadań',
|
||||||
|
'Subtasks exportation for "%s"' => 'Izvoz pod-zadań dla "%s"',
|
||||||
|
'Task Title' => 'Naslov zadatka',
|
||||||
|
'Untitled' => 'Bez naslova',
|
||||||
|
'Application default' => 'Postavke aplikacje',
|
||||||
|
'Language:' => 'Jezik:',
|
||||||
|
'Timezone:' => 'Vremenska zona:',
|
||||||
|
'All columns' => 'Sve kolone',
|
||||||
|
'Calendar for "%s"' => 'Kalendar za "%s"',
|
||||||
|
'Filter by column' => 'Po koloni',
|
||||||
|
'Filter by status' => 'Po statusu',
|
||||||
|
'Calendar' => 'Kalendar',
|
||||||
|
'Next' => 'Sledeći',
|
||||||
|
// '#%d' => '',
|
||||||
|
'Filter by color' => 'Po boji',
|
||||||
|
'Filter by swimlane' => 'Po razdelniku',
|
||||||
|
'All swimlanes' => 'Svi razdelniki',
|
||||||
|
'All colors' => 'Sve boje',
|
||||||
|
'All status' => 'Svi statusi',
|
||||||
|
'Add a comment logging moving the task between columns' => 'Dodaj logovanje premeštanja zadataka po kolonama',
|
||||||
|
'Moved to column %s' => 'Premešten u kolonu %s',
|
||||||
|
// 'Change description' => '',
|
||||||
|
'User dashboard' => 'Korisnički panel',
|
||||||
|
// 'Allow only one subtask in progress at the same time for a user' => '',
|
||||||
|
// 'Edit column "%s"' => '',
|
||||||
|
// 'Enable time tracking for subtasks' => '',
|
||||||
|
// 'Select the new status of the subtask: "%s"' => '',
|
||||||
|
// 'Subtask timesheet' => '',
|
||||||
|
'There is nothing to show.' => 'Nema podataka',
|
||||||
|
'Time Tracking' => 'Praćenje vremena',
|
||||||
|
// 'You already have one subtask in progress' => '',
|
||||||
|
'Which parts of the project do you want to duplicate?' => 'Koje delove projekta želite da kopirate',
|
||||||
|
// 'Change dashboard view' => '',
|
||||||
|
// 'Show/hide activities' => '',
|
||||||
|
// 'Show/hide projects' => '',
|
||||||
|
// 'Show/hide subtasks' => '',
|
||||||
|
// 'Show/hide tasks' => '',
|
||||||
|
// 'Disable login form' => '',
|
||||||
|
// 'Show/hide calendar' => '',
|
||||||
|
// 'User calendar' => '',
|
||||||
|
// 'Bitbucket commit received' => '',
|
||||||
|
// 'Bitbucket webhooks' => '',
|
||||||
|
// 'Help on Bitbucket webhooks' => '',
|
||||||
|
// 'Start' => '',
|
||||||
|
// 'End' => '',
|
||||||
|
// 'Task age in days' => '',
|
||||||
|
// 'Days in this column' => '',
|
||||||
|
// '%dd' => '',
|
||||||
|
'Add a link' => 'Dodaj link',
|
||||||
|
// 'Add a new link' => '',
|
||||||
|
// 'Do you really want to remove this link: "%s"?' => '',
|
||||||
|
// 'Do you really want to remove this link with task #%d?' => '',
|
||||||
|
// 'Field required' => '',
|
||||||
|
// 'Link added successfully.' => '',
|
||||||
|
// 'Link updated successfully.' => '',
|
||||||
|
// 'Link removed successfully.' => '',
|
||||||
|
// 'Link labels' => '',
|
||||||
|
// 'Link modification' => '',
|
||||||
|
// 'Links' => '',
|
||||||
|
// 'Link settings' => '',
|
||||||
|
// 'Opposite label' => '',
|
||||||
|
// 'Remove a link' => '',
|
||||||
|
// 'Task\'s links' => '',
|
||||||
|
// 'The labels must be different' => '',
|
||||||
|
// 'There is no link.' => '',
|
||||||
|
// 'This label must be unique' => '',
|
||||||
|
// 'Unable to create your link.' => '',
|
||||||
|
// 'Unable to update your link.' => '',
|
||||||
|
// 'Unable to remove this link.' => '',
|
||||||
|
// 'relates to' => '',
|
||||||
|
// 'blocks' => '',
|
||||||
|
// 'is blocked by' => '',
|
||||||
|
// 'duplicates' => '',
|
||||||
|
// 'is duplicated by' => '',
|
||||||
|
// 'is a child of' => '',
|
||||||
|
// 'is a parent of' => '',
|
||||||
|
// 'targets milestone' => '',
|
||||||
|
// 'is a milestone of' => '',
|
||||||
|
// 'fixes' => '',
|
||||||
|
// 'is fixed by' => '',
|
||||||
|
// 'This task' => '',
|
||||||
|
// '<1h' => '',
|
||||||
|
// '%dh' => '',
|
||||||
|
// '%b %e' => '',
|
||||||
|
// 'Expand tasks' => '',
|
||||||
|
// 'Collapse tasks' => '',
|
||||||
|
// 'Expand/collapse tasks' => '',
|
||||||
|
// 'Close dialog box' => '',
|
||||||
|
// 'Submit a form' => '',
|
||||||
|
// 'Board view' => '',
|
||||||
|
// 'Keyboard shortcuts' => '',
|
||||||
|
// 'Open board switcher' => '',
|
||||||
|
// 'Application' => '',
|
||||||
|
// 'Filter recently updated' => '',
|
||||||
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
|
);
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'Ingen',
|
'None' => 'Ingen',
|
||||||
'edit' => 'redigera',
|
'edit' => 'redigera',
|
||||||
'Edit' => 'Redigera',
|
'Edit' => 'Redigera',
|
||||||
|
@ -408,13 +410,13 @@ return array(
|
||||||
'Comment updated' => 'Kommentaren har uppdaterats',
|
'Comment updated' => 'Kommentaren har uppdaterats',
|
||||||
'New comment posted by %s' => 'Ny kommentar postad av %s',
|
'New comment posted by %s' => 'Ny kommentar postad av %s',
|
||||||
'List of due tasks for the project "%s"' => 'Lista med uppgifter för projektet "%s"',
|
'List of due tasks for the project "%s"' => 'Lista med uppgifter för projektet "%s"',
|
||||||
// 'New attachment' => '',
|
'New attachment' => 'Ny bifogning',
|
||||||
// 'New comment' => '',
|
'New comment' => 'Ny kommentar',
|
||||||
// 'New subtask' => '',
|
'New subtask' => 'Ny deluppgift',
|
||||||
// 'Subtask updated' => '',
|
'Subtask updated' => 'Deluppgiften har uppdaterats',
|
||||||
// 'Task updated' => '',
|
'Task updated' => 'Uppgiften har uppdaterats',
|
||||||
// 'Task closed' => '',
|
'Task closed' => 'Uppgiften har stängts',
|
||||||
// 'Task opened' => '',
|
'Task opened' => 'Uppgiften har öppnats',
|
||||||
'[%s][Due tasks]' => '[%s][Förfallen uppgift]',
|
'[%s][Due tasks]' => '[%s][Förfallen uppgift]',
|
||||||
'[Kanboard] Notification' => '[Kanboard] Notis',
|
'[Kanboard] Notification' => '[Kanboard] Notis',
|
||||||
'I want to receive notifications only for those projects:' => 'Jag vill endast få notiser för dessa projekt:',
|
'I want to receive notifications only for those projects:' => 'Jag vill endast få notiser för dessa projekt:',
|
||||||
|
@ -498,9 +500,9 @@ return array(
|
||||||
'Task assignee change' => 'Ändra tilldelning av uppgiften',
|
'Task assignee change' => 'Ändra tilldelning av uppgiften',
|
||||||
'%s change the assignee of the task #%d to %s' => '%s byt tilldelning av uppgiften #%d till %s',
|
'%s change the assignee of the task #%d to %s' => '%s byt tilldelning av uppgiften #%d till %s',
|
||||||
'%s changed the assignee of the task %s to %s' => '%s byt tilldelning av uppgiften %s till %s',
|
'%s changed the assignee of the task %s to %s' => '%s byt tilldelning av uppgiften %s till %s',
|
||||||
// 'Column Change' => '',
|
'Column Change' => 'Ändring av kolumn',
|
||||||
// 'Position Change' => '',
|
'Position Change' => 'Ändring av position',
|
||||||
// 'Assignee Change' => '',
|
'Assignee Change' => 'Ändring av tilldelning',
|
||||||
'New password for the user "%s"' => 'Nytt lösenord för användaren "%s"',
|
'New password for the user "%s"' => 'Nytt lösenord för användaren "%s"',
|
||||||
'Choose an event' => 'Välj en händelse',
|
'Choose an event' => 'Välj en händelse',
|
||||||
'Github commit received' => 'Github-bidrag mottaget',
|
'Github commit received' => 'Github-bidrag mottaget',
|
||||||
|
@ -645,93 +647,203 @@ return array(
|
||||||
'Application default' => 'Applikationsstandard',
|
'Application default' => 'Applikationsstandard',
|
||||||
'Language:' => 'Språk',
|
'Language:' => 'Språk',
|
||||||
'Timezone:' => 'Tidszon',
|
'Timezone:' => 'Tidszon',
|
||||||
// 'All columns' => '',
|
'All columns' => 'Alla kolumner',
|
||||||
// 'Calendar for "%s"' => '',
|
'Calendar for "%s"' => 'Kalender för "%s"',
|
||||||
// 'Filter by column' => '',
|
'Filter by column' => 'Filtrera på kolumn',
|
||||||
// 'Filter by status' => '',
|
'Filter by status' => 'Filtrera på status',
|
||||||
// 'Calendar' => '',
|
'Calendar' => 'Kalender',
|
||||||
'Next' => 'Nästa',
|
'Next' => 'Nästa',
|
||||||
// '#%d' => '',
|
'#%d' => '#%d',
|
||||||
// 'Filter by color' => '',
|
'Filter by color' => 'Filtrera på färg',
|
||||||
// 'Filter by swimlane' => '',
|
'Filter by swimlane' => 'Filtrera på swimlane',
|
||||||
// 'All swimlanes' => '',
|
'All swimlanes' => 'Alla swimlanes',
|
||||||
// 'All colors' => '',
|
'All colors' => 'Alla färger',
|
||||||
// 'All status' => '',
|
'All status' => 'Alla status',
|
||||||
// 'Add a comment logging moving the task between columns' => '',
|
'Add a comment logging moving the task between columns' => 'Lägg till en kommentar för att logga förflyttning av en uppgift mellan kolumner',
|
||||||
// 'Moved to column %s' => '',
|
'Moved to column %s' => 'Flyttad till kolumn %s',
|
||||||
// 'Change description' => '',
|
'Change description' => 'Ändra beskrivning',
|
||||||
// 'User dashboard' => '',
|
'User dashboard' => 'Användardashboard',
|
||||||
// 'Allow only one subtask in progress at the same time for a user' => '',
|
'Allow only one subtask in progress at the same time for a user' => 'Tillåt endast en deluppgift igång samtidigt för en användare',
|
||||||
// 'Edit column "%s"' => '',
|
'Edit column "%s"' => 'Ändra kolumn "%s"',
|
||||||
// 'Enable time tracking for subtasks' => '',
|
'Enable time tracking for subtasks' => 'Aktivera tidsbevakning för deluppgifter',
|
||||||
// 'Select the new status of the subtask: "%s"' => '',
|
'Select the new status of the subtask: "%s"' => 'Välj ny status för deluppgiften: "%s"',
|
||||||
// 'Subtask timesheet' => '',
|
'Subtask timesheet' => 'Tidrapport för deluppgiften',
|
||||||
// 'There is nothing to show.' => '',
|
'There is nothing to show.' => 'Det finns inget att visa',
|
||||||
// 'Time Tracking' => '',
|
'Time Tracking' => 'Tidsbevakning',
|
||||||
// 'You already have one subtask in progress' => '',
|
'You already have one subtask in progress' => 'Du har redan en deluppgift igång',
|
||||||
// 'Which parts of the project do you want to duplicate?' => '',
|
'Which parts of the project do you want to duplicate?' => 'Vilka delar av projektet vill du duplicera?',
|
||||||
// 'Change dashboard view' => '',
|
'Change dashboard view' => 'Ändra dashboard vy',
|
||||||
// 'Show/hide activities' => '',
|
'Show/hide activities' => 'Visa/dölj aktiviteter',
|
||||||
// 'Show/hide projects' => '',
|
'Show/hide projects' => 'Visa/dölj projekt',
|
||||||
// 'Show/hide subtasks' => '',
|
'Show/hide subtasks' => 'Visa/dölj deluppgifter',
|
||||||
// 'Show/hide tasks' => '',
|
'Show/hide tasks' => 'Visa/dölj uppgifter',
|
||||||
// 'Disable login form' => '',
|
'Disable login form' => 'Inaktivera loginformuläret',
|
||||||
// 'Show/hide calendar' => '',
|
'Show/hide calendar' => 'Visa/dölj kalender',
|
||||||
// 'User calendar' => '',
|
'User calendar' => 'Användarkalender',
|
||||||
// 'Bitbucket commit received' => '',
|
'Bitbucket commit received' => 'Bitbucket bidrag mottaget',
|
||||||
// 'Bitbucket webhooks' => '',
|
'Bitbucket webhooks' => 'Bitbucket webhooks',
|
||||||
// 'Help on Bitbucket webhooks' => '',
|
'Help on Bitbucket webhooks' => 'Hjälp för Bitbucket webhooks',
|
||||||
// 'Start' => '',
|
'Start' => 'Start',
|
||||||
// 'End' => '',
|
'End' => 'Slut',
|
||||||
// 'Task age in days' => '',
|
'Task age in days' => 'Uppgiftsålder i dagar',
|
||||||
// 'Days in this column' => '',
|
'Days in this column' => 'Dagar i denna kolumn',
|
||||||
// '%dd' => '',
|
'%dd' => '%dd',
|
||||||
// 'Add a link' => '',
|
'Add a link' => 'Lägg till länk',
|
||||||
// 'Add a new link' => '',
|
'Add a new link' => 'Lägg till ny länk',
|
||||||
// 'Do you really want to remove this link: "%s"?' => '',
|
'Do you really want to remove this link: "%s"?' => 'Vill du verkligen ta bort länken: "%s"?',
|
||||||
// 'Do you really want to remove this link with task #%d?' => '',
|
'Do you really want to remove this link with task #%d?' => 'Vill du verkligen ta bort länken till uppgiften #%d?',
|
||||||
// 'Field required' => '',
|
'Field required' => 'Fältet krävs',
|
||||||
// 'Link added successfully.' => '',
|
'Link added successfully.' => 'Länken har lagts till',
|
||||||
// 'Link updated successfully.' => '',
|
'Link updated successfully.' => 'Länken har uppdaterats',
|
||||||
// 'Link removed successfully.' => '',
|
'Link removed successfully.' => 'Länken har tagits bort',
|
||||||
// 'Link labels' => '',
|
'Link labels' => 'Länketiketter',
|
||||||
// 'Link modification' => '',
|
'Link modification' => 'Länkändring',
|
||||||
// 'Links' => '',
|
'Links' => 'Länkar',
|
||||||
// 'Link settings' => '',
|
'Link settings' => 'Länkinställningar',
|
||||||
// 'Opposite label' => '',
|
'Opposite label' => 'Motpartslänk',
|
||||||
// 'Remove a link' => '',
|
'Remove a link' => 'Ta bort en länk',
|
||||||
// 'Task\'s links' => '',
|
'Task\'s links' => 'Uppgiftslänkar',
|
||||||
// 'The labels must be different' => '',
|
'The labels must be different' => 'Etiketterna måste vara olika',
|
||||||
// 'There is no link.' => '',
|
'There is no link.' => 'Det finns ingen länk',
|
||||||
// 'This label must be unique' => '',
|
'This label must be unique' => 'Länken måste vara unik',
|
||||||
// 'Unable to create your link.' => '',
|
'Unable to create your link.' => 'Kunde inte skapa din länk',
|
||||||
// 'Unable to update your link.' => '',
|
'Unable to update your link.' => 'Kunde inte uppdatera din länk',
|
||||||
// 'Unable to remove this link.' => '',
|
'Unable to remove this link.' => 'Kunde inte ta bort din länk',
|
||||||
// 'relates to' => '',
|
'relates to' => 'relaterar till',
|
||||||
// 'blocks' => '',
|
'blocks' => 'blockerar',
|
||||||
// 'is blocked by' => '',
|
'is blocked by' => 'blockeras av',
|
||||||
// 'duplicates' => '',
|
'duplicates' => 'dupplicerar',
|
||||||
// 'is duplicated by' => '',
|
'is duplicated by' => 'är duplicerad av',
|
||||||
// 'is a child of' => '',
|
'is a child of' => 'är underliggande till',
|
||||||
// 'is a parent of' => '',
|
'is a parent of' => 'är överliggande till',
|
||||||
// 'targets milestone' => '',
|
'targets milestone' => 'milstolpemål',
|
||||||
// 'is a milestone of' => '',
|
'is a milestone of' => 'är en milstolpe för',
|
||||||
// 'fixes' => '',
|
'fixes' => 'åtgärdar',
|
||||||
// 'is fixed by' => '',
|
'is fixed by' => 'åtgärdas av',
|
||||||
// 'This task' => '',
|
'This task' => 'Denna uppgift',
|
||||||
// '<1h' => '',
|
'<1h' => '<1h',
|
||||||
// '%dh' => '',
|
'%dh' => '%dh',
|
||||||
// '%b %e' => '',
|
'%b %e' => '%b %e',
|
||||||
// 'Expand tasks' => '',
|
'Expand tasks' => 'Expandera uppgifter',
|
||||||
// 'Collapse tasks' => '',
|
'Collapse tasks' => 'Minimera uppgifter',
|
||||||
// 'Expand/collapse tasks' => '',
|
'Expand/collapse tasks' => 'Expandera/minimera uppgifter',
|
||||||
// 'Close dialog box' => '',
|
'Close dialog box' => 'Stäng dialogruta',
|
||||||
// 'Submit a form' => '',
|
'Submit a form' => 'Sänd formulär',
|
||||||
// 'Board view' => '',
|
'Board view' => 'Tavelvy',
|
||||||
// 'Keyboard shortcuts' => '',
|
'Keyboard shortcuts' => 'Tangentbordsgenvägar',
|
||||||
// 'Open board switcher' => '',
|
'Open board switcher' => 'Växling av öppen tavla',
|
||||||
// 'Application' => '',
|
'Application' => 'Applikation',
|
||||||
// 'Filter recently updated' => '',
|
'Filter recently updated' => 'Filter som uppdaterats nyligen',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
'since %B %e, %Y at %k:%M %p' => 'sedan %B %e, %Y at %k:%M %p',
|
||||||
// 'More filters' => '',
|
'More filters' => 'Fler filter',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
'None' => 'ไม่มี',
|
'None' => 'ไม่มี',
|
||||||
'edit' => 'แก้ไข',
|
'edit' => 'แก้ไข',
|
||||||
'Edit' => 'แก้ไข',
|
'Edit' => 'แก้ไข',
|
||||||
|
@ -734,4 +736,114 @@ return array(
|
||||||
// 'Filter recently updated' => '',
|
// 'Filter recently updated' => '',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
// 'More filters' => '',
|
||||||
|
// 'Compact view' => '',
|
||||||
|
// 'Horizontal scrolling' => '',
|
||||||
|
// 'Compact/wide view' => '',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
);
|
);
|
||||||
|
|
849
sources/app/Locale/tr_TR/translations.php
Normal file
849
sources/app/Locale/tr_TR/translations.php
Normal file
|
@ -0,0 +1,849 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'number.decimals_separator' => '',
|
||||||
|
// 'number.thousands_separator' => '',
|
||||||
|
'None' => 'Hiçbiri',
|
||||||
|
'edit' => 'düzenle',
|
||||||
|
'Edit' => 'Düzenle',
|
||||||
|
'remove' => 'sil',
|
||||||
|
'Remove' => 'Sil',
|
||||||
|
'Update' => 'Güncelle',
|
||||||
|
'Yes' => 'Evet',
|
||||||
|
'No' => 'Hayır',
|
||||||
|
'cancel' => 'İptal',
|
||||||
|
'or' => 'veya',
|
||||||
|
'Yellow' => 'Sarı',
|
||||||
|
'Blue' => 'Mavi',
|
||||||
|
'Green' => 'Yeşil',
|
||||||
|
'Purple' => 'Mor',
|
||||||
|
'Red' => 'Kırmızı',
|
||||||
|
'Orange' => 'Turuncu',
|
||||||
|
'Grey' => 'Gri',
|
||||||
|
'Save' => 'Kaydet',
|
||||||
|
'Login' => 'Giriş',
|
||||||
|
'Official website:' => 'Resmi internet sitesi:',
|
||||||
|
'Unassigned' => 'Atanmamış',
|
||||||
|
'View this task' => 'Bu görevi görüntüle',
|
||||||
|
'Remove user' => 'Kullanıcıyı kaldır',
|
||||||
|
'Do you really want to remove this user: "%s"?' => 'Bu kullanıcıyı gerçekten silmek istiyor musunuz: "%s"?',
|
||||||
|
'New user' => 'Yeni kullanıcı',
|
||||||
|
'All users' => 'Tüm kullanıcılar',
|
||||||
|
'Username' => 'Kullanıcı adı',
|
||||||
|
'Password' => 'Şifre',
|
||||||
|
// 'Default project' => '',
|
||||||
|
'Administrator' => 'Yönetici',
|
||||||
|
'Sign in' => 'Giriş yap',
|
||||||
|
'Users' => 'Kullanıcılar',
|
||||||
|
'No user' => 'Kullanıcı yok',
|
||||||
|
'Forbidden' => 'Yasak',
|
||||||
|
'Access Forbidden' => 'Erişim yasak',
|
||||||
|
'Only administrators can access to this page.' => 'Bu sayfaya yalnızca yöneticiler erişebilir.',
|
||||||
|
'Edit user' => 'Kullanıcıyı düzenle',
|
||||||
|
'Logout' => 'Çıkış yap',
|
||||||
|
'Bad username or password' => 'Hatalı kullanıcı adı veya şifre',
|
||||||
|
'users' => 'kullanıcılar',
|
||||||
|
'projects' => 'projeler',
|
||||||
|
'Edit project' => 'Projeyi düzenle',
|
||||||
|
'Name' => 'İsim',
|
||||||
|
'Activated' => 'Aktif',
|
||||||
|
'Projects' => 'Projeler',
|
||||||
|
'No project' => 'Proje yok',
|
||||||
|
'Project' => 'Proje',
|
||||||
|
'Status' => 'Durum',
|
||||||
|
'Tasks' => 'Görevler',
|
||||||
|
'Board' => 'Tablo',
|
||||||
|
'Actions' => 'İşlemler',
|
||||||
|
'Inactive' => 'Aktif değil',
|
||||||
|
'Active' => 'Aktif',
|
||||||
|
'Column %d' => 'Sütun %d',
|
||||||
|
'Add this column' => 'Bu sütunu ekle',
|
||||||
|
'%d tasks on the board' => '%d görev bu tabloda',
|
||||||
|
'%d tasks in total' => '%d görev toplam',
|
||||||
|
'Unable to update this board.' => 'Bu tablo güncellenemiyor.',
|
||||||
|
'Edit board' => 'Tabloyu düzenle',
|
||||||
|
'Disable' => 'Devre dışı bırak',
|
||||||
|
'Enable' => 'Etkinleştir',
|
||||||
|
'New project' => 'Yeni proje',
|
||||||
|
'Do you really want to remove this project: "%s"?' => 'Bu projeyi gerçekten silmek istiyor musunuz: "%s"?',
|
||||||
|
'Remove project' => 'Projeyi sil',
|
||||||
|
'Boards' => 'Tablolar',
|
||||||
|
'Edit the board for "%s"' => 'Tabloyu "%s" için güncelle',
|
||||||
|
'All projects' => 'Tüm projeler',
|
||||||
|
'Change columns' => 'Sütunları değiştir',
|
||||||
|
'Add a new column' => 'Yeni sütun ekle',
|
||||||
|
'Title' => 'Başlık',
|
||||||
|
'Add Column' => 'Sütun ekle',
|
||||||
|
'Project "%s"' => 'Proje "%s"',
|
||||||
|
'Nobody assigned' => 'Kullanıcı atanmamış',
|
||||||
|
'Assigned to %s' => '%s kullanıcısına atanmış',
|
||||||
|
'Remove a column' => 'Bir sütunu sil',
|
||||||
|
'Remove a column from a board' => 'Tablodan bir sütunu sil',
|
||||||
|
'Unable to remove this column.' => 'Bu sütun silinemiyor.',
|
||||||
|
'Do you really want to remove this column: "%s"?' => 'Bu sütunu gerçekten silmek istiyor musunuz: "%s"?',
|
||||||
|
'This action will REMOVE ALL TASKS associated to this column!' => 'Bu komut sütun içindeki TÜM GÖREVLERİ silecek!',
|
||||||
|
'Settings' => 'Ayarlar',
|
||||||
|
'Application settings' => 'Uygulama ayarları',
|
||||||
|
'Language' => 'Dil',
|
||||||
|
// 'Webhook token:' => '',
|
||||||
|
'API token:' => 'API Token:',
|
||||||
|
'More information' => 'Daha fazla bilgi',
|
||||||
|
'Database size:' => 'Veritabanı boyutu :',
|
||||||
|
'Download the database' => 'Veritabanını indir',
|
||||||
|
'Optimize the database' => 'Veritabanını optimize et',
|
||||||
|
'(VACUUM command)' => '(VACUUM komutu)',
|
||||||
|
'(Gzip compressed Sqlite file)' => '(Gzip ile sıkıştırılmış Sqlite dosyası)',
|
||||||
|
'User settings' => 'Kullanıcı ayarları',
|
||||||
|
'My default project:' => 'Benim varsayılan projem:',
|
||||||
|
'Close a task' => 'Bir görevi kapat',
|
||||||
|
'Do you really want to close this task: "%s"?' => 'Bu görevi gerçekten kapatmak istiyor musunuz: "%s"?',
|
||||||
|
'Edit a task' => 'Bir görevi düzenle',
|
||||||
|
'Column' => 'Sütun',
|
||||||
|
'Color' => 'Renk',
|
||||||
|
'Assignee' => 'Atanan',
|
||||||
|
'Create another task' => 'Başka bir görev oluştur',
|
||||||
|
'New task' => 'Nouvelle tâche',
|
||||||
|
'Open a task' => 'Bir görevi aç',
|
||||||
|
'Do you really want to open this task: "%s"?' => 'Bu görevi gerçekten açmak istiyor musunuz: "%s"?',
|
||||||
|
'Back to the board' => 'Tabloya dön',
|
||||||
|
// 'Created on %B %e, %Y at %k:%M %p' => '',
|
||||||
|
'There is nobody assigned' => 'Kimse atanmamış',
|
||||||
|
'Column on the board:' => 'Tablodaki sütun:',
|
||||||
|
'Status is open' => 'Açık durumda',
|
||||||
|
'Status is closed' => 'Kapalı durumda',
|
||||||
|
'Close this task' => 'Görevi kapat',
|
||||||
|
'Open this task' => 'Görevi aç',
|
||||||
|
'There is no description.' => 'Açıklama yok.',
|
||||||
|
'Add a new task' => 'Yeni görev ekle',
|
||||||
|
'The username is required' => 'Kullanıcı adı gerekli',
|
||||||
|
'The maximum length is %d characters' => 'Maksimum uzunluk %d karakterdir',
|
||||||
|
'The minimum length is %d characters' => 'Minimum uzunluk %d karakterdir',
|
||||||
|
'The password is required' => 'Şifre gerekli',
|
||||||
|
'This value must be an integer' => 'Bu değer bir rakam olmak zorunda',
|
||||||
|
'The username must be unique' => 'Kullanıcı adı daha önceden var',
|
||||||
|
'The username must be alphanumeric' => 'Kullanıcı adı alfanumerik olmalı (geçersiz karakter var)',
|
||||||
|
'The user id is required' => 'Kullanıcı kodu gerekli',
|
||||||
|
'Passwords don\'t match' => 'Şifreler uyuşmuyor',
|
||||||
|
'The confirmation is required' => 'Onay gerekli',
|
||||||
|
'The column is required' => 'Sütun gerekli',
|
||||||
|
'The project is required' => 'Proje gerekli',
|
||||||
|
'The color is required' => 'Renk gerekli',
|
||||||
|
'The id is required' => 'Kod gerekli',
|
||||||
|
'The project id is required' => 'Proje kodu gerekli',
|
||||||
|
'The project name is required' => 'Proje adı gerekli',
|
||||||
|
'This project must be unique' => 'Bu projenin tekil olması gerekli',
|
||||||
|
'The title is required' => 'Başlık gerekli',
|
||||||
|
'The language is required' => 'Dil seçimi gerekli',
|
||||||
|
'There is no active project, the first step is to create a new project.' => 'Aktif bir proje yok. İlk aşama yeni bir proje oluşturmak olmalı.',
|
||||||
|
'Settings saved successfully.' => 'Ayarlar başarıyla kaydedildi.',
|
||||||
|
'Unable to save your settings.' => 'Ayarlarınız kaydedilemedi.',
|
||||||
|
'Database optimization done.' => 'Veritabanı optimizasyonu tamamlandı.',
|
||||||
|
'Your project have been created successfully.' => 'Projeniz başarıyla oluşturuldu.',
|
||||||
|
'Unable to create your project.' => 'Proje oluşturulamadı.',
|
||||||
|
'Project updated successfully.' => 'Proje başarıyla güncellendi.',
|
||||||
|
'Unable to update this project.' => 'Bu proje güncellenemedi.',
|
||||||
|
'Unable to remove this project.' => 'Bu proje silinemedi.',
|
||||||
|
'Project removed successfully.' => 'Proje başarıyla silindi.',
|
||||||
|
'Project activated successfully.' => 'Proje başarıyla aktive edildi.',
|
||||||
|
'Unable to activate this project.' => 'Bu proje aktive edilemedi.',
|
||||||
|
'Project disabled successfully.' => 'Proje devre dışı bırakıldı.',
|
||||||
|
'Unable to disable this project.' => 'Bu proje devre dışı bırakılamadı.',
|
||||||
|
'Unable to open this task.' => 'Bu görev açılamıyor.',
|
||||||
|
'Task opened successfully.' => 'Görev başarıyla açıldı.',
|
||||||
|
'Unable to close this task.' => 'Bu görev kapatılamıyor.',
|
||||||
|
'Task closed successfully.' => 'Görev başarıyla kapatıldı.',
|
||||||
|
'Unable to update your task.' => 'Görev güncellenemiyor.',
|
||||||
|
'Task updated successfully.' => 'Görev başarıyla güncellendi.',
|
||||||
|
'Unable to create your task.' => 'Görev oluşturulamadı.',
|
||||||
|
'Task created successfully.' => 'Görev başarıyla oluşturuldu.',
|
||||||
|
'User created successfully.' => 'Kullanıcı başarıyla oluşturuldu',
|
||||||
|
'Unable to create your user.' => 'Kullanıcı oluşturulamıyor.',
|
||||||
|
'User updated successfully.' => 'Kullanıcı başarıyla güncellendi.',
|
||||||
|
'Unable to update your user.' => 'Kullanıcı güncellenemiyor.',
|
||||||
|
'User removed successfully.' => 'Kullanıcı silindi.',
|
||||||
|
'Unable to remove this user.' => 'Bu kullanıcı silinemiyor.',
|
||||||
|
'Board updated successfully.' => 'Tablo başarıyla güncellendi.',
|
||||||
|
'Ready' => 'Hazır',
|
||||||
|
'Backlog' => 'Bekleme listesi',
|
||||||
|
'Work in progress' => 'İşlemde',
|
||||||
|
'Done' => 'Tamamlandı',
|
||||||
|
'Application version:' => 'Uygulama versiyonu:',
|
||||||
|
// 'Completed on %B %e, %Y at %k:%M %p' => '',
|
||||||
|
// '%B %e, %Y at %k:%M %p' => '',
|
||||||
|
'Date created' => 'Oluşturulma tarihi',
|
||||||
|
'Date completed' => 'Tamamlanma tarihi',
|
||||||
|
'Id' => 'Kod',
|
||||||
|
'No task' => 'Görev yok',
|
||||||
|
'Completed tasks' => 'Tamamlanan görevler',
|
||||||
|
'List of projects' => 'Proje listesi',
|
||||||
|
'Completed tasks for "%s"' => '"%s" için tamamlanan görevler',
|
||||||
|
'%d closed tasks' => '%d kapatılmış görevler',
|
||||||
|
// 'No task for this project' => '',
|
||||||
|
'Public link' => 'Dışa açık link',
|
||||||
|
'There is no column in your project!' => 'Projenizde hiç sütun yok',
|
||||||
|
'Change assignee' => 'Atanmış Kullanıcıyı değiştir',
|
||||||
|
'Change assignee for the task "%s"' => '"%s" görevi için atanmış kullanıcıyı değiştir',
|
||||||
|
'Timezone' => 'Saat dilimi',
|
||||||
|
// 'Sorry, I didn\'t find this information in my database!' => '',
|
||||||
|
'Page not found' => 'Sayfa bulunamadı',
|
||||||
|
'Complexity' => 'Zorluk seviyesi',
|
||||||
|
'limit' => 'limit',
|
||||||
|
'Task limit' => 'Görev limiti',
|
||||||
|
'Task count' => 'Görev sayısı',
|
||||||
|
'This value must be greater than %d' => 'Bu değer %d den büyük olmalı',
|
||||||
|
'Edit project access list' => 'Proje erişim listesini düzenle',
|
||||||
|
'Edit users access' => 'Kullanıcı erişim haklarını düzenle',
|
||||||
|
'Allow this user' => 'Bu kullanıcıya izin ver',
|
||||||
|
'Only those users have access to this project:' => 'Bu projeye yalnızca şu kullanıcılar erişebilir:',
|
||||||
|
'Don\'t forget that administrators have access to everything.' => 'Dikkat: Yöneticilerin herşeye erişimi olduğunu unutmayın!',
|
||||||
|
'Revoke' => 'Iptal et',
|
||||||
|
'List of authorized users' => 'Yetkili kullanıcıların listesi',
|
||||||
|
'User' => 'Kullanıcı',
|
||||||
|
'Nobody have access to this project.' => 'Bu projeye kimsenin erişimi yok.',
|
||||||
|
'You are not allowed to access to this project.' => 'Bu projeye giriş yetkiniz yok.',
|
||||||
|
'Comments' => 'Yorumlar',
|
||||||
|
'Post comment' => 'Yorum ekle',
|
||||||
|
'Write your text in Markdown' => 'Yazınızı Markdown ile yazın',
|
||||||
|
'Leave a comment' => 'Bir yorum ekle',
|
||||||
|
'Comment is required' => 'Yorum gerekli',
|
||||||
|
'Leave a description' => 'Açıklama ekleyin',
|
||||||
|
'Comment added successfully.' => 'Yorum eklendi',
|
||||||
|
'Unable to create your comment.' => 'Yorumunuz oluşturulamadı',
|
||||||
|
'The description is required' => 'Açıklama gerekli',
|
||||||
|
'Edit this task' => 'Bu görevi değiştir',
|
||||||
|
'Due Date' => 'Termin',
|
||||||
|
'Invalid date' => 'Geçersiz tarihi',
|
||||||
|
// 'Must be done before %B %e, %Y' => '',
|
||||||
|
'%B %e, %Y' => '%d %B %Y',
|
||||||
|
'%b %e, %Y' => '%d/%m/%Y',
|
||||||
|
'Automatic actions' => 'Otomatik işlemler',
|
||||||
|
'Your automatic action have been created successfully.' => 'Otomatik işlem başarıyla oluşturuldu',
|
||||||
|
'Unable to create your automatic action.' => 'Otomatik işleminiz oluşturulamadı',
|
||||||
|
'Remove an action' => 'Bir işlemi sil',
|
||||||
|
'Unable to remove this action.' => 'Bu işlem silinemedi',
|
||||||
|
'Action removed successfully.' => 'İşlem başarıyla silindi',
|
||||||
|
'Automatic actions for the project "%s"' => '"%s" projesi için otomatik işlemler',
|
||||||
|
'Defined actions' => 'Tanımlanan işlemler',
|
||||||
|
'Add an action' => 'İşlem ekle',
|
||||||
|
'Event name' => 'Durum adı',
|
||||||
|
'Action name' => 'İşlem adı',
|
||||||
|
'Action parameters' => 'İşlem parametreleri',
|
||||||
|
'Action' => 'İşlem',
|
||||||
|
'Event' => 'Durum',
|
||||||
|
'When the selected event occurs execute the corresponding action.' => 'Seçilen durum oluştuğunda ilgili eylemi gerçekleştir.',
|
||||||
|
'Next step' => 'Sonraki adım',
|
||||||
|
'Define action parameters' => 'İşlem parametrelerini düzenle',
|
||||||
|
'Save this action' => 'Bu işlemi kaydet',
|
||||||
|
'Do you really want to remove this action: "%s"?' => 'Bu işlemi silmek istediğinize emin misiniz: "%s"?',
|
||||||
|
'Remove an automatic action' => 'Bir otomatik işlemi sil',
|
||||||
|
'Close the task' => 'Görevi kapat',
|
||||||
|
'Assign the task to a specific user' => 'Görevi bir kullanıcıya ata',
|
||||||
|
'Assign the task to the person who does the action' => 'Görevi, işlemi gerçekleştiren kullanıcıya ata',
|
||||||
|
'Duplicate the task to another project' => 'Görevi bir başka projeye kopyala',
|
||||||
|
'Move a task to another column' => 'Bir görevi başka bir sütuna taşı',
|
||||||
|
'Move a task to another position in the same column' => 'Bir görevin aynı sütunda yerini değiştir',
|
||||||
|
'Task modification' => 'Görev düzenleme',
|
||||||
|
'Task creation' => 'Görev oluşturma',
|
||||||
|
'Open a closed task' => 'Kapalı bir görevi aç',
|
||||||
|
'Closing a task' => 'Bir görev kapatılıyor',
|
||||||
|
'Assign a color to a specific user' => 'Bir kullanıcıya renk tanımla',
|
||||||
|
'Column title' => 'Sütun başlığı',
|
||||||
|
'Position' => 'Pozisyon',
|
||||||
|
'Move Up' => 'Yukarı taşı',
|
||||||
|
'Move Down' => 'Aşağı taşı',
|
||||||
|
'Duplicate to another project' => 'Başka bir projeye kopyala',
|
||||||
|
'Duplicate' => 'Kopya oluştur',
|
||||||
|
'link' => 'link',
|
||||||
|
'Update this comment' => 'Bu yorumu güncelle',
|
||||||
|
'Comment updated successfully.' => 'Yorum güncellendi.',
|
||||||
|
'Unable to update your comment.' => 'Yorum güncellenemedi.',
|
||||||
|
'Remove a comment' => 'Bir yorumu sil',
|
||||||
|
'Comment removed successfully.' => 'Yorum silindi.',
|
||||||
|
'Unable to remove this comment.' => 'Bu yorum silinemiyor.',
|
||||||
|
'Do you really want to remove this comment?' => 'Bu yorumu silmek istediğinize emin misiniz?',
|
||||||
|
'Only administrators or the creator of the comment can access to this page.' => 'Bu sayfaya yalnızca yorum sahibi ve yöneticiler erişebilir.',
|
||||||
|
'Details' => 'Detaylar',
|
||||||
|
'Current password for the user "%s"' => 'Kullanıcı için mevcut şifre "%s"',
|
||||||
|
'The current password is required' => 'Mevcut şifre gerekli',
|
||||||
|
'Wrong password' => 'Yanlış Şifre',
|
||||||
|
'Reset all tokens' => 'Tüm fişleri sıfırla',
|
||||||
|
'All tokens have been regenerated.' => 'Tüm fişler yeniden oluşturuldu.',
|
||||||
|
'Unknown' => 'Bilinmeyen',
|
||||||
|
'Last logins' => 'Son kullanıcı girişleri',
|
||||||
|
'Login date' => 'Giriş tarihi',
|
||||||
|
'Authentication method' => 'Doğrulama yöntemi',
|
||||||
|
'IP address' => 'IP adresi',
|
||||||
|
'User agent' => 'Kullanıcı sistemi',
|
||||||
|
'Persistent connections' => 'Kalıcı bağlantılar',
|
||||||
|
// 'No session.' => '',
|
||||||
|
'Expiration date' => 'Geçerlilik sonu',
|
||||||
|
'Remember Me' => 'Beni hatırla',
|
||||||
|
'Creation date' => 'Oluşturulma tarihi',
|
||||||
|
'Filter by user' => 'Kullanıcıya göre filtrele',
|
||||||
|
'Filter by due date' => 'Termine göre filtrele',
|
||||||
|
'Everybody' => 'Herkes',
|
||||||
|
'Open' => 'Açık',
|
||||||
|
'Closed' => 'Kapalı',
|
||||||
|
'Search' => 'Ara',
|
||||||
|
'Nothing found.' => 'Hiçbir şey bulunamadı',
|
||||||
|
'Search in the project "%s"' => '"%s" Projesinde ara',
|
||||||
|
'Due date' => 'Termin',
|
||||||
|
'Others formats accepted: %s and %s' => 'Diğer kabul edilen formatlar: %s ve %s',
|
||||||
|
'Description' => 'Açıklama',
|
||||||
|
'%d comments' => '%d yorumlar',
|
||||||
|
'%d comment' => '%d yorum',
|
||||||
|
'Email address invalid' => 'E-Posta adresi geçersiz',
|
||||||
|
'Your Google Account is not linked anymore to your profile.' => 'Google hesabınız artık profilinize bağlı değil',
|
||||||
|
'Unable to unlink your Google Account.' => 'Google hesabınızla bağ koparılamadı',
|
||||||
|
'Google authentication failed' => 'Google hesap doğrulaması başarısız',
|
||||||
|
'Unable to link your Google Account.' => 'Google hesabınızla bağ oluşturulamadı',
|
||||||
|
'Your Google Account is linked to your profile successfully.' => 'Google hesabınız profilinize başarıyla bağlandı',
|
||||||
|
'Email' => 'E-Posta',
|
||||||
|
'Link my Google Account' => 'Google hesabımla bağ oluştur',
|
||||||
|
'Unlink my Google Account' => 'Google hesabımla bağı kaldır',
|
||||||
|
'Login with my Google Account' => 'Google hesabımla giriş yap',
|
||||||
|
'Project not found.' => 'Proje bulunamadı',
|
||||||
|
'Task #%d' => 'Görev #%d',
|
||||||
|
'Task removed successfully.' => 'Görev silindi',
|
||||||
|
'Unable to remove this task.' => 'Görev silinemiyor',
|
||||||
|
'Remove a task' => 'Bir görevi sil',
|
||||||
|
'Do you really want to remove this task: "%s"?' => 'Bu görevi silmek istediğinize emin misiniz: "%s"?',
|
||||||
|
'Assign automatically a color based on a category' => 'Kategoriye göre otomatik renk ata',
|
||||||
|
'Assign automatically a category based on a color' => 'Rengine göre otomatik kategori ata',
|
||||||
|
'Task creation or modification' => 'Görev oluşturma veya değiştirme',
|
||||||
|
'Category' => 'Kategori',
|
||||||
|
'Category:' => 'Kategori:',
|
||||||
|
'Categories' => 'Kategoriler',
|
||||||
|
'Category not found.' => 'Kategori bulunamadı',
|
||||||
|
'Your category have been created successfully.' => 'Kategori oluşturuldu',
|
||||||
|
'Unable to create your category.' => 'Kategori oluşturulamadı',
|
||||||
|
'Your category have been updated successfully.' => 'Kategori başarıyla güncellendi',
|
||||||
|
'Unable to update your category.' => 'Kategori güncellenemedi',
|
||||||
|
'Remove a category' => 'Bir kategoriyi sil',
|
||||||
|
'Category removed successfully.' => 'Kategori silindi',
|
||||||
|
'Unable to remove this category.' => 'Bu kategori silinemedi',
|
||||||
|
'Category modification for the project "%s"' => '"%s" projesi için kategori değiştirme',
|
||||||
|
'Category Name' => 'Kategori adı',
|
||||||
|
'Categories for the project "%s"' => '"%s" Projesi için kategoriler',
|
||||||
|
'Add a new category' => 'Yeni kategori ekle',
|
||||||
|
'Do you really want to remove this category: "%s"?' => 'Bu kategoriyi silmek istediğinize emin misiniz: "%s"?',
|
||||||
|
'Filter by category' => 'Kategoriye göre filtrele',
|
||||||
|
'All categories' => 'Tüm kategoriler',
|
||||||
|
'No category' => 'Kategori Yok',
|
||||||
|
'The name is required' => 'İsim gerekli',
|
||||||
|
'Remove a file' => 'Dosya sil',
|
||||||
|
'Unable to remove this file.' => 'Dosya silinemedi',
|
||||||
|
'File removed successfully.' => 'Dosya silindi',
|
||||||
|
'Attach a document' => 'Dosya ekle',
|
||||||
|
'Do you really want to remove this file: "%s"?' => 'Bu dosyayı silmek istediğinize emin misiniz: "%s"?',
|
||||||
|
'open' => 'aç',
|
||||||
|
'Attachments' => 'Ekler',
|
||||||
|
'Edit the task' => 'Görevi değiştir',
|
||||||
|
'Edit the description' => 'Açıklamayı değiştir',
|
||||||
|
'Add a comment' => 'Yorum ekle',
|
||||||
|
'Edit a comment' => 'Yorum değiştir',
|
||||||
|
'Summary' => 'Özet',
|
||||||
|
'Time tracking' => 'Zaman takibi',
|
||||||
|
'Estimate:' => 'Tahmini:',
|
||||||
|
'Spent:' => 'Harcanan:',
|
||||||
|
'Do you really want to remove this sub-task?' => 'Bu alt görevi silmek istediğinize emin misiniz',
|
||||||
|
'Remaining:' => 'Kalan',
|
||||||
|
'hours' => 'saat',
|
||||||
|
'spent' => 'harcanan',
|
||||||
|
'estimated' => 'tahmini',
|
||||||
|
'Sub-Tasks' => 'Alt Görev',
|
||||||
|
'Add a sub-task' => 'Alt görev ekle',
|
||||||
|
// 'Original estimate' => '',
|
||||||
|
'Create another sub-task' => 'Başka bir alt görev daha oluştur',
|
||||||
|
// 'Time spent' => '',
|
||||||
|
'Edit a sub-task' => 'Alt görev düzenle',
|
||||||
|
'Remove a sub-task' => 'Alt görev sil',
|
||||||
|
'The time must be a numeric value' => 'Zaman alfanumerik bir değer olmalı',
|
||||||
|
'Todo' => 'Yapılacaklar',
|
||||||
|
'In progress' => 'İşlemde',
|
||||||
|
'Sub-task removed successfully.' => 'Alt görev silindi',
|
||||||
|
'Unable to remove this sub-task.' => 'Alt görev silinemedi',
|
||||||
|
'Sub-task updated successfully.' => 'Alt görev güncellendi',
|
||||||
|
'Unable to update your sub-task.' => 'Alt görev güncellenemiyor',
|
||||||
|
'Unable to create your sub-task.' => 'Alt görev oluşturulamadı',
|
||||||
|
'Sub-task added successfully.' => 'Alt görev başarıyla eklendii',
|
||||||
|
'Maximum size: ' => 'Maksimum boyutu',
|
||||||
|
'Unable to upload the file.' => 'Karşıya yükleme başarısız',
|
||||||
|
'Display another project' => 'Başka bir proje göster',
|
||||||
|
'Your GitHub account was successfully linked to your profile.' => 'GitHub Hesabınız Profilinize bağlandı.',
|
||||||
|
'Unable to link your GitHub Account.' => 'GitHub hesabınızla bağ oluşturulamadı.',
|
||||||
|
// 'GitHub authentication failed' => '',
|
||||||
|
// 'Your GitHub account is no longer linked to your profile.' => '',
|
||||||
|
// 'Unable to unlink your GitHub Account.' => '',
|
||||||
|
// 'Login with my GitHub Account' => '',
|
||||||
|
// 'Link my GitHub Account' => '',
|
||||||
|
// 'Unlink my GitHub Account' => '',
|
||||||
|
'Created by %s' => '%s tarafından oluşturuldu',
|
||||||
|
'Last modified on %B %e, %Y at %k:%M %p' => 'Son değişiklik tarihi %d.%m.%Y, saati %H:%M',
|
||||||
|
'Tasks Export' => 'Görevleri dışa aktar',
|
||||||
|
'Tasks exportation for "%s"' => '"%s" için görevleri dışa aktar',
|
||||||
|
'Start Date' => 'Başlangıç tarihi',
|
||||||
|
'End Date' => 'Bitiş tarihi',
|
||||||
|
'Execute' => 'Gerçekleştir',
|
||||||
|
'Task Id' => 'Görev No',
|
||||||
|
'Creator' => 'Oluşturan',
|
||||||
|
'Modification date' => 'Değişiklik tarihi',
|
||||||
|
'Completion date' => 'Tamamlanma tarihi',
|
||||||
|
// 'Webhook URL for task creation' => '',
|
||||||
|
// 'Webhook URL for task modification' => '',
|
||||||
|
'Clone' => 'Kopya oluştur',
|
||||||
|
'Clone Project' => 'Projenin kopyasını oluştur',
|
||||||
|
'Project cloned successfully.' => 'Proje kopyası başarıyla oluşturuldu.',
|
||||||
|
'Unable to clone this project.' => 'Proje kopyası oluşturulamadı.',
|
||||||
|
'Email notifications' => 'E-Posta bilgilendirmesi',
|
||||||
|
'Enable email notifications' => 'E-Posta bilgilendirmesini aç',
|
||||||
|
'Task position:' => 'Görev pozisyonu',
|
||||||
|
'The task #%d have been opened.' => '#%d numaralı görev açıldı.',
|
||||||
|
'The task #%d have been closed.' => '#%d numaralı görev kapatıldı.',
|
||||||
|
'Sub-task updated' => 'Alt görev güncellendi',
|
||||||
|
'Title:' => 'Başlık',
|
||||||
|
'Status:' => 'Durum',
|
||||||
|
'Assignee:' => 'Sorumlu:',
|
||||||
|
'Time tracking:' => 'Zaman takibi',
|
||||||
|
'New sub-task' => 'Yeni alt görev',
|
||||||
|
'New attachment added "%s"' => 'Yeni dosya "%s" eklendi.',
|
||||||
|
'Comment updated' => 'Yorum güncellendi',
|
||||||
|
'New comment posted by %s' => '%s tarafından yeni yorum eklendi',
|
||||||
|
'List of due tasks for the project "%s"' => '"%s" projesi için ilgili görevlerin listesi',
|
||||||
|
'New attachment' => 'Yeni dosya eki',
|
||||||
|
'New comment' => 'Yeni yorum',
|
||||||
|
'New subtask' => 'Yeni alt görev',
|
||||||
|
'Subtask updated' => 'Alt görev güncellendi',
|
||||||
|
'Task updated' => 'Görev güncellendi',
|
||||||
|
'Task closed' => 'Görev kapatıldı',
|
||||||
|
'Task opened' => 'Görev açıldı',
|
||||||
|
'[%s][Due tasks]' => '[%s][İlgili görevler]',
|
||||||
|
'[Kanboard] Notification' => '[Kanboard] Bildirim',
|
||||||
|
'I want to receive notifications only for those projects:' => 'Yalnızca bu projelerle ilgili bildirim almak istiyorum:',
|
||||||
|
'view the task on Kanboard' => 'bu görevi Kanboard\'da göster',
|
||||||
|
'Public access' => 'Dışa açık erişim',
|
||||||
|
'Category management' => 'Kategori yönetimi',
|
||||||
|
'User management' => 'Kullanıcı yönetimi',
|
||||||
|
'Active tasks' => 'Aktif görevler',
|
||||||
|
'Disable public access' => 'Dışa açık erişimi kapat',
|
||||||
|
'Enable public access' => 'Dışa açık erişimi aç',
|
||||||
|
'Active projects' => 'Aktif projeler',
|
||||||
|
'Inactive projects' => 'Aktif olmayan projeler',
|
||||||
|
'Public access disabled' => 'Dışa açık erişim kapatıldı',
|
||||||
|
'Do you really want to disable this project: "%s"?' => 'Bu projeyi devre dışı bırakmak istediğinize emin misiniz?: "%s"',
|
||||||
|
'Do you really want to duplicate this project: "%s"?' => 'Bu projenin kopyasını oluşturmak istediğinize emin misiniz?: "%s"',
|
||||||
|
'Do you really want to enable this project: "%s"?' => 'Bu projeyi aktive etmek istediğinize emin misiniz?: "%s"',
|
||||||
|
'Project activation' => 'Proje aktivasyonu',
|
||||||
|
'Move the task to another project' => 'Görevi başka projeye taşı',
|
||||||
|
'Move to another project' => 'Başka projeye taşı',
|
||||||
|
'Do you really want to duplicate this task?' => 'Bu görevin kopyasını oluşturmak istediğinize emin misiniz?',
|
||||||
|
'Duplicate a task' => 'Görevin kopyasını oluştur',
|
||||||
|
'External accounts' => 'Dış hesaplar',
|
||||||
|
'Account type' => 'Hesap türü',
|
||||||
|
'Local' => 'Yerel',
|
||||||
|
'Remote' => 'Uzak',
|
||||||
|
'Enabled' => 'Etkinleştirildi',
|
||||||
|
'Disabled' => 'Devre dışı bırakıldı',
|
||||||
|
'Google account linked' => 'Google hesabıyla bağlı',
|
||||||
|
'Github account linked' => 'Github hesabıyla bağlı',
|
||||||
|
'Username:' => 'Kullanıcı adı',
|
||||||
|
'Name:' => 'Ad',
|
||||||
|
'Email:' => 'E-Posta',
|
||||||
|
'Default project:' => 'Varsayılan Proje:',
|
||||||
|
'Notifications:' => 'Bildirimler:',
|
||||||
|
'Notifications' => 'Bildirimler',
|
||||||
|
'Group:' => 'Grup',
|
||||||
|
'Regular user' => 'Varsayılan kullanıcı',
|
||||||
|
'Account type:' => 'Hesap türü:',
|
||||||
|
'Edit profile' => 'Profili değiştir',
|
||||||
|
'Change password' => 'Şifre değiştir',
|
||||||
|
'Password modification' => 'Şifre değişimi',
|
||||||
|
'External authentications' => 'Dış kimlik doğrulamaları',
|
||||||
|
'Google Account' => 'Google hesabı',
|
||||||
|
'Github Account' => 'Github hesabı',
|
||||||
|
'Never connected.' => 'Hiç bağlanmamış.',
|
||||||
|
'No account linked.' => 'Bağlanmış hesap yok.',
|
||||||
|
'Account linked.' => 'Hesap bağlandı',
|
||||||
|
'No external authentication enabled.' => 'Dış kimlik doğrulama kapalı.',
|
||||||
|
'Password modified successfully.' => 'Şifre başarıyla değiştirildi.',
|
||||||
|
'Unable to change the password.' => 'Şifre değiştirilemedi.',
|
||||||
|
'Change category for the task "%s"' => '"%s" görevi için kategori değiştirme',
|
||||||
|
'Change category' => 'Kategori değiştirme',
|
||||||
|
'%s updated the task %s' => '%s kullanıcısı %s görevini güncelledi',
|
||||||
|
'%s opened the task %s' => '%s kullanıcısı %s görevini açtı',
|
||||||
|
'%s moved the task %s to the position #%d in the column "%s"' => '%s kullanıcısı %s görevini #%d pozisyonu "%s" sütununa taşıdı',
|
||||||
|
'%s moved the task %s to the column "%s"' => '%s kullanıcısı %s görevini "%s" sütununa taşıdı',
|
||||||
|
'%s created the task %s' => '%s kullanıcısı %s görevini oluşturdu',
|
||||||
|
'%s closed the task %s' => '%s kullanıcısı %s görevini kapattı',
|
||||||
|
'%s created a subtask for the task %s' => '%s kullanıcısı %s görevi için bir alt görev oluşturdu',
|
||||||
|
'%s updated a subtask for the task %s' => '%s kullanıcısı %s görevinin bir alt görevini güncelledi',
|
||||||
|
'Assigned to %s with an estimate of %s/%sh' => '%s kullanıcısına tahmini %s/%s saat tamamlanma süresi ile atanmış',
|
||||||
|
'Not assigned, estimate of %sh' => 'Kimseye atanmamış, tahmini süre %s saat',
|
||||||
|
'%s updated a comment on the task %s' => '%s kullanıcısı %s görevinde bir yorumu güncelledi',
|
||||||
|
'%s commented the task %s' => '%s kullanıcısı %s görevine yorum ekledi',
|
||||||
|
'%s\'s activity' => '%s\'in aktivitesi',
|
||||||
|
'No activity.' => 'Aktivite yok.',
|
||||||
|
'RSS feed' => 'RSS kaynağı',
|
||||||
|
'%s updated a comment on the task #%d' => '%s kullanıcısı #%d nolu görevde bir yorumu güncelledi',
|
||||||
|
'%s commented on the task #%d' => '%s kullanıcısı #%d nolu göreve yorum ekledi',
|
||||||
|
'%s updated a subtask for the task #%d' => '%s kullanıcısı #%d nolu görevin bir alt görevini güncelledi',
|
||||||
|
'%s created a subtask for the task #%d' => '%s kullanıcısı #%d nolu göreve bir alt görev ekledi',
|
||||||
|
'%s updated the task #%d' => '%s kullanıcısı #%d nolu görevi güncelledi',
|
||||||
|
'%s created the task #%d' => '%s kullanıcısı #%d nolu görevi oluşturdu',
|
||||||
|
'%s closed the task #%d' => '%s kullanıcısı #%d nolu görevi kapattı',
|
||||||
|
'%s open the task #%d' => '%s kullanıcısı #%d nolu görevi açtı',
|
||||||
|
'%s moved the task #%d to the column "%s"' => '%s kullanıcısı #%d nolu görevi "%s" sütununa taşıdı',
|
||||||
|
'%s moved the task #%d to the position %d in the column "%s"' => '%s kullanıcısı #%d nolu görevi %d pozisyonu "%s" sütununa taşıdı',
|
||||||
|
'Activity' => 'Aktivite',
|
||||||
|
'Default values are "%s"' => 'Varsayılan değerler "%s"',
|
||||||
|
'Default columns for new projects (Comma-separated)' => 'Yeni projeler için varsayılan sütunlar (virgül ile ayrılmış)',
|
||||||
|
'Task assignee change' => 'Göreve atanan kullanıcı değişikliği',
|
||||||
|
'%s change the assignee of the task #%d to %s' => '%s kullanıcısı #%d nolu görevin sorumlusunu %s olarak değiştirdi',
|
||||||
|
'%s changed the assignee of the task %s to %s' => '%s kullanıcısı %s görevinin sorumlusunu %s olarak değiştirdi',
|
||||||
|
'Column Change' => 'Sütun değişikliği',
|
||||||
|
'Position Change' => 'Konum değişikliği',
|
||||||
|
'Assignee Change' => 'Sorumlu değişikliği',
|
||||||
|
'New password for the user "%s"' => '"%s" kullanıcısı için yeni şifre',
|
||||||
|
'Choose an event' => 'Bir durum seçin',
|
||||||
|
// 'Github commit received' => '',
|
||||||
|
// 'Github issue opened' => '',
|
||||||
|
// 'Github issue closed' => '',
|
||||||
|
// 'Github issue reopened' => '',
|
||||||
|
// 'Github issue assignee change' => '',
|
||||||
|
// 'Github issue label change' => '',
|
||||||
|
'Create a task from an external provider' => 'Dış sağlayıcı ile bir görev oluştur',
|
||||||
|
'Change the assignee based on an external username' => 'Dış kaynaklı kullanıcı adı ile göreve atananı değiştir',
|
||||||
|
'Change the category based on an external label' => 'Dış kaynaklı bir etiket ile kategori değiştir',
|
||||||
|
'Reference' => 'Referans',
|
||||||
|
'Reference: %s' => 'Referans: %s',
|
||||||
|
'Label' => 'Etiket',
|
||||||
|
'Database' => 'Veri bankası',
|
||||||
|
'About' => 'Hakkında',
|
||||||
|
'Database driver:' => 'Veri bankası sürücüsü',
|
||||||
|
'Board settings' => 'Tablo ayarları',
|
||||||
|
'URL and token' => 'URL veya Token',
|
||||||
|
'Webhook settings' => 'Webhook ayarları',
|
||||||
|
'URL for task creation:' => 'Görev oluşturma için URL',
|
||||||
|
'Reset token' => 'Reset Token',
|
||||||
|
'API endpoint:' => 'API endpoint',
|
||||||
|
'Refresh interval for private board' => 'Özel tablolar için yenileme sıklığı',
|
||||||
|
'Refresh interval for public board' => 'Dışa açık tablolar için yenileme sıklığı',
|
||||||
|
'Task highlight period' => 'Görevi öne çıkarma süresi',
|
||||||
|
'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Bir görevin yeni değiştirilmiş sayılması için süre (saniye olarak) (Bu özelliği iptal etmek için 0, varsayılan değer 2 gün)',
|
||||||
|
'Frequency in second (60 seconds by default)' => 'Saniye olarak frekans (varsayılan 60 saniye)',
|
||||||
|
'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Saniye olarak frekans (Bu özelliği iptal etmek için 0, varsayılan değer 10 saniye)',
|
||||||
|
'Application URL' => 'Uygulama URL',
|
||||||
|
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Örneğin: http://example.kanboard.net/ (E-posta bildirimleri için kullanılıyor)',
|
||||||
|
'Token regenerated.' => 'Token yeniden oluşturuldu.',
|
||||||
|
'Date format' => 'Tarih formatı',
|
||||||
|
'ISO format is always accepted, example: "%s" and "%s"' => 'ISO formatı her zaman kabul edilir, örneğin: "%s" ve "%s"',
|
||||||
|
'New private project' => 'Yeni özel proje',
|
||||||
|
'This project is private' => 'Bu proje özel',
|
||||||
|
'Type here to create a new sub-task' => 'Yeni bir alt görev oluşturmak için buraya yazın',
|
||||||
|
'Add' => 'Ekle',
|
||||||
|
'Estimated time: %s hours' => 'Tahmini süre: %s Saat',
|
||||||
|
'Time spent: %s hours' => 'Kullanılan süre: %s Saat',
|
||||||
|
'Started on %B %e, %Y' => '%B %e %Y tarihinde başlatıldı',
|
||||||
|
'Start date' => 'Başlangıç tarihi',
|
||||||
|
'Time estimated' => 'Tahmini süre',
|
||||||
|
'There is nothing assigned to you.' => 'Size atanan hiçbir şey yok.',
|
||||||
|
'My tasks' => 'Görevlerim',
|
||||||
|
'Activity stream' => 'Güncel olay akışı',
|
||||||
|
'Dashboard' => 'Anasayfa',
|
||||||
|
'Confirmation' => 'Onay',
|
||||||
|
'Allow everybody to access to this project' => 'Bu projeye herkesin erişimine izin ver',
|
||||||
|
'Everybody have access to this project.' => 'Bu projeye herkesin erişimi var.',
|
||||||
|
'Webhooks' => 'Webhooks',
|
||||||
|
'API' => 'API',
|
||||||
|
'Integration' => 'Entegrasyon',
|
||||||
|
'Github webhooks' => 'Github Webhook',
|
||||||
|
'Help on Github webhooks' => 'Github Webhooks hakkında yardım',
|
||||||
|
'Create a comment from an external provider' => 'Dış sağlayıcı ile bir yorum oluştur',
|
||||||
|
'Github issue comment created' => 'Github hata yorumu oluşturuldu',
|
||||||
|
'Configure' => 'Ayarla',
|
||||||
|
'Project management' => 'Proje yönetimi',
|
||||||
|
'My projects' => 'Projelerim',
|
||||||
|
'Columns' => 'Sütunlar',
|
||||||
|
'Task' => 'Görev',
|
||||||
|
'Your are not member of any project.' => 'Hiç bir projenin üyesi değilsiniz.',
|
||||||
|
'Percentage' => 'Yüzde',
|
||||||
|
'Number of tasks' => 'Görev sayısı',
|
||||||
|
'Task distribution' => 'Görev dağılımı',
|
||||||
|
'Reportings' => 'Raporlar',
|
||||||
|
'Task repartition for "%s"' => '"%s" için görev dağılımı',
|
||||||
|
'Analytics' => 'Analiz',
|
||||||
|
'Subtask' => 'Alt görev',
|
||||||
|
'My subtasks' => 'Alt görevlerim',
|
||||||
|
'User repartition' => 'Kullanıcı dağılımı',
|
||||||
|
'User repartition for "%s"' => '"%s" için kullanıcı dağılımı',
|
||||||
|
'Clone this project' => 'Projenin kopyasını oluştur',
|
||||||
|
'Column removed successfully.' => 'Sütun başarıyla kaldırıldı.',
|
||||||
|
'Edit Project' => 'Projeyi düzenle',
|
||||||
|
'Github Issue' => 'Github Issue',
|
||||||
|
'Not enough data to show the graph.' => 'Grafik gösterimi için yeterli veri yok.',
|
||||||
|
'Previous' => 'Önceki',
|
||||||
|
'The id must be an integer' => 'ID bir tamsayı olmalı',
|
||||||
|
'The project id must be an integer' => 'Proje numarası bir tam sayı olmalı',
|
||||||
|
'The status must be an integer' => 'Durum bir tam sayı olmalı',
|
||||||
|
'The subtask id is required' => 'Alt görev numarası gerekli',
|
||||||
|
'The subtask id must be an integer' => 'Alt görev numarası bir tam sayı olmalı',
|
||||||
|
'The task id is required' => 'Görev numarası gerekli',
|
||||||
|
'The task id must be an integer' => 'Görev numarası bir tam sayı olmalı',
|
||||||
|
'The user id must be an integer' => 'Kullanıcı numarası bir tam sayı olmalı',
|
||||||
|
'This value is required' => 'Bu değer gerekli',
|
||||||
|
'This value must be numeric' => 'Bu değer sayı olmalı',
|
||||||
|
'Unable to create this task.' => 'Bu görev oluşturulamıyor.',
|
||||||
|
'Cumulative flow diagram' => 'Kümülatif akış diyagramı',
|
||||||
|
'Cumulative flow diagram for "%s"' => '"%s" için kümülatif akış diyagramı',
|
||||||
|
'Daily project summary' => 'Günlük proje özeti',
|
||||||
|
'Daily project summary export' => 'Günlük proje özetini dışa aktar',
|
||||||
|
'Daily project summary export for "%s"' => '"%s" için günlük proje özetinin dışa',
|
||||||
|
'Exports' => 'Dışa aktarımlar',
|
||||||
|
'This export contains the number of tasks per column grouped per day.' => 'Bu dışa aktarım günlük gruplanmış olarak her sütundaki görev sayısını içerir.',
|
||||||
|
'Nothing to preview...' => 'Önizleme yapılacak bir şey yok ...',
|
||||||
|
'Preview' => 'Önizleme',
|
||||||
|
'Write' => 'Değiştir',
|
||||||
|
'Active swimlanes' => 'Aktif Kulvar',
|
||||||
|
'Add a new swimlane' => 'Yeni bir Kulvar ekle',
|
||||||
|
'Change default swimlane' => 'Varsayılan Kulvarı değiştir',
|
||||||
|
'Default swimlane' => 'Varsayılan Kulvar',
|
||||||
|
'Do you really want to remove this swimlane: "%s"?' => 'Bu Kulvarı silmek istediğinize emin misiniz?: "%s"?',
|
||||||
|
'Inactive swimlanes' => 'Pasif Kulvarlar',
|
||||||
|
'Set project manager' => 'Proje yöneticisi olarak ata',
|
||||||
|
'Set project member' => 'Proje üyesi olarak ata',
|
||||||
|
'Remove a swimlane' => 'Kulvarı sil',
|
||||||
|
'Rename' => 'Yeniden adlandır',
|
||||||
|
'Show default swimlane' => 'Varsayılan Kulvarı göster',
|
||||||
|
'Swimlane modification for the project "%s"' => '"% s" Projesi için Kulvar değişikliği',
|
||||||
|
'Swimlane not found.' => 'Kulvar bulunamadı',
|
||||||
|
'Swimlane removed successfully.' => 'Kulvar başarıyla kaldırıldı.',
|
||||||
|
'Swimlanes' => 'Kulvarlar',
|
||||||
|
'Swimlane updated successfully.' => 'Kulvar başarıyla güncellendi.',
|
||||||
|
'The default swimlane have been updated successfully.' => 'Varsayılan Kulvarlar başarıyla güncellendi.',
|
||||||
|
'Unable to create your swimlane.' => 'Bu Kulvarı oluşturmak mümkün değil.',
|
||||||
|
'Unable to remove this swimlane.' => 'Bu Kulvarı silmek mümkün değil.',
|
||||||
|
'Unable to update this swimlane.' => 'Bu Kulvarı değiştirmek mümkün değil.',
|
||||||
|
'Your swimlane have been created successfully.' => 'Kulvar başarıyla oluşturuldu.',
|
||||||
|
'Example: "Bug, Feature Request, Improvement"' => 'Örnek: "Sorun, Özellik talebi, İyileştirme"',
|
||||||
|
'Default categories for new projects (Comma-separated)' => 'Yeni projeler için varsayılan kategoriler (Virgül ile ayrılmış)',
|
||||||
|
// 'Gitlab commit received' => '',
|
||||||
|
// 'Gitlab issue opened' => '',
|
||||||
|
// 'Gitlab issue closed' => '',
|
||||||
|
// 'Gitlab webhooks' => '',
|
||||||
|
// 'Help on Gitlab webhooks' => '',
|
||||||
|
'Integrations' => 'Entegrasyon',
|
||||||
|
'Integration with third-party services' => 'Dış servislerle entegrasyon',
|
||||||
|
'Role for this project' => 'Bu proje için rol',
|
||||||
|
'Project manager' => 'Proje Yöneticisi',
|
||||||
|
'Project member' => 'Proje Üyesi',
|
||||||
|
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Bir Proje Yöneticisi proje ayarlarını değiştirebilir ve bir üyeden daha fazla yetkiye sahiptir.',
|
||||||
|
// 'Gitlab Issue' => '',
|
||||||
|
'Subtask Id' => 'Alt görev No:',
|
||||||
|
'Subtasks' => 'Alt görevler',
|
||||||
|
'Subtasks Export' => 'Alt görevleri dışa aktar',
|
||||||
|
'Subtasks exportation for "%s"' => '"%s" için alt görevleri dışa aktarımı',
|
||||||
|
'Task Title' => 'Görev Başlığı',
|
||||||
|
'Untitled' => 'Başlıksız',
|
||||||
|
'Application default' => 'Uygulama varsayılanları',
|
||||||
|
'Language:' => 'Dil:',
|
||||||
|
'Timezone:' => 'Saat dilimi:',
|
||||||
|
'All columns' => 'Tüm sütunlar',
|
||||||
|
'Calendar for "%s"' => '"%s" için takvim',
|
||||||
|
'Filter by column' => 'Sütuna göre filtrele',
|
||||||
|
'Filter by status' => 'Duruma göre filtrele',
|
||||||
|
'Calendar' => 'Takvim',
|
||||||
|
'Next' => 'Sonraki',
|
||||||
|
'#%d' => '#%d',
|
||||||
|
'Filter by color' => 'Renklere göre filtrele',
|
||||||
|
'Filter by swimlane' => 'Kulvara göre filtrele',
|
||||||
|
'All swimlanes' => 'Tüm Kulvarlar',
|
||||||
|
'All colors' => 'Tüm Renkler',
|
||||||
|
'All status' => 'Tüm Durumlar',
|
||||||
|
'Add a comment logging moving the task between columns' => 'Sütun değiştiğinde kayıt olarak yorum ekle',
|
||||||
|
'Moved to column %s' => '%s Sütununa taşındı',
|
||||||
|
'Change description' => 'Açıklamayı değiştir',
|
||||||
|
'User dashboard' => 'Kullanıcı Anasayfası',
|
||||||
|
'Allow only one subtask in progress at the same time for a user' => 'Bir kullanıcı için aynı anda yalnızca bir alt göreve izin ver',
|
||||||
|
'Edit column "%s"' => '"%s" sütununu değiştir',
|
||||||
|
'Enable time tracking for subtasks' => 'Alt görevler için zaman takibini etkinleştir',
|
||||||
|
'Select the new status of the subtask: "%s"' => '"%s" alt görevi için yeni durum seçin.',
|
||||||
|
'Subtask timesheet' => 'Alt görev için zaman takip tablosu',
|
||||||
|
'There is nothing to show.' => 'Gösterilecek hiçbir şey yok.',
|
||||||
|
'Time Tracking' => 'Zaman takibi',
|
||||||
|
'You already have one subtask in progress' => 'Zaten işlemde olan bir alt görev var',
|
||||||
|
'Which parts of the project do you want to duplicate?' => 'Projenin hangi kısımlarının kopyasını oluşturmak istiyorsunuz?',
|
||||||
|
'Change dashboard view' => 'Anasayfa görünümünü değiştir',
|
||||||
|
'Show/hide activities' => 'Aktiviteleri göster/gizle',
|
||||||
|
'Show/hide projects' => 'Projeleri göster/gizle',
|
||||||
|
'Show/hide subtasks' => 'Alt görevleri göster/gizle',
|
||||||
|
'Show/hide tasks' => 'Görevleri göster/gizle',
|
||||||
|
'Disable login form' => 'Giriş formunu devre dışı bırak',
|
||||||
|
'Show/hide calendar' => 'Takvimi göster/gizle',
|
||||||
|
'User calendar' => 'Kullanıcı takvimi',
|
||||||
|
'Bitbucket commit received' => 'Bitbucket commit alındı',
|
||||||
|
'Bitbucket webhooks' => 'Bitbucket webhooks',
|
||||||
|
'Help on Bitbucket webhooks' => 'Bitbucket webhooks için yardım',
|
||||||
|
'Start' => 'Başlangıç',
|
||||||
|
'End' => 'Son',
|
||||||
|
'Task age in days' => 'Görev yaşı gün olarak',
|
||||||
|
'Days in this column' => 'Bu sütunda geçirilen gün',
|
||||||
|
'%dd' => '%dG',
|
||||||
|
'Add a link' => 'Link ekle',
|
||||||
|
'Add a new link' => 'Yeni link ekle',
|
||||||
|
'Do you really want to remove this link: "%s"?' => '"%s" linkini gerçekten silmek istiyor musunuz?',
|
||||||
|
'Do you really want to remove this link with task #%d?' => '#%d numaralı görev ile linki gerçekten silmek istiyor musunuz?',
|
||||||
|
'Field required' => 'Bu alan gerekli',
|
||||||
|
'Link added successfully.' => 'Link başarıyla eklendi.',
|
||||||
|
'Link updated successfully.' => 'Link başarıyla güncellendi.',
|
||||||
|
'Link removed successfully.' => 'Link başarıyla silindi.',
|
||||||
|
'Link labels' => 'Link etiketleri',
|
||||||
|
'Link modification' => 'Link değiştirme',
|
||||||
|
'Links' => 'Links',
|
||||||
|
'Link settings' => 'Link ayarları',
|
||||||
|
'Opposite label' => 'Zıt etiket',
|
||||||
|
'Remove a link' => 'Bir link silmek',
|
||||||
|
'Task\'s links' => 'Görevin linkleri',
|
||||||
|
'The labels must be different' => 'Etiketler farklı olmalı',
|
||||||
|
'There is no link.' => 'Hiç bir bağ yok',
|
||||||
|
'This label must be unique' => 'Bu etiket tek olmalı',
|
||||||
|
'Unable to create your link.' => 'Link oluşturulamadı.',
|
||||||
|
'Unable to update your link.' => 'Link güncellenemiyor.',
|
||||||
|
'Unable to remove this link.' => 'Link kaldırılamıyor',
|
||||||
|
'relates to' => 'şununla ilgili',
|
||||||
|
'blocks' => 'şunu engelliyor',
|
||||||
|
'is blocked by' => 'şunun tarafından engelleniyor',
|
||||||
|
'duplicates' => 'şunun kopyasını oluşturuyor',
|
||||||
|
'is duplicated by' => 'şunun tarafından kopyası oluşturuluyor',
|
||||||
|
'is a child of' => 'şunun astı',
|
||||||
|
'is a parent of' => 'şunun üstü',
|
||||||
|
'targets milestone' => 'şu kilometre taşını hedefliyor',
|
||||||
|
'is a milestone of' => 'şunun için bir kilometre taşı',
|
||||||
|
'fixes' => 'düzeltiyor',
|
||||||
|
'is fixed by' => 'şunun tarafından düzeltildi',
|
||||||
|
'This task' => 'Bu görev',
|
||||||
|
'<1h' => '<1s',
|
||||||
|
'%dh' => '%ds',
|
||||||
|
// '%b %e' => '',
|
||||||
|
'Expand tasks' => 'Görevleri genişlet',
|
||||||
|
'Collapse tasks' => 'Görevleri daralt',
|
||||||
|
'Expand/collapse tasks' => 'Görevleri genişlet/daralt',
|
||||||
|
'Close dialog box' => 'İletiyi kapat',
|
||||||
|
'Submit a form' => 'Formu gönder',
|
||||||
|
'Board view' => 'Tablo görünümü',
|
||||||
|
'Keyboard shortcuts' => 'Klavye kısayolları',
|
||||||
|
'Open board switcher' => 'Tablo seçim listesini aç',
|
||||||
|
'Application' => 'Uygulama',
|
||||||
|
'Filter recently updated' => 'Son güncellenenleri göster',
|
||||||
|
'since %B %e, %Y at %k:%M %p' => '%B %e, %Y saat %k:%M %p\'den beri',
|
||||||
|
'More filters' => 'Daha fazla filtre',
|
||||||
|
'Compact view' => 'Ekrana sığdır',
|
||||||
|
'Horizontal scrolling' => 'Geniş görünüm',
|
||||||
|
'Compact/wide view' => 'Ekrana sığdır / Geniş görünüm',
|
||||||
|
// 'No results match:' => '',
|
||||||
|
// 'Remove hourly rate' => '',
|
||||||
|
// 'Do you really want to remove this hourly rate?' => '',
|
||||||
|
// 'Hourly rates' => '',
|
||||||
|
// 'Hourly rate' => '',
|
||||||
|
// 'Currency' => '',
|
||||||
|
// 'Effective date' => '',
|
||||||
|
// 'Add new rate' => '',
|
||||||
|
// 'Rate removed successfully.' => '',
|
||||||
|
// 'Unable to remove this rate.' => '',
|
||||||
|
// 'Unable to save the hourly rate.' => '',
|
||||||
|
// 'Hourly rate created successfully.' => '',
|
||||||
|
// 'Start time' => '',
|
||||||
|
// 'End time' => '',
|
||||||
|
// 'Comment' => '',
|
||||||
|
// 'All day' => '',
|
||||||
|
// 'Day' => '',
|
||||||
|
// 'Manage timetable' => '',
|
||||||
|
// 'Overtime timetable' => '',
|
||||||
|
// 'Time off timetable' => '',
|
||||||
|
// 'Timetable' => '',
|
||||||
|
// 'Work timetable' => '',
|
||||||
|
// 'Week timetable' => '',
|
||||||
|
// 'Day timetable' => '',
|
||||||
|
// 'From' => '',
|
||||||
|
// 'To' => '',
|
||||||
|
// 'Time slot created successfully.' => '',
|
||||||
|
// 'Unable to save this time slot.' => '',
|
||||||
|
// 'Time slot removed successfully.' => '',
|
||||||
|
// 'Unable to remove this time slot.' => '',
|
||||||
|
// 'Do you really want to remove this time slot?' => '',
|
||||||
|
// 'Remove time slot' => '',
|
||||||
|
// 'Add new time slot' => '',
|
||||||
|
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
||||||
|
// 'Files' => '',
|
||||||
|
// 'Images' => '',
|
||||||
|
// 'Private project' => '',
|
||||||
|
// 'Amount' => '',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
// 'Budget' => '',
|
||||||
|
// 'Budget line' => '',
|
||||||
|
// 'Budget line removed successfully.' => '',
|
||||||
|
// 'Budget lines' => '',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
// 'Cost' => '',
|
||||||
|
// 'Cost breakdown' => '',
|
||||||
|
// 'Custom Stylesheet' => '',
|
||||||
|
// 'download' => '',
|
||||||
|
// 'Do you really want to remove this budget line?' => '',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
// 'Expenses' => '',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
// 'New budget line' => '',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
// 'Remove a budget line' => '',
|
||||||
|
// 'Remove budget line' => '',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
// 'The budget line have been created successfully.' => '',
|
||||||
|
// 'Unable to create the budget line.' => '',
|
||||||
|
// 'Unable to remove this budget line.' => '',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
// 'Remaining' => '',
|
||||||
|
// 'Destination column' => '',
|
||||||
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
|
// 'Source column' => '',
|
||||||
|
// 'Show subtask estimates in the user calendar' => '',
|
||||||
|
// 'Transitions' => '',
|
||||||
|
// 'Executer' => '',
|
||||||
|
// 'Time spent in the column' => '',
|
||||||
|
// 'Task transitions' => '',
|
||||||
|
// 'Task transitions export' => '',
|
||||||
|
// 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '',
|
||||||
|
// 'Currency rates' => '',
|
||||||
|
// 'Rate' => '',
|
||||||
|
// 'Change reference currency' => '',
|
||||||
|
// 'Add a new currency rate' => '',
|
||||||
|
// 'Currency rates are used to calculate project budget.' => '',
|
||||||
|
// 'Reference currency' => '',
|
||||||
|
// 'The currency rate have been added successfully.' => '',
|
||||||
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
|
// 'Send notifications to Hipchat' => '',
|
||||||
|
// 'API URL' => '',
|
||||||
|
// 'Room API ID or name' => '',
|
||||||
|
// 'Room notification token' => '',
|
||||||
|
// 'Help on Hipchat integration' => '',
|
||||||
|
// 'Enable Gravatar images' => '',
|
||||||
|
// 'Information' => '',
|
||||||
|
// 'Check two factor authentication code' => '',
|
||||||
|
// 'The two factor authentication code is not valid.' => '',
|
||||||
|
// 'The two factor authentication code is valid.' => '',
|
||||||
|
// 'Code' => '',
|
||||||
|
// 'Two factor authentication' => '',
|
||||||
|
// 'Enable/disable two factor authentication' => '',
|
||||||
|
// 'This QR code contains the key URI: ' => '',
|
||||||
|
// 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '',
|
||||||
|
// 'Check my code' => '',
|
||||||
|
// 'Secret key: ' => '',
|
||||||
|
// 'Test your device' => '',
|
||||||
|
// 'Assign a color when the task is moved to a specific column' => '',
|
||||||
|
);
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'number.decimals_separator' => '.',
|
||||||
|
'number.thousands_separator' => ',',
|
||||||
'None' => '无',
|
'None' => '无',
|
||||||
'edit' => '编辑',
|
'edit' => '编辑',
|
||||||
'Edit' => '编辑',
|
'Edit' => '编辑',
|
||||||
|
@ -379,7 +381,7 @@ return array(
|
||||||
'Created by %s' => '创建者:%s',
|
'Created by %s' => '创建者:%s',
|
||||||
'Last modified on %B %e, %Y at %k:%M %p' => '最后修改:%Y/%m/%d/ %H:%M',
|
'Last modified on %B %e, %Y at %k:%M %p' => '最后修改:%Y/%m/%d/ %H:%M',
|
||||||
'Tasks Export' => '任务导出',
|
'Tasks Export' => '任务导出',
|
||||||
'Tasks exportation for "%s"' => '导出任务"%s"',
|
'Tasks exportation for "%s"' => '导出"%s"的任务',
|
||||||
'Start Date' => '开始时间',
|
'Start Date' => '开始时间',
|
||||||
'End Date' => '结束时间',
|
'End Date' => '结束时间',
|
||||||
'Execute' => '执行',
|
'Execute' => '执行',
|
||||||
|
@ -408,13 +410,13 @@ return array(
|
||||||
'Comment updated' => '更新了评论',
|
'Comment updated' => '更新了评论',
|
||||||
'New comment posted by %s' => '%s 的新评论',
|
'New comment posted by %s' => '%s 的新评论',
|
||||||
'List of due tasks for the project "%s"' => '项目"%s"的到期任务列表',
|
'List of due tasks for the project "%s"' => '项目"%s"的到期任务列表',
|
||||||
// 'New attachment' => '',
|
'New attachment' => '新建附件',
|
||||||
// 'New comment' => '',
|
'New comment' => '新建评论',
|
||||||
// 'New subtask' => '',
|
'New subtask' => '新建子任务',
|
||||||
// 'Subtask updated' => '',
|
'Subtask updated' => '子任务更新',
|
||||||
// 'Task updated' => '',
|
'Task updated' => '任务更新',
|
||||||
// 'Task closed' => '',
|
'Task closed' => '任务关闭',
|
||||||
// 'Task opened' => '',
|
'Task opened' => '任务开启',
|
||||||
'[%s][Due tasks]' => '[%s][到期任务]',
|
'[%s][Due tasks]' => '[%s][到期任务]',
|
||||||
'[Kanboard] Notification' => '[Kanboard] 通知',
|
'[Kanboard] Notification' => '[Kanboard] 通知',
|
||||||
'I want to receive notifications only for those projects:' => '我仅需要收到下面项目的通知:',
|
'I want to receive notifications only for those projects:' => '我仅需要收到下面项目的通知:',
|
||||||
|
@ -498,9 +500,9 @@ return array(
|
||||||
'Task assignee change' => '任务分配变更',
|
'Task assignee change' => '任务分配变更',
|
||||||
'%s change the assignee of the task #%d to %s' => '%s 将任务 #%d 分配给了 %s',
|
'%s change the assignee of the task #%d to %s' => '%s 将任务 #%d 分配给了 %s',
|
||||||
'%s changed the assignee of the task %s to %s' => '%s 将任务 %s 分配给 %s',
|
'%s changed the assignee of the task %s to %s' => '%s 将任务 %s 分配给 %s',
|
||||||
// 'Column Change' => '',
|
'Column Change' => '栏目变更',
|
||||||
// 'Position Change' => '',
|
'Position Change' => '位置变更',
|
||||||
// 'Assignee Change' => '',
|
'Assignee Change' => '负责人变更',
|
||||||
'New password for the user "%s"' => '用户"%s"的新密码',
|
'New password for the user "%s"' => '用户"%s"的新密码',
|
||||||
'Choose an event' => '选择一个事件',
|
'Choose an event' => '选择一个事件',
|
||||||
'Github commit received' => '收到了Github提交',
|
'Github commit received' => '收到了Github提交',
|
||||||
|
@ -607,8 +609,8 @@ return array(
|
||||||
'Default swimlane' => '默认泳道',
|
'Default swimlane' => '默认泳道',
|
||||||
'Do you really want to remove this swimlane: "%s"?' => '确定要删除泳道:"%s"?',
|
'Do you really want to remove this swimlane: "%s"?' => '确定要删除泳道:"%s"?',
|
||||||
'Inactive swimlanes' => '非活动泳道',
|
'Inactive swimlanes' => '非活动泳道',
|
||||||
// 'Set project manager' => '',
|
'Set project manager' => '设为项目经理',
|
||||||
// 'Set project member' => '',
|
'Set project member' => '设为项目成员',
|
||||||
'Remove a swimlane' => '删除泳道',
|
'Remove a swimlane' => '删除泳道',
|
||||||
'Rename' => '重命名',
|
'Rename' => '重命名',
|
||||||
'Show default swimlane' => '显示默认泳道',
|
'Show default swimlane' => '显示默认泳道',
|
||||||
|
@ -622,92 +624,92 @@ return array(
|
||||||
'Unable to remove this swimlane.' => '无法删除此泳道',
|
'Unable to remove this swimlane.' => '无法删除此泳道',
|
||||||
'Unable to update this swimlane.' => '无法更新此泳道',
|
'Unable to update this swimlane.' => '无法更新此泳道',
|
||||||
'Your swimlane have been created successfully.' => '已经成功创建泳道。',
|
'Your swimlane have been created successfully.' => '已经成功创建泳道。',
|
||||||
// 'Example: "Bug, Feature Request, Improvement"' => '',
|
'Example: "Bug, Feature Request, Improvement"' => '示例:“缺陷,功能需求,提升',
|
||||||
// 'Default categories for new projects (Comma-separated)' => '',
|
'Default categories for new projects (Comma-separated)' => '新项目的默认分类(用逗号分隔)',
|
||||||
// 'Gitlab commit received' => '',
|
'Gitlab commit received' => '收到 Gitlab 提交',
|
||||||
// 'Gitlab issue opened' => '',
|
'Gitlab issue opened' => '开启 Gitlab 问题',
|
||||||
// 'Gitlab issue closed' => '',
|
'Gitlab issue closed' => '关闭 Gitlab 问题',
|
||||||
// 'Gitlab webhooks' => '',
|
'Gitlab webhooks' => 'Gitlab 网络钩子',
|
||||||
// 'Help on Gitlab webhooks' => '',
|
'Help on Gitlab webhooks' => 'Gitlab 网络钩子帮助',
|
||||||
// 'Integrations' => '',
|
'Integrations' => '整合',
|
||||||
// 'Integration with third-party services' => '',
|
'Integration with third-party services' => '与第三方服务进行整合',
|
||||||
// 'Role for this project' => '',
|
'Role for this project' => '项目角色',
|
||||||
// 'Project manager' => '',
|
'Project manager' => '项目管理员',
|
||||||
// 'Project member' => '',
|
'Project member' => '项目成员',
|
||||||
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
|
'A project manager can change the settings of the project and have more privileges than a standard user.' => '项目经理可以修改项目的设置,比标准用户多了一些权限',
|
||||||
// 'Gitlab Issue' => '',
|
'Gitlab Issue' => 'Gitlab 问题',
|
||||||
// 'Subtask Id' => '',
|
'Subtask Id' => '子任务 Id',
|
||||||
// 'Subtasks' => '',
|
'Subtasks' => '子任务',
|
||||||
// 'Subtasks Export' => '',
|
'Subtasks Export' => '子任务导出',
|
||||||
// 'Subtasks exportation for "%s"' => '',
|
'Subtasks exportation for "%s"' => '导出"%s"的子任务',
|
||||||
// 'Task Title' => '',
|
'Task Title' => '任务标题',
|
||||||
// 'Untitled' => '',
|
'Untitled' => '无标题',
|
||||||
// 'Application default' => '',
|
'Application default' => '程序默认',
|
||||||
// 'Language:' => '',
|
'Language:' => '语言:',
|
||||||
// 'Timezone:' => '',
|
'Timezone:' => '时区:',
|
||||||
// 'All columns' => '',
|
'All columns' => '全部栏目',
|
||||||
// 'Calendar for "%s"' => '',
|
'Calendar for "%s"' => '"%s"的日程表',
|
||||||
// 'Filter by column' => '',
|
'Filter by column' => '按栏目过滤',
|
||||||
// 'Filter by status' => '',
|
'Filter by status' => '按状态过滤',
|
||||||
// 'Calendar' => '',
|
'Calendar' => '日程表',
|
||||||
// 'Next' => '',
|
'Next' => '前进',
|
||||||
// '#%d' => '',
|
'#%d' => '#%d',
|
||||||
// 'Filter by color' => '',
|
'Filter by color' => '按颜色过滤',
|
||||||
// 'Filter by swimlane' => '',
|
'Filter by swimlane' => '按泳道过滤',
|
||||||
// 'All swimlanes' => '',
|
'All swimlanes' => '全部泳道',
|
||||||
// 'All colors' => '',
|
'All colors' => '全部颜色',
|
||||||
// 'All status' => '',
|
'All status' => '全部状态',
|
||||||
// 'Add a comment logging moving the task between columns' => '',
|
'Add a comment logging moving the task between columns' => '在不同栏目间移动任务时添加一个评论',
|
||||||
// 'Moved to column %s' => '',
|
'Moved to column %s' => '移动到栏目 %s',
|
||||||
// 'Change description' => '',
|
'Change description' => '修改描述',
|
||||||
// 'User dashboard' => '',
|
'User dashboard' => '用户仪表板',
|
||||||
// 'Allow only one subtask in progress at the same time for a user' => '',
|
'Allow only one subtask in progress at the same time for a user' => '每用户同时仅有一个活动子任务',
|
||||||
// 'Edit column "%s"' => '',
|
'Edit column "%s"' => '编辑栏目"%s"',
|
||||||
// 'Enable time tracking for subtasks' => '',
|
'Enable time tracking for subtasks' => '启用子任务的时间记录',
|
||||||
// 'Select the new status of the subtask: "%s"' => '',
|
'Select the new status of the subtask: "%s"' => '选择子任务的新状态:"%s"',
|
||||||
// 'Subtask timesheet' => '',
|
'Subtask timesheet' => '子任务时间',
|
||||||
// 'There is nothing to show.' => '',
|
'There is nothing to show.' => '无内容。',
|
||||||
// 'Time Tracking' => '',
|
'Time Tracking' => '时间记录',
|
||||||
// 'You already have one subtask in progress' => '',
|
'You already have one subtask in progress' => '你已经有了一个进行中的子任务',
|
||||||
// 'Which parts of the project do you want to duplicate?' => '',
|
'Which parts of the project do you want to duplicate?' => '要复制项目的哪些内容?',
|
||||||
// 'Change dashboard view' => '',
|
'Change dashboard view' => '修改仪表板视图',
|
||||||
// 'Show/hide activities' => '',
|
'Show/hide activities' => '显示/隐藏活动',
|
||||||
// 'Show/hide projects' => '',
|
'Show/hide projects' => '显示/隐藏项目',
|
||||||
// 'Show/hide subtasks' => '',
|
'Show/hide subtasks' => '显示/隐藏子任务',
|
||||||
// 'Show/hide tasks' => '',
|
'Show/hide tasks' => '显示/隐藏任务',
|
||||||
// 'Disable login form' => '',
|
'Disable login form' => '禁用登录界面',
|
||||||
// 'Show/hide calendar' => '',
|
'Show/hide calendar' => '显示/隐藏日程表',
|
||||||
// 'User calendar' => '',
|
'User calendar' => '用户日程表',
|
||||||
// 'Bitbucket commit received' => '',
|
'Bitbucket commit received' => '收到Bitbucket提交',
|
||||||
// 'Bitbucket webhooks' => '',
|
'Bitbucket webhooks' => 'Bitbucket网络钩子',
|
||||||
// 'Help on Bitbucket webhooks' => '',
|
'Help on Bitbucket webhooks' => 'Bitbucket网络钩子帮助',
|
||||||
// 'Start' => '',
|
'Start' => '开始',
|
||||||
// 'End' => '',
|
'End' => '结束',
|
||||||
// 'Task age in days' => '',
|
'Task age in days' => '任务存在天数',
|
||||||
// 'Days in this column' => '',
|
'Days in this column' => '在此栏目的天数',
|
||||||
// '%dd' => '',
|
'%dd' => '%d天',
|
||||||
// 'Add a link' => '',
|
'Add a link' => '添加一个关联',
|
||||||
// 'Add a new link' => '',
|
'Add a new link' => '添加一个新关联',
|
||||||
// 'Do you really want to remove this link: "%s"?' => '',
|
'Do you really want to remove this link: "%s"?' => '确认要删除此关联吗:"%s"?',
|
||||||
// 'Do you really want to remove this link with task #%d?' => '',
|
'Do you really want to remove this link with task #%d?' => '确认要删除到任务 #%d 的关联吗?',
|
||||||
// 'Field required' => '',
|
'Field required' => '必须的字段',
|
||||||
// 'Link added successfully.' => '',
|
'Link added successfully.' => '成功添加关联。',
|
||||||
// 'Link updated successfully.' => '',
|
'Link updated successfully.' => '成功更新关联。',
|
||||||
// 'Link removed successfully.' => '',
|
'Link removed successfully.' => '成功删除关联。',
|
||||||
// 'Link labels' => '',
|
'Link labels' => '关联标签',
|
||||||
// 'Link modification' => '',
|
'Link modification' => '关联修改',
|
||||||
// 'Links' => '',
|
'Links' => '关联',
|
||||||
// 'Link settings' => '',
|
'Link settings' => '关联设置',
|
||||||
// 'Opposite label' => '',
|
'Opposite label' => '反向标签',
|
||||||
// 'Remove a link' => '',
|
'Remove a link' => '删除关联',
|
||||||
// 'Task\'s links' => '',
|
'Task\'s links' => '任务的关联',
|
||||||
// 'The labels must be different' => '',
|
'The labels must be different' => '标签不能一样',
|
||||||
// 'There is no link.' => '',
|
'There is no link.' => '没有关联',
|
||||||
// 'This label must be unique' => '',
|
'This label must be unique' => '关联必须唯一',
|
||||||
// 'Unable to create your link.' => '',
|
'Unable to create your link.' => '无法创建关联。',
|
||||||
// 'Unable to update your link.' => '',
|
'Unable to update your link.' => '无法更新关联。',
|
||||||
// 'Unable to remove this link.' => '',
|
'Unable to remove this link.' => '无法删除关联。',
|
||||||
// 'relates to' => '',
|
'relates to' => '关联到',
|
||||||
// 'blocks' => '',
|
// 'blocks' => '',
|
||||||
// 'is blocked by' => '',
|
// 'is blocked by' => '',
|
||||||
// 'duplicates' => '',
|
// 'duplicates' => '',
|
||||||
|
@ -718,20 +720,130 @@ return array(
|
||||||
// 'is a milestone of' => '',
|
// 'is a milestone of' => '',
|
||||||
// 'fixes' => '',
|
// 'fixes' => '',
|
||||||
// 'is fixed by' => '',
|
// 'is fixed by' => '',
|
||||||
// 'This task' => '',
|
'This task' => '此任务',
|
||||||
// '<1h' => '',
|
'<1h' => '<1h',
|
||||||
// '%dh' => '',
|
'%dh' => '%h',
|
||||||
// '%b %e' => '',
|
// '%b %e' => '',
|
||||||
// 'Expand tasks' => '',
|
'Expand tasks' => '展开任务',
|
||||||
// 'Collapse tasks' => '',
|
'Collapse tasks' => '收缩任务',
|
||||||
// 'Expand/collapse tasks' => '',
|
'Expand/collapse tasks' => '展开/收缩任务',
|
||||||
// 'Close dialog box' => '',
|
'Close dialog box' => '关闭对话框',
|
||||||
// 'Submit a form' => '',
|
'Submit a form' => '提交表单',
|
||||||
// 'Board view' => '',
|
'Board view' => '面板视图',
|
||||||
// 'Keyboard shortcuts' => '',
|
'Keyboard shortcuts' => '键盘快捷方式',
|
||||||
// 'Open board switcher' => '',
|
'Open board switcher' => '打开面板切换器',
|
||||||
// 'Application' => '',
|
'Application' => '应用程序',
|
||||||
// 'Filter recently updated' => '',
|
'Filter recently updated' => '过滤最近的更新',
|
||||||
// 'since %B %e, %Y at %k:%M %p' => '',
|
// 'since %B %e, %Y at %k:%M %p' => '',
|
||||||
// 'More filters' => '',
|
'More filters' => '更多过滤',
|
||||||
|
'Compact view' => '紧凑视图',
|
||||||
|
'Horizontal scrolling' => '水平滚动',
|
||||||
|
'Compact/wide view' => '紧凑/宽视图',
|
||||||
|
'No results match:' => '无匹配结果:',
|
||||||
|
'Remove hourly rate' => '删除小时工资',
|
||||||
|
'Do you really want to remove this hourly rate?' => '确定要删除此计时工资吗?',
|
||||||
|
'Hourly rates' => '小时工资',
|
||||||
|
'Hourly rate' => '小时工资',
|
||||||
|
'Currency' => '货币',
|
||||||
|
'Effective date' => '开始时间',
|
||||||
|
'Add new rate' => '添加小时工资',
|
||||||
|
'Rate removed successfully.' => '成功删除工资。',
|
||||||
|
'Unable to remove this rate.' => '无法删除此小时工资。',
|
||||||
|
'Unable to save the hourly rate.' => '无法删除小时工资。',
|
||||||
|
'Hourly rate created successfully.' => '成功创建小时工资。',
|
||||||
|
'Start time' => '开始时间',
|
||||||
|
'End time' => '结束时1间',
|
||||||
|
'Comment' => '注释',
|
||||||
|
'All day' => '全天',
|
||||||
|
'Day' => '日期',
|
||||||
|
'Manage timetable' => '管理时间表',
|
||||||
|
'Overtime timetable' => '',
|
||||||
|
'Time off timetable' => '加班时间表',
|
||||||
|
'Timetable' => '时间表',
|
||||||
|
'Work timetable' => '工作时间表',
|
||||||
|
'Week timetable' => '周时间表',
|
||||||
|
'Day timetable' => '日时间表',
|
||||||
|
'From' => '从',
|
||||||
|
'To' => '到',
|
||||||
|
'Time slot created successfully.' => '成功创建时间段。',
|
||||||
|
'Unable to save this time slot.' => '无法保存此时间段。',
|
||||||
|
'Time slot removed successfully.' => '成功删除时间段。',
|
||||||
|
'Unable to remove this time slot.' => '无法删除此时间段。',
|
||||||
|
'Do you really want to remove this time slot?' => '确认要删除此时间段吗?',
|
||||||
|
'Remove time slot' => '删除时间段',
|
||||||
|
'Add new time slot' => '添加新时间段',
|
||||||
|
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '如果在放假和加班计划中选择全天,则会使用这里配置的时间段。',
|
||||||
|
'Files' => '文件',
|
||||||
|
'Images' => '图片',
|
||||||
|
'Private project' => '私人项目',
|
||||||
|
'Amount' => '数量',
|
||||||
|
// 'AUD - Australian Dollar' => '',
|
||||||
|
'Budget' => '预算',
|
||||||
|
'Budget line' => '预算线',
|
||||||
|
'Budget line removed successfully.' => '成功删除预算线',
|
||||||
|
'Budget lines' => '预算线',
|
||||||
|
// 'CAD - Canadian Dollar' => '',
|
||||||
|
// 'CHF - Swiss Francs' => '',
|
||||||
|
'Cost' => '成本',
|
||||||
|
'Cost breakdown' => '成本分解',
|
||||||
|
'Custom Stylesheet' => '自定义样式表',
|
||||||
|
'download' => '下载',
|
||||||
|
'Do you really want to remove this budget line?' => '确定要删除此预算线吗?',
|
||||||
|
// 'EUR - Euro' => '',
|
||||||
|
'Expenses' => '花费',
|
||||||
|
// 'GBP - British Pound' => '',
|
||||||
|
// 'INR - Indian Rupee' => '',
|
||||||
|
// 'JPY - Japanese Yen' => '',
|
||||||
|
'New budget line' => '新预算线',
|
||||||
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
|
'Remove a budget line' => '删除预算线',
|
||||||
|
'Remove budget line' => '删除预算线',
|
||||||
|
// 'RSD - Serbian dinar' => '',
|
||||||
|
'The budget line have been created successfully.' => '成功创建预算线。',
|
||||||
|
'Unable to create the budget line.' => '无法创建预算线。',
|
||||||
|
'Unable to remove this budget line.' => '无法删除此预算线。',
|
||||||
|
// 'USD - US Dollar' => '',
|
||||||
|
'Remaining' => '剩余',
|
||||||
|
'Destination column' => '目标栏目',
|
||||||
|
'Move the task to another column when assigned to a user' => '指定负责人时移动到其它栏目',
|
||||||
|
'Move the task to another column when assignee is cleared' => '移除负责人时移动到其它栏目',
|
||||||
|
'Source column' => '原栏目',
|
||||||
|
'Show subtask estimates in the user calendar' => '在用户日历中显示子任务预估',
|
||||||
|
'Transitions' => '变更',
|
||||||
|
'Executer' => '执行者',
|
||||||
|
'Time spent in the column' => '栏目中的时间消耗',
|
||||||
|
'Task transitions' => '任务变更',
|
||||||
|
'Task transitions export' => '导出任务变更',
|
||||||
|
'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '此报告记录任务的变更,包含日期、用户和时间消耗。',
|
||||||
|
'Currency rates' => '汇率',
|
||||||
|
'Rate' => '汇率',
|
||||||
|
'Change reference currency' => '修改参考货币',
|
||||||
|
'Add a new currency rate' => '添加新汇率',
|
||||||
|
'Currency rates are used to calculate project budget.' => '汇率会用来计算项目预算。',
|
||||||
|
'Reference currency' => '参考货币',
|
||||||
|
'The currency rate have been added successfully.' => '成功添加汇率。',
|
||||||
|
'Unable to add this currency rate.' => '无法添加此汇率',
|
||||||
|
'Send notifications to a Slack channel' => '发送通知到 Slack 频道',
|
||||||
|
'Webhook URL' => '网络钩子 URL',
|
||||||
|
'Help on Slack integration' => 'Slack 整合帮助',
|
||||||
|
'%s remove the assignee of the task %s' => '%s删除了任务%s的负责人',
|
||||||
|
'Send notifications to Hipchat' => '发送通知到 Hipchat',
|
||||||
|
'API URL' => 'API URL',
|
||||||
|
'Room API ID or name' => '房间 API ID 或名称',
|
||||||
|
'Room notification token' => '房间通知令牌',
|
||||||
|
'Help on Hipchat integration' => 'Hipchat 整合帮助',
|
||||||
|
'Enable Gravatar images' => '启用 Gravatar 图像',
|
||||||
|
'Information' => '信息',
|
||||||
|
'Check two factor authentication code' => '检查双重认证码',
|
||||||
|
'The two factor authentication code is not valid.' => '双重认证码不正确。',
|
||||||
|
'The two factor authentication code is valid.' => '双重认证码正确。',
|
||||||
|
'Code' => '认证码',
|
||||||
|
'Two factor authentication' => '双重认证',
|
||||||
|
'Enable/disable two factor authentication' => '启用/禁用双重认证',
|
||||||
|
'This QR code contains the key URI: ' => '此二维码包含密码 URI:',
|
||||||
|
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => '将密码保存到 TOTP 软件(例如Google 认证或 FreeOTP)',
|
||||||
|
'Check my code' => '检查我的认证码',
|
||||||
|
'Secret key: ' => '密码:',
|
||||||
|
'Test your device' => '测试设备',
|
||||||
|
'Assign a color when the task is moved to a specific column' => '任务移动到指定栏目时设置颜色',
|
||||||
);
|
);
|
||||||
|
|
|
@ -56,6 +56,7 @@ class Acl extends Base
|
||||||
'export' => array('tasks', 'subtasks', 'summary'),
|
'export' => array('tasks', 'subtasks', 'summary'),
|
||||||
'project' => array('edit', 'update', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'),
|
'project' => array('edit', 'update', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'),
|
||||||
'swimlane' => '*',
|
'swimlane' => '*',
|
||||||
|
'budget' => '*',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +71,8 @@ class Acl extends Base
|
||||||
'config' => '*',
|
'config' => '*',
|
||||||
'link' => '*',
|
'link' => '*',
|
||||||
'project' => array('remove'),
|
'project' => array('remove'),
|
||||||
|
'hourlyrate' => '*',
|
||||||
|
'currency' => '*',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,6 +45,9 @@ class Action extends Base
|
||||||
'TaskAssignCurrentUser' => t('Assign the task to the person who does the action'),
|
'TaskAssignCurrentUser' => t('Assign the task to the person who does the action'),
|
||||||
'TaskDuplicateAnotherProject' => t('Duplicate the task to another project'),
|
'TaskDuplicateAnotherProject' => t('Duplicate the task to another project'),
|
||||||
'TaskMoveAnotherProject' => t('Move the task to another project'),
|
'TaskMoveAnotherProject' => t('Move the task to another project'),
|
||||||
|
'TaskMoveColumnAssigned' => t('Move the task to another column when assigned to a user'),
|
||||||
|
'TaskMoveColumnUnAssigned' => t('Move the task to another column when assignee is cleared'),
|
||||||
|
'TaskAssignColorColumn' => t('Assign a color when the task is moved to a specific column'),
|
||||||
'TaskAssignColorUser' => t('Assign a color to a specific user'),
|
'TaskAssignColorUser' => t('Assign a color to a specific user'),
|
||||||
'TaskAssignColorCategory' => t('Assign automatically a color based on a category'),
|
'TaskAssignColorCategory' => t('Assign automatically a color based on a category'),
|
||||||
'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'),
|
'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'),
|
||||||
|
@ -211,7 +214,7 @@ class Action extends Base
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $values Required parameters to save an action
|
* @param array $values Required parameters to save an action
|
||||||
* @return bool Success or not
|
* @return boolean|integer
|
||||||
*/
|
*/
|
||||||
public function create(array $values)
|
public function create(array $values)
|
||||||
{
|
{
|
||||||
|
@ -248,7 +251,7 @@ class Action extends Base
|
||||||
|
|
||||||
// $this->container['fileCache']->remove('proxy_action_getAll');
|
// $this->container['fileCache']->remove('proxy_action_getAll');
|
||||||
|
|
||||||
return true;
|
return $action_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Pimple\Container;
|
||||||
* @property \Model\Action $action
|
* @property \Model\Action $action
|
||||||
* @property \Model\Authentication $authentication
|
* @property \Model\Authentication $authentication
|
||||||
* @property \Model\Board $board
|
* @property \Model\Board $board
|
||||||
|
* @property \Model\Budget $budget
|
||||||
* @property \Model\Category $category
|
* @property \Model\Category $category
|
||||||
* @property \Model\Comment $comment
|
* @property \Model\Comment $comment
|
||||||
* @property \Model\CommentHistory $commentHistory
|
* @property \Model\CommentHistory $commentHistory
|
||||||
|
@ -42,7 +43,11 @@ use Pimple\Container;
|
||||||
* @property \Model\TaskLink $taskLink
|
* @property \Model\TaskLink $taskLink
|
||||||
* @property \Model\TaskPosition $taskPosition
|
* @property \Model\TaskPosition $taskPosition
|
||||||
* @property \Model\TaskValidator $taskValidator
|
* @property \Model\TaskValidator $taskValidator
|
||||||
* @property \Model\TimeTracking $timeTracking
|
* @property \Model\Timetable $timetable
|
||||||
|
* @property \Model\TimetableDay $timetableDay
|
||||||
|
* @property \Model\TimetableExtra $timetableExtra
|
||||||
|
* @property \Model\TimetableOff $timetableOfff
|
||||||
|
* @property \Model\TimetableWeek $timetableWeek
|
||||||
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
|
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
|
||||||
* @property \Model\User $user
|
* @property \Model\User $user
|
||||||
* @property \Model\UserSession $userSession
|
* @property \Model\UserSession $userSession
|
||||||
|
|
214
sources/app/Model/Budget.php
Normal file
214
sources/app/Model/Budget.php
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use DateInterval;
|
||||||
|
use DateTime;
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Budget
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Budget extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'budget_lines';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all budget lines for a project
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAll($project_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('project_id', $project_id)->desc('date')->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current total of the budget
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getTotal($project_id)
|
||||||
|
{
|
||||||
|
$result = $this->db->table(self::TABLE)->columns('SUM(amount) as total')->eq('project_id', $project_id)->findOne();
|
||||||
|
return isset($result['total']) ? (float) $result['total'] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get breakdown by tasks/subtasks/users
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @return \PicoDb\Table
|
||||||
|
*/
|
||||||
|
public function getSubtaskBreakdown($project_id)
|
||||||
|
{
|
||||||
|
return $this->db
|
||||||
|
->table(SubtaskTimeTracking::TABLE)
|
||||||
|
->columns(
|
||||||
|
SubtaskTimeTracking::TABLE.'.id',
|
||||||
|
SubtaskTimeTracking::TABLE.'.user_id',
|
||||||
|
SubtaskTimeTracking::TABLE.'.subtask_id',
|
||||||
|
SubtaskTimeTracking::TABLE.'.start',
|
||||||
|
SubtaskTimeTracking::TABLE.'.time_spent',
|
||||||
|
Subtask::TABLE.'.task_id',
|
||||||
|
Subtask::TABLE.'.title AS subtask_title',
|
||||||
|
Task::TABLE.'.title AS task_title',
|
||||||
|
Task::TABLE.'.project_id',
|
||||||
|
User::TABLE.'.username',
|
||||||
|
User::TABLE.'.name'
|
||||||
|
)
|
||||||
|
->join(Subtask::TABLE, 'id', 'subtask_id')
|
||||||
|
->join(Task::TABLE, 'id', 'task_id', Subtask::TABLE)
|
||||||
|
->join(User::TABLE, 'id', 'user_id')
|
||||||
|
->eq(Task::TABLE.'.project_id', $project_id)
|
||||||
|
->filter(array($this, 'applyUserRate'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gather necessary information to display the budget graph
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDailyBudgetBreakdown($project_id)
|
||||||
|
{
|
||||||
|
$out = array();
|
||||||
|
$in = $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->gt('amount', 0)->asc('date')->getAll('date', 'amount');
|
||||||
|
$time_slots = $this->getSubtaskBreakdown($project_id)->findAll();
|
||||||
|
|
||||||
|
foreach ($time_slots as $slot) {
|
||||||
|
$date = date('Y-m-d', $slot['start']);
|
||||||
|
|
||||||
|
if (! isset($out[$date])) {
|
||||||
|
$out[$date] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$out[$date] += $slot['cost'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = key($in) ?: key($out);
|
||||||
|
$end = new DateTime;
|
||||||
|
$left = 0;
|
||||||
|
$serie = array();
|
||||||
|
|
||||||
|
for ($today = new DateTime($start); $today <= $end; $today->add(new DateInterval('P1D'))) {
|
||||||
|
|
||||||
|
$date = $today->format('Y-m-d');
|
||||||
|
$today_in = isset($in[$date]) ? (int) $in[$date] : 0;
|
||||||
|
$today_out = isset($out[$date]) ? (int) $out[$date] : 0;
|
||||||
|
|
||||||
|
if ($today_in > 0 || $today_out > 0) {
|
||||||
|
|
||||||
|
$left += $today_in;
|
||||||
|
$left -= $today_out;
|
||||||
|
|
||||||
|
$serie[] = array(
|
||||||
|
'date' => $date,
|
||||||
|
'in' => $today_in,
|
||||||
|
'out' => -$today_out,
|
||||||
|
'left' => $left,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $serie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter callback to apply the rate according to the effective date
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $records
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function applyUserRate(array $records)
|
||||||
|
{
|
||||||
|
$rates = $this->hourlyRate->getAllByProject($records[0]['project_id']);
|
||||||
|
|
||||||
|
foreach ($records as &$record) {
|
||||||
|
|
||||||
|
$hourly_price = 0;
|
||||||
|
|
||||||
|
foreach ($rates as $rate) {
|
||||||
|
|
||||||
|
if ($rate['user_id'] == $record['user_id'] && date('Y-m-d', $rate['date_effective']) <= date('Y-m-d', $record['start'])) {
|
||||||
|
$hourly_price = $this->currency->getPrice($rate['currency'], $rate['rate']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$record['cost'] = $hourly_price * $record['time_spent'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $records;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new budget line in the database
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @param float $amount
|
||||||
|
* @param string $comment
|
||||||
|
* @param string $date
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create($project_id, $amount, $comment, $date = '')
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'project_id' => $project_id,
|
||||||
|
'amount' => $amount,
|
||||||
|
'comment' => $comment,
|
||||||
|
'date' => $date ?: date('Y-m-d'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->persist(self::TABLE, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a specific budget line
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $budget_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($budget_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $budget_id)->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('project_id', t('Field required')),
|
||||||
|
new Validators\Required('amount', t('Field required')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,7 +47,8 @@ class Comment extends Base
|
||||||
self::TABLE.'.user_id',
|
self::TABLE.'.user_id',
|
||||||
self::TABLE.'.comment',
|
self::TABLE.'.comment',
|
||||||
User::TABLE.'.username',
|
User::TABLE.'.username',
|
||||||
User::TABLE.'.name'
|
User::TABLE.'.name',
|
||||||
|
User::TABLE.'.email'
|
||||||
)
|
)
|
||||||
->join(User::TABLE, 'id', 'user_id')
|
->join(User::TABLE, 'id', 'user_id')
|
||||||
->orderBy(self::TABLE.'.date', 'ASC')
|
->orderBy(self::TABLE.'.date', 'ASC')
|
||||||
|
|
|
@ -21,6 +21,28 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
const TABLE = 'settings';
|
const TABLE = 'settings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get available currencies
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCurrencies()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'USD' => t('USD - US Dollar'),
|
||||||
|
'EUR' => t('EUR - Euro'),
|
||||||
|
'GBP' => t('GBP - British Pound'),
|
||||||
|
'CHF' => t('CHF - Swiss Francs'),
|
||||||
|
'CAD' => t('CAD - Canadian Dollar'),
|
||||||
|
'AUD' => t('AUD - Australian Dollar'),
|
||||||
|
'NZD' => t('NZD - New Zealand Dollar'),
|
||||||
|
'INR' => t('INR - Indian Rupee'),
|
||||||
|
'JPY' => t('JPY - Japanese Yen'),
|
||||||
|
'RSD' => t('RSD - Serbian dinar'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get available timezones
|
* Get available timezones
|
||||||
*
|
*
|
||||||
|
@ -58,11 +80,14 @@ class Config extends Base
|
||||||
'fr_FR' => 'Français',
|
'fr_FR' => 'Français',
|
||||||
'it_IT' => 'Italiano',
|
'it_IT' => 'Italiano',
|
||||||
'hu_HU' => 'Magyar',
|
'hu_HU' => 'Magyar',
|
||||||
|
'nl_NL' => 'Nederlands',
|
||||||
'pl_PL' => 'Polski',
|
'pl_PL' => 'Polski',
|
||||||
'pt_BR' => 'Português (Brasil)',
|
'pt_BR' => 'Português (Brasil)',
|
||||||
'ru_RU' => 'Русский',
|
'ru_RU' => 'Русский',
|
||||||
|
'sr_Latn_RS' => 'Srpski',
|
||||||
'fi_FI' => 'Suomi',
|
'fi_FI' => 'Suomi',
|
||||||
'sv_SE' => 'Svenska',
|
'sv_SE' => 'Svenska',
|
||||||
|
'tr_TR' => 'Türkçe',
|
||||||
'zh_CN' => '中文(简体)',
|
'zh_CN' => '中文(简体)',
|
||||||
'ja_JP' => '日本語',
|
'ja_JP' => '日本語',
|
||||||
'th_TH' => 'ไทย',
|
'th_TH' => 'ไทย',
|
||||||
|
@ -99,6 +124,7 @@ class Config extends Base
|
||||||
'zh_CN' => 'zh-cn',
|
'zh_CN' => 'zh-cn',
|
||||||
'ja_JP' => 'ja',
|
'ja_JP' => 'ja',
|
||||||
'th_TH' => 'th',
|
'th_TH' => 'th',
|
||||||
|
'tr_TR' => 'tr',
|
||||||
);
|
);
|
||||||
|
|
||||||
$lang = $this->getCurrentLanguage();
|
$lang = $this->getCurrentLanguage();
|
||||||
|
|
104
sources/app/Model/Currency.php
Normal file
104
sources/app/Model/Currency.php
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currency
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Currency extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'currencies';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all currency rates
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAll()
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the price for the reference currency
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getPrice($currency, $price)
|
||||||
|
{
|
||||||
|
static $rates = null;
|
||||||
|
$reference = $this->config->get('application_currency', 'USD');
|
||||||
|
|
||||||
|
if ($reference !== $currency) {
|
||||||
|
$rates = $rates === null ? $this->db->hashtable(self::TABLE)->getAll('currency', 'rate') : array();
|
||||||
|
$rate = isset($rates[$currency]) ? $rates[$currency] : 1;
|
||||||
|
|
||||||
|
return $rate * $price;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $price;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new currency rate
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $currency
|
||||||
|
* @param float $rate
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create($currency, $rate)
|
||||||
|
{
|
||||||
|
if ($this->db->table(self::TABLE)->eq('currency', $currency)->count() === 1) {
|
||||||
|
return $this->update($currency, $rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->persist(self::TABLE, compact('currency', 'rate'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a currency rate
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $currency
|
||||||
|
* @param float $rate
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function update($currency, $rate)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('currency', $currency)->update(array('rate' => $rate));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validate(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('currency', t('Field required')),
|
||||||
|
new Validators\Required('rate', t('Field required')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,47 @@ use DateTime;
|
||||||
*/
|
*/
|
||||||
class DateParser extends Base
|
class DateParser extends Base
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Return true if the date is within the date range
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param DateTime $date
|
||||||
|
* @param DateTime $start
|
||||||
|
* @param DateTime $end
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function withinDateRange(DateTime $date, DateTime $start, DateTime $end)
|
||||||
|
{
|
||||||
|
return $date >= $start && $date <= $end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total number of hours between 2 datetime objects
|
||||||
|
* Minutes are rounded to the nearest quarter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param DateTime $d1
|
||||||
|
* @param DateTime $d2
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getHours(DateTime $d1, DateTime $d2)
|
||||||
|
{
|
||||||
|
$seconds = $this->getRoundedSeconds(abs($d1->getTimestamp() - $d2->getTimestamp()));
|
||||||
|
return round($seconds / 3600, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Round the timestamp to the nearest quarter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $seconds Timestamp
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getRoundedSeconds($seconds)
|
||||||
|
{
|
||||||
|
return (int) round($seconds / (15 * 60)) * (15 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a timestamp if the given date format is correct otherwise return 0
|
* Return a timestamp if the given date format is correct otherwise return 0
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,7 +17,7 @@ class File extends Base
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
const TABLE = 'task_has_files';
|
const TABLE = 'files';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events
|
* Events
|
||||||
|
@ -112,6 +112,38 @@ class File extends Base
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all images for a given task
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllImages($task_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)
|
||||||
|
->eq('task_id', $task_id)
|
||||||
|
->eq('is_image', 1)
|
||||||
|
->asc('name')
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all files without images for a given task
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllDocuments($task_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)
|
||||||
|
->eq('task_id', $task_id)
|
||||||
|
->eq('is_image', 0)
|
||||||
|
->asc('name')
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a filename is an image
|
* Check if a filename is an image
|
||||||
*
|
*
|
||||||
|
@ -121,7 +153,17 @@ class File extends Base
|
||||||
*/
|
*/
|
||||||
public function isImage($filename)
|
public function isImage($filename)
|
||||||
{
|
{
|
||||||
return getimagesize($filename) !== false;
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
switch ($extension) {
|
||||||
|
case 'jpeg':
|
||||||
|
case 'jpg':
|
||||||
|
case 'png':
|
||||||
|
case 'gif':
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,7 +230,7 @@ class File extends Base
|
||||||
$task_id,
|
$task_id,
|
||||||
$original_filename,
|
$original_filename,
|
||||||
$destination_filename,
|
$destination_filename,
|
||||||
$this->isImage(FILES_DIR.$destination_filename)
|
$this->isImage($original_filename)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
121
sources/app/Model/HourlyRate.php
Normal file
121
sources/app/Model/HourlyRate.php
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hourly Rate
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class HourlyRate extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'hourly_rates';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all user rates for a given project
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllByProject($project_id)
|
||||||
|
{
|
||||||
|
$members = $this->projectPermission->getMembers($project_id);
|
||||||
|
|
||||||
|
if (empty($members)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->db->table(self::TABLE)->in('user_id', array_keys($members))->desc('date_effective')->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all rates for a given user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllByUser($user_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('user_id', $user_id)->desc('date_effective')->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current rate for a given user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getCurrentRate($user_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('user_id', $user_id)->desc('date_effective')->findOneColumn('rate') ?: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new rate in the database
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @param float $rate Hourly rate
|
||||||
|
* @param string $currency Currency code
|
||||||
|
* @param string $date ISO8601 date format
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create($user_id, $rate, $currency, $date)
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'rate' => $rate,
|
||||||
|
'currency' => $currency,
|
||||||
|
'date_effective' => $this->dateParser->removeTimeFromTimestamp($this->dateParser->getTimestamp($date)),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->persist(self::TABLE, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a specific rate
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $rate_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($rate_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $rate_id)->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('user_id', t('Field required')),
|
||||||
|
new Validators\Required('rate', t('Field required')),
|
||||||
|
new Validators\Numeric('rate', t('This value must be numeric')),
|
||||||
|
new Validators\Required('date_effective', t('Field required')),
|
||||||
|
new Validators\Required('currency', t('Field required')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,17 +81,63 @@ class ProjectActivity extends Base
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $this->db->table(self::TABLE)
|
$query = $this
|
||||||
|
->db
|
||||||
|
->table(self::TABLE)
|
||||||
->columns(
|
->columns(
|
||||||
self::TABLE.'.*',
|
self::TABLE.'.*',
|
||||||
User::TABLE.'.username AS author_username',
|
User::TABLE.'.username AS author_username',
|
||||||
User::TABLE.'.name AS author_name'
|
User::TABLE.'.name AS author_name',
|
||||||
|
User::TABLE.'.email'
|
||||||
)
|
)
|
||||||
->in('project_id', $project_ids)
|
->in('project_id', $project_ids)
|
||||||
->join(User::TABLE, 'id', 'creator_id')
|
->join(User::TABLE, 'id', 'creator_id')
|
||||||
->desc(self::TABLE.'.id')
|
->desc(self::TABLE.'.id')
|
||||||
->limit($limit);
|
->limit($limit);
|
||||||
|
|
||||||
|
return $this->getEvents($query, $start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all events for the given task
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @param integer $limit Maximum events number
|
||||||
|
* @param integer $start Timestamp of earliest activity
|
||||||
|
* @param integer $end Timestamp of latest activity
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTask($task_id, $limit = 50, $start = null, $end = null)
|
||||||
|
{
|
||||||
|
$query = $this
|
||||||
|
->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
self::TABLE.'.*',
|
||||||
|
User::TABLE.'.username AS author_username',
|
||||||
|
User::TABLE.'.name AS author_name',
|
||||||
|
User::TABLE.'.email'
|
||||||
|
)
|
||||||
|
->eq('task_id', $task_id)
|
||||||
|
->join(User::TABLE, 'id', 'creator_id')
|
||||||
|
->desc(self::TABLE.'.id')
|
||||||
|
->limit($limit);
|
||||||
|
|
||||||
|
return $this->getEvents($query, $start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common function to return events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \PicoDb\Table $query PicoDb Query
|
||||||
|
* @param integer $start Timestamp of earliest activity
|
||||||
|
* @param integer $end Timestamp of latest activity
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getEvents(\PicoDb\Table $query, $start, $end)
|
||||||
|
{
|
||||||
if (! is_null($start)){
|
if (! is_null($start)){
|
||||||
$query->gte('date_creation', $start);
|
$query->gte('date_creation', $start);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +208,13 @@ class ProjectActivity extends Base
|
||||||
{
|
{
|
||||||
switch ($event['event_name']) {
|
switch ($event['event_name']) {
|
||||||
case Task::EVENT_ASSIGNEE_CHANGE:
|
case Task::EVENT_ASSIGNEE_CHANGE:
|
||||||
return t('%s change the assignee of the task #%d to %s', $event['author'], $event['task']['id'], $event['task']['assignee_name'] ?: $event['task']['assignee_username']);
|
$assignee = $event['task']['assignee_name'] ?: $event['task']['assignee_username'];
|
||||||
|
|
||||||
|
if (! empty($assignee)) {
|
||||||
|
return t('%s change the assignee of the task #%d to %s', $event['author'], $event['task']['id'], $assignee);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t('%s remove the assignee of the task %s', $event['author'], e('#%d', $event['task']['id']));
|
||||||
case Task::EVENT_UPDATE:
|
case Task::EVENT_UPDATE:
|
||||||
return t('%s updated the task #%d', $event['author'], $event['task']['id']);
|
return t('%s updated the task #%d', $event['author'], $event['task']['id']);
|
||||||
case Task::EVENT_CREATE:
|
case Task::EVENT_CREATE:
|
||||||
|
|
|
@ -316,7 +316,10 @@ class ProjectPermission extends Base
|
||||||
{
|
{
|
||||||
return $this->db
|
return $this->db
|
||||||
->hashtable(Project::TABLE)
|
->hashtable(Project::TABLE)
|
||||||
->eq('user_id', $user_id)
|
->beginOr()
|
||||||
|
->eq(self::TABLE.'.user_id', $user_id)
|
||||||
|
->eq(Project::TABLE.'.is_everybody_allowed', 1)
|
||||||
|
->closeOr()
|
||||||
->join(self::TABLE, 'project_id', 'id')
|
->join(self::TABLE, 'project_id', 'id')
|
||||||
->getAll('projects.id', 'name');
|
->getAll('projects.id', 'name');
|
||||||
}
|
}
|
||||||
|
@ -332,7 +335,10 @@ class ProjectPermission extends Base
|
||||||
{
|
{
|
||||||
return $this->db
|
return $this->db
|
||||||
->table(Project::TABLE)
|
->table(Project::TABLE)
|
||||||
->eq('user_id', $user_id)
|
->beginOr()
|
||||||
|
->eq(self::TABLE.'.user_id', $user_id)
|
||||||
|
->eq(Project::TABLE.'.is_everybody_allowed', 1)
|
||||||
|
->closeOr()
|
||||||
->join(self::TABLE, 'project_id', 'id')
|
->join(self::TABLE, 'project_id', 'id')
|
||||||
->findAllByColumn('projects.id');
|
->findAllByColumn('projects.id');
|
||||||
}
|
}
|
||||||
|
@ -348,7 +354,10 @@ class ProjectPermission extends Base
|
||||||
{
|
{
|
||||||
return $this->db
|
return $this->db
|
||||||
->table(Project::TABLE)
|
->table(Project::TABLE)
|
||||||
->eq('user_id', $user_id)
|
->beginOr()
|
||||||
|
->eq(self::TABLE.'.user_id', $user_id)
|
||||||
|
->eq(Project::TABLE.'.is_everybody_allowed', 1)
|
||||||
|
->closeOr()
|
||||||
->eq(Project::TABLE.'.is_active', Project::ACTIVE)
|
->eq(Project::TABLE.'.is_active', Project::ACTIVE)
|
||||||
->join(self::TABLE, 'project_id', 'id')
|
->join(self::TABLE, 'project_id', 'id')
|
||||||
->findAllByColumn('projects.id');
|
->findAllByColumn('projects.id');
|
||||||
|
@ -365,7 +374,10 @@ class ProjectPermission extends Base
|
||||||
{
|
{
|
||||||
return $this->db
|
return $this->db
|
||||||
->hashtable(Project::TABLE)
|
->hashtable(Project::TABLE)
|
||||||
->eq('user_id', $user_id)
|
->beginOr()
|
||||||
|
->eq(self::TABLE.'.user_id', $user_id)
|
||||||
|
->eq(Project::TABLE.'.is_everybody_allowed', 1)
|
||||||
|
->closeOr()
|
||||||
->eq(Project::TABLE.'.is_active', Project::ACTIVE)
|
->eq(Project::TABLE.'.is_active', Project::ACTIVE)
|
||||||
->join(self::TABLE, 'project_id', 'id')
|
->join(self::TABLE, 'project_id', 'id')
|
||||||
->getAll('projects.id', 'name');
|
->getAll('projects.id', 'name');
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Subtask extends Base
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
const TABLE = 'task_has_subtasks';
|
const TABLE = 'subtasks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Task "done" status
|
* Task "done" status
|
||||||
|
@ -98,6 +98,7 @@ class Subtask extends Base
|
||||||
Subtask::TABLE.'.*',
|
Subtask::TABLE.'.*',
|
||||||
Task::TABLE.'.project_id',
|
Task::TABLE.'.project_id',
|
||||||
Task::TABLE.'.color_id',
|
Task::TABLE.'.color_id',
|
||||||
|
Task::TABLE.'.title AS task_name',
|
||||||
Project::TABLE.'.name AS project_name'
|
Project::TABLE.'.name AS project_name'
|
||||||
)
|
)
|
||||||
->eq('user_id', $user_id)
|
->eq('user_id', $user_id)
|
||||||
|
@ -122,7 +123,7 @@ class Subtask extends Base
|
||||||
->eq('task_id', $task_id)
|
->eq('task_id', $task_id)
|
||||||
->columns(self::TABLE.'.*', User::TABLE.'.username', User::TABLE.'.name')
|
->columns(self::TABLE.'.*', User::TABLE.'.username', User::TABLE.'.name')
|
||||||
->join(User::TABLE, 'id', 'user_id')
|
->join(User::TABLE, 'id', 'user_id')
|
||||||
->asc(self::TABLE.'.id')
|
->asc(self::TABLE.'.position')
|
||||||
->filter(array($this, 'addStatusName'))
|
->filter(array($this, 'addStatusName'))
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
@ -163,6 +164,22 @@ class Subtask extends Base
|
||||||
$this->resetFields($values, array('time_estimated', 'time_spent'));
|
$this->resetFields($values, array('time_estimated', 'time_spent'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the last column for a given project
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLastPosition($task_id)
|
||||||
|
{
|
||||||
|
return (int) $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->eq('task_id', $task_id)
|
||||||
|
->desc('position')
|
||||||
|
->findOneColumn('position');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new subtask
|
* Create a new subtask
|
||||||
*
|
*
|
||||||
|
@ -173,6 +190,8 @@ class Subtask extends Base
|
||||||
public function create(array $values)
|
public function create(array $values)
|
||||||
{
|
{
|
||||||
$this->prepare($values);
|
$this->prepare($values);
|
||||||
|
$values['position'] = $this->getLastPosition($values['task_id']) + 1;
|
||||||
|
|
||||||
$subtask_id = $this->persist(self::TABLE, $values);
|
$subtask_id = $this->persist(self::TABLE, $values);
|
||||||
|
|
||||||
if ($subtask_id) {
|
if ($subtask_id) {
|
||||||
|
@ -208,6 +227,64 @@ class Subtask extends Base
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a subtask down, increment the position value
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id
|
||||||
|
* @param integer $subtask_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function moveDown($task_id, $subtask_id)
|
||||||
|
{
|
||||||
|
$subtasks = $this->db->hashtable(self::TABLE)->eq('task_id', $task_id)->asc('position')->getAll('id', 'position');
|
||||||
|
$positions = array_flip($subtasks);
|
||||||
|
|
||||||
|
if (isset($subtasks[$subtask_id]) && $subtasks[$subtask_id] < count($subtasks)) {
|
||||||
|
|
||||||
|
$position = ++$subtasks[$subtask_id];
|
||||||
|
$subtasks[$positions[$position]]--;
|
||||||
|
|
||||||
|
$this->db->startTransaction();
|
||||||
|
$this->db->table(self::TABLE)->eq('id', $subtask_id)->update(array('position' => $position));
|
||||||
|
$this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $subtasks[$positions[$position]]));
|
||||||
|
$this->db->closeTransaction();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a subtask up, decrement the position value
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id
|
||||||
|
* @param integer $subtask_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function moveUp($task_id, $subtask_id)
|
||||||
|
{
|
||||||
|
$subtasks = $this->db->hashtable(self::TABLE)->eq('task_id', $task_id)->asc('position')->getAll('id', 'position');
|
||||||
|
$positions = array_flip($subtasks);
|
||||||
|
|
||||||
|
if (isset($subtasks[$subtask_id]) && $subtasks[$subtask_id] > 1) {
|
||||||
|
|
||||||
|
$position = --$subtasks[$subtask_id];
|
||||||
|
$subtasks[$positions[$position]]++;
|
||||||
|
|
||||||
|
$this->db->startTransaction();
|
||||||
|
$this->db->table(self::TABLE)->eq('id', $subtask_id)->update(array('position' => $position));
|
||||||
|
$this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $subtasks[$positions[$position]]));
|
||||||
|
$this->db->closeTransaction();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the status of subtask
|
* Change the status of subtask
|
||||||
*
|
*
|
||||||
|
@ -286,9 +363,9 @@ class Subtask extends Base
|
||||||
return $this->db->transaction(function ($db) use ($src_task_id, $dst_task_id) {
|
return $this->db->transaction(function ($db) use ($src_task_id, $dst_task_id) {
|
||||||
|
|
||||||
$subtasks = $db->table(Subtask::TABLE)
|
$subtasks = $db->table(Subtask::TABLE)
|
||||||
->columns('title', 'time_estimated')
|
->columns('title', 'time_estimated', 'position')
|
||||||
->eq('task_id', $src_task_id)
|
->eq('task_id', $src_task_id)
|
||||||
->asc('id') // Explicit sorting for postgresql
|
->asc('position')
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
foreach ($subtasks as &$subtask) {
|
foreach ($subtasks as &$subtask) {
|
||||||
|
@ -380,7 +457,7 @@ class Subtask extends Base
|
||||||
return array(
|
return array(
|
||||||
new Validators\Integer('id', t('The subtask id must be an integer')),
|
new Validators\Integer('id', t('The subtask id must be an integer')),
|
||||||
new Validators\Integer('task_id', t('The task id must be an integer')),
|
new Validators\Integer('task_id', t('The task id must be an integer')),
|
||||||
new Validators\MaxLength('title', t('The maximum length is %d characters', 100), 100),
|
new Validators\MaxLength('title', t('The maximum length is %d characters', 255), 255),
|
||||||
new Validators\Integer('user_id', t('The user id must be an integer')),
|
new Validators\Integer('user_id', t('The user id must be an integer')),
|
||||||
new Validators\Integer('status', t('The status must be an integer')),
|
new Validators\Integer('status', t('The status must be an integer')),
|
||||||
new Validators\Numeric('time_estimated', t('The time must be a numeric value')),
|
new Validators\Numeric('time_estimated', t('The time must be a numeric value')),
|
||||||
|
|
124
sources/app/Model/SubtaskForecast.php
Normal file
124
sources/app/Model/SubtaskForecast.php
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use DateInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtask Forecast
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class SubtaskForecast extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get not completed subtasks with an estimate sorted by postition
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSubtasks($user_id)
|
||||||
|
{
|
||||||
|
return $this->db
|
||||||
|
->table(Subtask::TABLE)
|
||||||
|
->columns(Subtask::TABLE.'.id', Task::TABLE.'.project_id', Subtask::TABLE.'.task_id', Subtask::TABLE.'.title', Subtask::TABLE.'.time_estimated')
|
||||||
|
->join(Task::TABLE, 'id', 'task_id')
|
||||||
|
->asc(Task::TABLE.'.position')
|
||||||
|
->asc(Subtask::TABLE.'.position')
|
||||||
|
->gt(Subtask::TABLE.'.time_estimated', 0)
|
||||||
|
->eq(Subtask::TABLE.'.status', Subtask::STATUS_TODO)
|
||||||
|
->eq(Subtask::TABLE.'.user_id', $user_id)
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the start date for the forecast
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getStartDate($user_id)
|
||||||
|
{
|
||||||
|
$subtask = $this->db->table(Subtask::TABLE)
|
||||||
|
->columns(Subtask::TABLE.'.time_estimated', SubtaskTimeTracking::TABLE.'.start')
|
||||||
|
->eq(SubtaskTimeTracking::TABLE.'.user_id', $user_id)
|
||||||
|
->eq(SubtaskTimeTracking::TABLE.'.end', 0)
|
||||||
|
->status('status', Subtask::STATUS_INPROGRESS)
|
||||||
|
->join(SubtaskTimeTracking::TABLE, 'subtask_id', 'id')
|
||||||
|
->findOne();
|
||||||
|
|
||||||
|
if ($subtask && $subtask['time_estimated'] && $subtask['start']) {
|
||||||
|
return date('Y-m-d H:i', $subtask['start'] + $subtask['time_estimated'] * 3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
return date('Y-m-d H:i');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all calendar events according to the user timetable and the subtasks estimates
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @param string $end End date of the calendar
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCalendarEvents($user_id, $end)
|
||||||
|
{
|
||||||
|
$events = array();
|
||||||
|
$start_date = new DateTime($this->getStartDate($user_id));
|
||||||
|
$timetable = $this->timetable->calculate($user_id, $start_date, new DateTime($end));
|
||||||
|
$subtasks = $this->getSubtasks($user_id);
|
||||||
|
$total = count($subtasks);
|
||||||
|
$offset = 0;
|
||||||
|
|
||||||
|
foreach ($timetable as $slot) {
|
||||||
|
|
||||||
|
$interval = $this->dateParser->getHours($slot[0], $slot[1]);
|
||||||
|
$start = $slot[0]->getTimestamp();
|
||||||
|
|
||||||
|
if ($slot[0] < $start_date) {
|
||||||
|
|
||||||
|
if (! $this->dateParser->withinDateRange($start_date, $slot[0], $slot[1])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$interval = $this->dateParser->getHours(new DateTime, $slot[1]);
|
||||||
|
$start = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($offset < $total) {
|
||||||
|
|
||||||
|
$event = array(
|
||||||
|
'id' => $subtasks[$offset]['id'].'-'.$subtasks[$offset]['task_id'].'-'.$offset,
|
||||||
|
'subtask_id' => $subtasks[$offset]['id'],
|
||||||
|
'title' => t('#%d', $subtasks[$offset]['task_id']).' '.$subtasks[$offset]['title'],
|
||||||
|
'url' => $this->helper->url('task', 'show', array('task_id' => $subtasks[$offset]['task_id'], 'project_id' => $subtasks[$offset]['project_id'])),
|
||||||
|
'editable' => false,
|
||||||
|
'start' => date('Y-m-d\TH:i:s', $start),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($subtasks[$offset]['time_estimated'] <= $interval) {
|
||||||
|
|
||||||
|
$start += $subtasks[$offset]['time_estimated'] * 3600;
|
||||||
|
$interval -= $subtasks[$offset]['time_estimated'];
|
||||||
|
$offset++;
|
||||||
|
|
||||||
|
$event['end'] = date('Y-m-d\TH:i:s', $start);
|
||||||
|
$events[] = $event;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$subtasks[$offset]['time_estimated'] -= $interval;
|
||||||
|
$event['end'] = $slot[1]->format('Y-m-d\TH:i:s');
|
||||||
|
$events[] = $event;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Model;
|
namespace Model;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtask timesheet
|
* Subtask timesheet
|
||||||
*
|
*
|
||||||
|
@ -33,6 +35,7 @@ class SubtaskTimeTracking extends Base
|
||||||
self::TABLE.'.subtask_id',
|
self::TABLE.'.subtask_id',
|
||||||
self::TABLE.'.end',
|
self::TABLE.'.end',
|
||||||
self::TABLE.'.start',
|
self::TABLE.'.start',
|
||||||
|
self::TABLE.'.time_spent',
|
||||||
Subtask::TABLE.'.task_id',
|
Subtask::TABLE.'.task_id',
|
||||||
Subtask::TABLE.'.title AS subtask_title',
|
Subtask::TABLE.'.title AS subtask_title',
|
||||||
Task::TABLE.'.title AS task_title',
|
Task::TABLE.'.title AS task_title',
|
||||||
|
@ -60,6 +63,7 @@ class SubtaskTimeTracking extends Base
|
||||||
self::TABLE.'.subtask_id',
|
self::TABLE.'.subtask_id',
|
||||||
self::TABLE.'.end',
|
self::TABLE.'.end',
|
||||||
self::TABLE.'.start',
|
self::TABLE.'.start',
|
||||||
|
self::TABLE.'.time_spent',
|
||||||
self::TABLE.'.user_id',
|
self::TABLE.'.user_id',
|
||||||
Subtask::TABLE.'.task_id',
|
Subtask::TABLE.'.task_id',
|
||||||
Subtask::TABLE.'.title AS subtask_title',
|
Subtask::TABLE.'.title AS subtask_title',
|
||||||
|
@ -89,6 +93,7 @@ class SubtaskTimeTracking extends Base
|
||||||
self::TABLE.'.subtask_id',
|
self::TABLE.'.subtask_id',
|
||||||
self::TABLE.'.end',
|
self::TABLE.'.end',
|
||||||
self::TABLE.'.start',
|
self::TABLE.'.start',
|
||||||
|
self::TABLE.'.time_spent',
|
||||||
self::TABLE.'.user_id',
|
self::TABLE.'.user_id',
|
||||||
Subtask::TABLE.'.task_id',
|
Subtask::TABLE.'.task_id',
|
||||||
Subtask::TABLE.'.title AS subtask_title',
|
Subtask::TABLE.'.title AS subtask_title',
|
||||||
|
@ -133,6 +138,8 @@ class SubtaskTimeTracking extends Base
|
||||||
->addCondition($this->getCalendarCondition($start, $end))
|
->addCondition($this->getCalendarCondition($start, $end))
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
|
$result = $this->timetable->calculateEventsIntersect($user_id, $result, $start, $end);
|
||||||
|
|
||||||
return $this->toCalendarEvents($result);
|
return $this->toCalendarEvents($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +242,11 @@ class SubtaskTimeTracking extends Base
|
||||||
*/
|
*/
|
||||||
public function logEndTime($subtask_id, $user_id)
|
public function logEndTime($subtask_id, $user_id)
|
||||||
{
|
{
|
||||||
$this->updateSubtaskTimeSpent($subtask_id, $user_id);
|
$time_spent = $this->getTimeSpent($subtask_id, $user_id);
|
||||||
|
|
||||||
|
if ($time_spent > 0) {
|
||||||
|
$this->updateSubtaskTimeSpent($subtask_id, $time_spent);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->db
|
return $this->db
|
||||||
->table(self::TABLE)
|
->table(self::TABLE)
|
||||||
|
@ -243,7 +254,56 @@ class SubtaskTimeTracking extends Base
|
||||||
->eq('user_id', $user_id)
|
->eq('user_id', $user_id)
|
||||||
->eq('end', 0)
|
->eq('end', 0)
|
||||||
->update(array(
|
->update(array(
|
||||||
'end' => time()
|
'end' => time(),
|
||||||
|
'time_spent' => $time_spent,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the time spent when the clock is stopped
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $subtask_id
|
||||||
|
* @param integer $user_id
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getTimeSpent($subtask_id, $user_id)
|
||||||
|
{
|
||||||
|
$start_time = $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->eq('subtask_id', $subtask_id)
|
||||||
|
->eq('user_id', $user_id)
|
||||||
|
->eq('end', 0)
|
||||||
|
->findOneColumn('start');
|
||||||
|
|
||||||
|
if ($start_time) {
|
||||||
|
|
||||||
|
$start = new DateTime;
|
||||||
|
$start->setTimestamp($start_time);
|
||||||
|
|
||||||
|
return $this->timetable->calculateEffectiveDuration($user_id, $start, new DateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update subtask time spent
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $subtask_id
|
||||||
|
* @param float $time_spent
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function updateSubtaskTimeSpent($subtask_id, $time_spent)
|
||||||
|
{
|
||||||
|
$subtask = $this->subtask->getById($subtask_id);
|
||||||
|
|
||||||
|
// Fire the event subtask.update
|
||||||
|
return $this->subtask->update(array(
|
||||||
|
'id' => $subtask['id'],
|
||||||
|
'time_spent' => $subtask['time_spent'] + $time_spent,
|
||||||
|
'task_id' => $subtask['task_id'],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,31 +349,4 @@ class SubtaskTimeTracking extends Base
|
||||||
)
|
)
|
||||||
->findOne();
|
->findOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update subtask time spent based on the punch clock table
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $subtask_id
|
|
||||||
* @param integer $user_id
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function updateSubtaskTimeSpent($subtask_id, $user_id)
|
|
||||||
{
|
|
||||||
$start_time = $this->db
|
|
||||||
->table(self::TABLE)
|
|
||||||
->eq('subtask_id', $subtask_id)
|
|
||||||
->eq('user_id', $user_id)
|
|
||||||
->eq('end', 0)
|
|
||||||
->findOneColumn('start');
|
|
||||||
|
|
||||||
$subtask = $this->subtask->getById($subtask_id);
|
|
||||||
|
|
||||||
return $start_time &&
|
|
||||||
$this->subtask->update(array( // Fire the event subtask.update
|
|
||||||
'id' => $subtask['id'],
|
|
||||||
'time_spent' => $subtask['time_spent'] + round((time() - $start_time) / 3600, 1),
|
|
||||||
'task_id' => $subtask['task_id'],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,22 @@ class Swimlane extends Base
|
||||||
->findOneColumn('id');
|
->findOneColumn('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a swimlane by the project and the name
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id Project id
|
||||||
|
* @param string $name Swimlane name
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getByName($project_id, $name)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)
|
||||||
|
->eq('project_id', $project_id)
|
||||||
|
->eq('name', $name)
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get default swimlane properties
|
* Get default swimlane properties
|
||||||
*
|
*
|
||||||
|
@ -83,10 +99,16 @@ class Swimlane extends Base
|
||||||
*/
|
*/
|
||||||
public function getDefault($project_id)
|
public function getDefault($project_id)
|
||||||
{
|
{
|
||||||
return $this->db->table(Project::TABLE)
|
$result = $this->db->table(Project::TABLE)
|
||||||
->eq('id', $project_id)
|
->eq('id', $project_id)
|
||||||
->columns('id', 'default_swimlane', 'show_default_swimlane')
|
->columns('id', 'default_swimlane', 'show_default_swimlane')
|
||||||
->findOne();
|
->findOne();
|
||||||
|
|
||||||
|
if ($result['default_swimlane'] === 'Default swimlane') {
|
||||||
|
$result['default_swimlane'] = t($result['default_swimlane']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,6 +172,11 @@ class Swimlane extends Base
|
||||||
->findOneColumn('default_swimlane');
|
->findOneColumn('default_swimlane');
|
||||||
|
|
||||||
if ($default_swimlane) {
|
if ($default_swimlane) {
|
||||||
|
|
||||||
|
if ($default_swimlane === 'Default swimlane') {
|
||||||
|
$default_swimlane = t($default_swimlane);
|
||||||
|
}
|
||||||
|
|
||||||
array_unshift($swimlanes, array('id' => 0, 'name' => $default_swimlane));
|
array_unshift($swimlanes, array('id' => 0, 'name' => $default_swimlane));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,14 +194,17 @@ class Swimlane extends Base
|
||||||
public function getList($project_id, $prepend = false)
|
public function getList($project_id, $prepend = false)
|
||||||
{
|
{
|
||||||
$swimlanes = array();
|
$swimlanes = array();
|
||||||
$swimlanes[] = $this->db->table(Project::TABLE)->eq('id', $project_id)->findOneColumn('default_swimlane');
|
$default = $this->db->table(Project::TABLE)->eq('id', $project_id)->eq('show_default_swimlane', 1)->findOneColumn('default_swimlane');
|
||||||
|
|
||||||
$swimlanes = array_merge(
|
if ($prepend) {
|
||||||
$swimlanes,
|
$swimlanes[-1] = t('All swimlanes');
|
||||||
$this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->orderBy('name', 'asc')->getAll('id', 'name')
|
}
|
||||||
);
|
|
||||||
|
|
||||||
return $prepend ? array(-1 => t('All swimlanes')) + $swimlanes : $swimlanes;
|
if (! empty($default)) {
|
||||||
|
$swimlanes[0] = $default === 'Default swimlane' ? t($default) : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $swimlanes + $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->orderBy('position', 'asc')->getAll('id', 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -80,10 +80,10 @@ class TaskFinder extends Base
|
||||||
return $this->db
|
return $this->db
|
||||||
->table(Task::TABLE)
|
->table(Task::TABLE)
|
||||||
->columns(
|
->columns(
|
||||||
'(SELECT count(*) FROM comments WHERE task_id=tasks.id) AS nb_comments',
|
'(SELECT count(*) FROM '.Comment::TABLE.' WHERE task_id=tasks.id) AS nb_comments',
|
||||||
'(SELECT count(*) FROM task_has_files WHERE task_id=tasks.id) AS nb_files',
|
'(SELECT count(*) FROM '.File::TABLE.' WHERE task_id=tasks.id) AS nb_files',
|
||||||
'(SELECT count(*) FROM task_has_subtasks WHERE task_id=tasks.id) AS nb_subtasks',
|
'(SELECT count(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id) AS nb_subtasks',
|
||||||
'(SELECT count(*) FROM task_has_subtasks WHERE task_id=tasks.id AND status=2) AS nb_completed_subtasks',
|
'(SELECT count(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id AND status=2) AS nb_completed_subtasks',
|
||||||
'(SELECT count(*) FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id) AS nb_links',
|
'(SELECT count(*) FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id) AS nb_links',
|
||||||
'tasks.id',
|
'tasks.id',
|
||||||
'tasks.reference',
|
'tasks.reference',
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Model;
|
||||||
|
|
||||||
use SimpleValidator\Validator;
|
use SimpleValidator\Validator;
|
||||||
use SimpleValidator\Validators;
|
use SimpleValidator\Validators;
|
||||||
|
use PicoDb\Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TaskLink model
|
* TaskLink model
|
||||||
|
@ -57,6 +58,7 @@ class TaskLink extends Base
|
||||||
->join(Link::TABLE, 'id', 'link_id')
|
->join(Link::TABLE, 'id', 'link_id')
|
||||||
->join(Task::TABLE, 'id', 'opposite_task_id')
|
->join(Task::TABLE, 'id', 'opposite_task_id')
|
||||||
->join(Board::TABLE, 'id', 'column_id', Task::TABLE)
|
->join(Board::TABLE, 'id', 'column_id', Task::TABLE)
|
||||||
|
->orderBy(Link::TABLE.'.id ASC, '.Board::TABLE.'.position ASC, '.Task::TABLE.'.is_active DESC, '.Task::TABLE.'.id', Table::SORT_ASC)
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,10 @@ class TaskPosition extends Base
|
||||||
* @param integer $column_id Column id
|
* @param integer $column_id Column id
|
||||||
* @param integer $position Position (must be >= 1)
|
* @param integer $position Position (must be >= 1)
|
||||||
* @param integer $swimlane_id Swimlane id
|
* @param integer $swimlane_id Swimlane id
|
||||||
|
* @param boolean $fire_events Fire events
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function movePosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0)
|
public function movePosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0, $fire_events = true)
|
||||||
{
|
{
|
||||||
$original_task = $this->taskFinder->getById($task_id);
|
$original_task = $this->taskFinder->getById($task_id);
|
||||||
|
|
||||||
|
@ -35,8 +36,10 @@ class TaskPosition extends Base
|
||||||
$this->calculateAndSave($project_id, 0, $column_id, 1, $original_task['swimlane_id']);
|
$this->calculateAndSave($project_id, 0, $column_id, 1, $original_task['swimlane_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($fire_events) {
|
||||||
$this->fireEvents($original_task, $column_id, $position, $swimlane_id);
|
$this->fireEvents($original_task, $column_id, $position, $swimlane_id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
@ -140,6 +143,9 @@ class TaskPosition extends Base
|
||||||
'position' => $new_position,
|
'position' => $new_position,
|
||||||
'column_id' => $new_column_id,
|
'column_id' => $new_column_id,
|
||||||
'swimlane_id' => $new_swimlane_id,
|
'swimlane_id' => $new_swimlane_id,
|
||||||
|
'src_column_id' => $task['column_id'],
|
||||||
|
'dst_column_id' => $new_column_id,
|
||||||
|
'date_moved' => $task['date_moved'],
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($task['swimlane_id'] != $new_swimlane_id) {
|
if ($task['swimlane_id'] != $new_swimlane_id) {
|
||||||
|
|
356
sources/app/Model/Timetable.php
Normal file
356
sources/app/Model/Timetable.php
Normal file
|
@ -0,0 +1,356 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use DateInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timetable
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Timetable extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* User time slots
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $day;
|
||||||
|
private $week;
|
||||||
|
private $overtime;
|
||||||
|
private $timeoff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a set of events by using the intersection between the timetable and the time tracking data
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @param array $events Time tracking data
|
||||||
|
* @param string $start ISO8601 date
|
||||||
|
* @param string $end ISO8601 date
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function calculateEventsIntersect($user_id, array $events, $start, $end)
|
||||||
|
{
|
||||||
|
$start_dt = new DateTime($start);
|
||||||
|
$start_dt->setTime(0, 0);
|
||||||
|
|
||||||
|
$end_dt = new DateTime($end);
|
||||||
|
$end_dt->setTime(23, 59);
|
||||||
|
|
||||||
|
$timetable = $this->calculate($user_id, $start_dt, $end_dt);
|
||||||
|
|
||||||
|
// The user has no timetable
|
||||||
|
if (empty($this->week)) {
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
foreach ($events as $event) {
|
||||||
|
$results = array_merge($results, $this->calculateEventIntersect($event, $timetable));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a serie of events based on the timetable and the provided event
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $event
|
||||||
|
* @param array $timetable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function calculateEventIntersect(array $event, array $timetable)
|
||||||
|
{
|
||||||
|
$events = array();
|
||||||
|
|
||||||
|
foreach ($timetable as $slot) {
|
||||||
|
|
||||||
|
$start_ts = $slot[0]->getTimestamp();
|
||||||
|
$end_ts = $slot[1]->getTimestamp();
|
||||||
|
|
||||||
|
if ($start_ts > $event['end']) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($event['start'] <= $start_ts) {
|
||||||
|
$event['start'] = $start_ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($event['start'] >= $start_ts && $event['start'] <= $end_ts) {
|
||||||
|
|
||||||
|
if ($event['end'] >= $end_ts) {
|
||||||
|
$events[] = array_merge($event, array('end' => $end_ts));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$events[] = $event;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate effective worked hours by taking into consideration the timetable
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @param \DateTime $start
|
||||||
|
* @param \DateTime $end
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function calculateEffectiveDuration($user_id, DateTime $start, DateTime $end)
|
||||||
|
{
|
||||||
|
$end_timetable = clone($end);
|
||||||
|
$end_timetable->setTime(23, 59);
|
||||||
|
|
||||||
|
$timetable = $this->calculate($user_id, $start, $end_timetable);
|
||||||
|
$found_start = false;
|
||||||
|
$hours = 0;
|
||||||
|
|
||||||
|
// The user has no timetable
|
||||||
|
if (empty($this->week)) {
|
||||||
|
return $this->dateParser->getHours($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($timetable as $slot) {
|
||||||
|
|
||||||
|
$isStartSlot = $this->dateParser->withinDateRange($start, $slot[0], $slot[1]);
|
||||||
|
$isEndSlot = $this->dateParser->withinDateRange($end, $slot[0], $slot[1]);
|
||||||
|
|
||||||
|
// Start and end are within the same time slot
|
||||||
|
if ($isStartSlot && $isEndSlot) {
|
||||||
|
return $this->dateParser->getHours($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We found the start slot
|
||||||
|
if (! $found_start && $isStartSlot) {
|
||||||
|
$found_start = true;
|
||||||
|
$hours = $this->dateParser->getHours($start, $slot[1]);
|
||||||
|
}
|
||||||
|
else if ($found_start) {
|
||||||
|
|
||||||
|
// We found the end slot
|
||||||
|
if ($isEndSlot) {
|
||||||
|
$hours += $this->dateParser->getHours($slot[0], $end);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// Sum hours of the intermediate time slots
|
||||||
|
$hours += $this->dateParser->getHours($slot[0], $slot[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The start date was not found in regular hours so we get the nearest time slot
|
||||||
|
if (! empty($timetable) && ! $found_start) {
|
||||||
|
$slot = $this->findClosestTimeSlot($start, $timetable);
|
||||||
|
|
||||||
|
if ($start < $slot[0]) {
|
||||||
|
return $this->calculateEffectiveDuration($user_id, $slot[0], $end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hours;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the nearest time slot
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param DateTime $date
|
||||||
|
* @param array $timetable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findClosestTimeSlot(DateTime $date, array $timetable)
|
||||||
|
{
|
||||||
|
$values = array();
|
||||||
|
|
||||||
|
foreach ($timetable as $slot) {
|
||||||
|
$t1 = abs($slot[0]->getTimestamp() - $date->getTimestamp());
|
||||||
|
$t2 = abs($slot[1]->getTimestamp() - $date->getTimestamp());
|
||||||
|
|
||||||
|
$values[] = min($t1, $t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($values);
|
||||||
|
return $timetable[key($values)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timetable for a user for a given date range
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @param \DateTime $start
|
||||||
|
* @param \DateTime $end
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function calculate($user_id, DateTime $start, DateTime $end)
|
||||||
|
{
|
||||||
|
$timetable = array();
|
||||||
|
|
||||||
|
$this->day = $this->timetableDay->getByUser($user_id);
|
||||||
|
$this->week = $this->timetableWeek->getByUser($user_id);
|
||||||
|
$this->overtime = $this->timetableExtra->getByUserAndDate($user_id, $start->format('Y-m-d'), $end->format('Y-m-d'));
|
||||||
|
$this->timeoff = $this->timetableOff->getByUserAndDate($user_id, $start->format('Y-m-d'), $end->format('Y-m-d'));
|
||||||
|
|
||||||
|
for ($today = clone($start); $today <= $end; $today->add(new DateInterval('P1D'))) {
|
||||||
|
$week_day = $today->format('N');
|
||||||
|
$timetable = array_merge($timetable, $this->getWeekSlots($today, $week_day));
|
||||||
|
$timetable = array_merge($timetable, $this->getOvertimeSlots($today, $week_day));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $timetable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return worked time slots for the given day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \DateTime $today
|
||||||
|
* @param string $week_day
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getWeekSlots(DateTime $today, $week_day)
|
||||||
|
{
|
||||||
|
$slots = array();
|
||||||
|
$dayoff = $this->getDayOff($today);
|
||||||
|
|
||||||
|
if (! empty($dayoff) && $dayoff['all_day'] == 1) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->week as $slot) {
|
||||||
|
if ($week_day == $slot['day']) {
|
||||||
|
$slots = array_merge($slots, $this->getDayWorkSlots($slot, $dayoff, $today));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the overtime time slots for the given day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \DateTime $today
|
||||||
|
* @param string $week_day
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getOvertimeSlots(DateTime $today, $week_day)
|
||||||
|
{
|
||||||
|
$slots = array();
|
||||||
|
|
||||||
|
foreach ($this->overtime as $slot) {
|
||||||
|
|
||||||
|
$day = new DateTime($slot['date']);
|
||||||
|
|
||||||
|
if ($week_day == $day->format('N')) {
|
||||||
|
|
||||||
|
if ($slot['all_day'] == 1) {
|
||||||
|
$slots = array_merge($slots, $this->getDaySlots($today));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$slots[] = $this->getTimeSlot($slot, $day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get worked time slots and remove time off
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $slot
|
||||||
|
* @param array $dayoff
|
||||||
|
* @param \DateTime $today
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDayWorkSlots(array $slot, array $dayoff, DateTime $today)
|
||||||
|
{
|
||||||
|
$slots = array();
|
||||||
|
|
||||||
|
if (! empty($dayoff) && $dayoff['start'] < $slot['end']) {
|
||||||
|
|
||||||
|
if ($dayoff['start'] > $slot['start']) {
|
||||||
|
$slots[] = $this->getTimeSlot(array('end' => $dayoff['start']) + $slot, $today);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dayoff['end'] < $slot['end']) {
|
||||||
|
$slots[] = $this->getTimeSlot(array('start' => $dayoff['end']) + $slot, $today);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$slots[] = $this->getTimeSlot($slot, $today);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get regular day work time slots
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \DateTime $today
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDaySlots(DateTime $today)
|
||||||
|
{
|
||||||
|
$slots = array();
|
||||||
|
|
||||||
|
foreach ($this->day as $day) {
|
||||||
|
$slots[] = $this->getTimeSlot($day, $today);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the start and end time slot for a given day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $slot
|
||||||
|
* @param \DateTime $today
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTimeSlot(array $slot, DateTime $today)
|
||||||
|
{
|
||||||
|
$date = $today->format('Y-m-d');
|
||||||
|
|
||||||
|
return array(
|
||||||
|
new DateTime($date.' '.$slot['start']),
|
||||||
|
new DateTime($date.' '.$slot['end']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return day off time slot
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \DateTime $today
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDayOff(DateTime $today)
|
||||||
|
{
|
||||||
|
foreach ($this->timeoff as $day) {
|
||||||
|
|
||||||
|
if ($day['date'] === $today->format('Y-m-d')) {
|
||||||
|
return $day;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
87
sources/app/Model/TimetableDay.php
Normal file
87
sources/app/Model/TimetableDay.php
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timetable Workweek
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TimetableDay extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'timetable_day';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timetable for a given user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getByUser($user_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('start')->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new time slot in the database
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @param string $start Start hour (24h format)
|
||||||
|
* @param string $end End hour (24h format)
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create($user_id, $start, $end)
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->persist(self::TABLE, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a specific time slot
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $slot_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($slot_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $slot_id)->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('user_id', t('Field required')),
|
||||||
|
new Validators\Required('start', t('Field required')),
|
||||||
|
new Validators\Required('end', t('Field required')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
22
sources/app/Model/TimetableExtra.php
Normal file
22
sources/app/Model/TimetableExtra.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timetable over-time
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TimetableExtra extends TimetableOff
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'timetable_extra';
|
||||||
|
}
|
125
sources/app/Model/TimetableOff.php
Normal file
125
sources/app/Model/TimetableOff.php
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timetable time off
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TimetableOff extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'timetable_off';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get query to fetch everything (pagination)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @return \PicoDb\Table
|
||||||
|
*/
|
||||||
|
public function getUserQuery($user_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(static::TABLE)->eq('user_id', $user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timetable for a given user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getByUser($user_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(static::TABLE)->eq('user_id', $user_id)->desc('date')->asc('start')->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timetable for a given user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @param string $start_date
|
||||||
|
* @param string $end_date
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getByUserAndDate($user_id, $start_date, $end_date)
|
||||||
|
{
|
||||||
|
return $this->db->table(static::TABLE)
|
||||||
|
->eq('user_id', $user_id)
|
||||||
|
->gte('date', $start_date)
|
||||||
|
->lte('date', $end_date)
|
||||||
|
->desc('date')
|
||||||
|
->asc('start')
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new time slot in the database
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @param string $date Day (ISO8601 format)
|
||||||
|
* @param boolean $all_day All day flag
|
||||||
|
* @param float $start Start hour (24h format)
|
||||||
|
* @param float $end End hour (24h format)
|
||||||
|
* @param string $comment
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create($user_id, $date, $all_day, $start = '', $end = '', $comment = '')
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'date' => $date,
|
||||||
|
'all_day' => (int) $all_day, // Postgres fix
|
||||||
|
'start' => $all_day ? '' : $start,
|
||||||
|
'end' => $all_day ? '' : $end,
|
||||||
|
'comment' => $comment,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->persist(static::TABLE, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a specific time slot
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $slot_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($slot_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(static::TABLE)->eq('id', $slot_id)->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('user_id', t('Field required')),
|
||||||
|
new Validators\Required('date', t('Field required')),
|
||||||
|
new Validators\Numeric('all_day', t('This value must be numeric')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
91
sources/app/Model/TimetableWeek.php
Normal file
91
sources/app/Model/TimetableWeek.php
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timetable Workweek
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TimetableWeek extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'timetable_week';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timetable for a given user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getByUser($user_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('day')->asc('start')->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new time slot in the database
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id User id
|
||||||
|
* @param string $day Day of the week (ISO-8601)
|
||||||
|
* @param string $start Start hour (24h format)
|
||||||
|
* @param string $end End hour (24h format)
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create($user_id, $day, $start, $end)
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'day' => $day,
|
||||||
|
'start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->persist(self::TABLE, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a specific time slot
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $slot_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($slot_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $slot_id)->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, array(
|
||||||
|
new Validators\Required('user_id', t('Field required')),
|
||||||
|
new Validators\Required('day', t('Field required')),
|
||||||
|
new Validators\Numeric('day', t('This value must be numeric')),
|
||||||
|
new Validators\Required('start', t('Field required')),
|
||||||
|
new Validators\Required('end', t('Field required')),
|
||||||
|
));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
170
sources/app/Model/Transition.php
Normal file
170
sources/app/Model/Transition.php
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition model
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Transition extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'transitions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save transition event
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @param array $task
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function save($user_id, array $task)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->insert(array(
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'project_id' => $task['project_id'],
|
||||||
|
'task_id' => $task['task_id'],
|
||||||
|
'src_column_id' => $task['src_column_id'],
|
||||||
|
'dst_column_id' => $task['dst_column_id'],
|
||||||
|
'date' => time(),
|
||||||
|
'time_spent' => time() - $task['date_moved']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all transitions by task
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllByTask($task_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
'src.title as src_column',
|
||||||
|
'dst.title as dst_column',
|
||||||
|
User::TABLE.'.name',
|
||||||
|
User::TABLE.'.username',
|
||||||
|
self::TABLE.'.user_id',
|
||||||
|
self::TABLE.'.date',
|
||||||
|
self::TABLE.'.time_spent'
|
||||||
|
)
|
||||||
|
->eq('task_id', $task_id)
|
||||||
|
->desc('date')
|
||||||
|
->join(User::TABLE, 'id', 'user_id')
|
||||||
|
->join(Board::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src')
|
||||||
|
->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst')
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all transitions by project
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @param mixed $from Start date (timestamp or user formatted date)
|
||||||
|
* @param mixed $to End date (timestamp or user formatted date)
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllByProjectAndDate($project_id, $from, $to)
|
||||||
|
{
|
||||||
|
if (! is_numeric($from)) {
|
||||||
|
$from = $this->dateParser->removeTimeFromTimestamp($this->dateParser->getTimestamp($from));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_numeric($to)) {
|
||||||
|
$to = $this->dateParser->removeTimeFromTimestamp(strtotime('+1 day', $this->dateParser->getTimestamp($to)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->db->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
Task::TABLE.'.id',
|
||||||
|
Task::TABLE.'.title',
|
||||||
|
'src.title as src_column',
|
||||||
|
'dst.title as dst_column',
|
||||||
|
User::TABLE.'.name',
|
||||||
|
User::TABLE.'.username',
|
||||||
|
self::TABLE.'.user_id',
|
||||||
|
self::TABLE.'.date',
|
||||||
|
self::TABLE.'.time_spent'
|
||||||
|
)
|
||||||
|
->gte('date', $from)
|
||||||
|
->lte('date', $to)
|
||||||
|
->eq(self::TABLE.'.project_id', $project_id)
|
||||||
|
->desc('date')
|
||||||
|
->join(Task::TABLE, 'id', 'task_id')
|
||||||
|
->join(User::TABLE, 'id', 'user_id')
|
||||||
|
->join(Board::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src')
|
||||||
|
->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst')
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get project export
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id Project id
|
||||||
|
* @param mixed $from Start date (timestamp or user formatted date)
|
||||||
|
* @param mixed $to End date (timestamp or user formatted date)
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function export($project_id, $from, $to)
|
||||||
|
{
|
||||||
|
$results = array($this->getColumns());
|
||||||
|
$transitions = $this->getAllByProjectAndDate($project_id, $from, $to);
|
||||||
|
|
||||||
|
foreach ($transitions as $transition) {
|
||||||
|
$results[] = $this->format($transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get column titles
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getColumns()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
e('Id'),
|
||||||
|
e('Task Title'),
|
||||||
|
e('Source column'),
|
||||||
|
e('Destination column'),
|
||||||
|
e('Executer'),
|
||||||
|
e('Date'),
|
||||||
|
e('Time spent'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the output of a transition array
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $transition
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function format(array $transition)
|
||||||
|
{
|
||||||
|
$values = array();
|
||||||
|
$values[] = $transition['id'];
|
||||||
|
$values[] = $transition['title'];
|
||||||
|
$values[] = $transition['src_column'];
|
||||||
|
$values[] = $transition['dst_column'];
|
||||||
|
$values[] = $transition['name'] ?: $transition['username'];
|
||||||
|
$values[] = date('Y-m-d H:i', $transition['date']);
|
||||||
|
$values[] = round($transition['time_spent'] / 3600, 2);
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,8 @@ class User extends Base
|
||||||
'is_ldap_user',
|
'is_ldap_user',
|
||||||
'notifications_enabled',
|
'notifications_enabled',
|
||||||
'google_id',
|
'google_id',
|
||||||
'github_id'
|
'github_id',
|
||||||
|
'twofactor_activated'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,14 +28,41 @@ class UserSession extends Base
|
||||||
unset($user['password']);
|
unset($user['password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($user['twofactor_secret'])) {
|
||||||
|
unset($user['twofactor_secret']);
|
||||||
|
}
|
||||||
|
|
||||||
$user['id'] = (int) $user['id'];
|
$user['id'] = (int) $user['id'];
|
||||||
$user['default_project_id'] = (int) $user['default_project_id'];
|
$user['default_project_id'] = (int) $user['default_project_id'];
|
||||||
$user['is_admin'] = (bool) $user['is_admin'];
|
$user['is_admin'] = (bool) $user['is_admin'];
|
||||||
$user['is_ldap_user'] = (bool) $user['is_ldap_user'];
|
$user['is_ldap_user'] = (bool) $user['is_ldap_user'];
|
||||||
|
$user['twofactor_activated'] = (bool) $user['twofactor_activated'];
|
||||||
|
|
||||||
$this->session['user'] = $user;
|
$this->session['user'] = $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user has validated the 2FA key
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function check2FA()
|
||||||
|
{
|
||||||
|
return isset($this->session['2fa_validated']) && $this->session['2fa_validated'] === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the user has 2FA enabled
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has2FA()
|
||||||
|
{
|
||||||
|
return isset($this->session['user']['twofactor_activated']) && $this->session['user']['twofactor_activated'] === true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the logged user is admin
|
* Return true if the logged user is admin
|
||||||
*
|
*
|
||||||
|
|
|
@ -10,27 +10,6 @@ namespace Model;
|
||||||
*/
|
*/
|
||||||
class Webhook extends Base
|
class Webhook extends Base
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* HTTP connection timeout in seconds
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
*/
|
|
||||||
const HTTP_TIMEOUT = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of maximum redirections for the HTTP client
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
*/
|
|
||||||
const HTTP_MAX_REDIRECTS = 3;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP client user agent
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const HTTP_USER_AGENT = 'Kanboard Webhook';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call the external URL
|
* Call the external URL
|
||||||
*
|
*
|
||||||
|
@ -42,22 +21,6 @@ class Webhook extends Base
|
||||||
{
|
{
|
||||||
$token = $this->config->get('webhook_token');
|
$token = $this->config->get('webhook_token');
|
||||||
|
|
||||||
$headers = array(
|
|
||||||
'Connection: close',
|
|
||||||
'User-Agent: '.self::HTTP_USER_AGENT,
|
|
||||||
);
|
|
||||||
|
|
||||||
$context = stream_context_create(array(
|
|
||||||
'http' => array(
|
|
||||||
'method' => 'POST',
|
|
||||||
'protocol_version' => 1.1,
|
|
||||||
'timeout' => self::HTTP_TIMEOUT,
|
|
||||||
'max_redirects' => self::HTTP_MAX_REDIRECTS,
|
|
||||||
'header' => implode("\r\n", $headers),
|
|
||||||
'content' => json_encode($task)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
if (strpos($url, '?') !== false) {
|
if (strpos($url, '?') !== false) {
|
||||||
$url .= '&token='.$token;
|
$url .= '&token='.$token;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +28,6 @@ class Webhook extends Base
|
||||||
$url .= '?token='.$token;
|
$url .= '?token='.$token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@file_get_contents($url, false, $context);
|
return $this->httpClient->post($url, $task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,190 @@ use PDO;
|
||||||
use Core\Security;
|
use Core\Security;
|
||||||
use Model\Link;
|
use Model\Link;
|
||||||
|
|
||||||
const VERSION = 46;
|
const VERSION = 61;
|
||||||
|
|
||||||
|
function version_61($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE users ADD COLUMN twofactor_activated TINYINT(1) DEFAULT 0');
|
||||||
|
$pdo->exec('ALTER TABLE users ADD COLUMN twofactor_secret CHAR(16)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_60($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_gravatar', '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_59($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_hipchat', '0'));
|
||||||
|
$rq->execute(array('integration_hipchat_api_url', 'https://api.hipchat.com'));
|
||||||
|
$rq->execute(array('integration_hipchat_room_id', ''));
|
||||||
|
$rq->execute(array('integration_hipchat_room_token', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_58($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_slack_webhook', '0'));
|
||||||
|
$rq->execute(array('integration_slack_webhook_url', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_57($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE currencies (`currency` CHAR(3) NOT NULL UNIQUE, `rate` FLOAT DEFAULT 0) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('application_currency', 'USD'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_56($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE transitions (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`project_id` INT NOT NULL,
|
||||||
|
`task_id` INT NOT NULL,
|
||||||
|
`src_column_id` INT NOT NULL,
|
||||||
|
`dst_column_id` INT NOT NULL,
|
||||||
|
`date` INT NOT NULL,
|
||||||
|
`time_spent` INT DEFAULT 0,
|
||||||
|
FOREIGN KEY(src_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(dst_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
|
||||||
|
$pdo->exec("CREATE INDEX transitions_task_index ON transitions(task_id)");
|
||||||
|
$pdo->exec("CREATE INDEX transitions_project_index ON transitions(project_id)");
|
||||||
|
$pdo->exec("CREATE INDEX transitions_user_index ON transitions(user_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_55($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('subtask_forecast', '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_54($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('application_stylesheet', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_53($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("ALTER TABLE subtask_time_tracking ADD COLUMN time_spent FLOAT DEFAULT 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_52($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE budget_lines (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`project_id` INT NOT NULL,
|
||||||
|
`amount` FLOAT NOT NULL,
|
||||||
|
`date` VARCHAR(10) NOT NULL,
|
||||||
|
`comment` TEXT,
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_51($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE timetable_day (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id INT NOT NULL,
|
||||||
|
start VARCHAR(5) NOT NULL,
|
||||||
|
end VARCHAR(5) NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_week (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
day INT NOT NULL,
|
||||||
|
start VARCHAR(5) NOT NULL,
|
||||||
|
end VARCHAR(5) NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_off (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id INT NOT NULL,
|
||||||
|
date VARCHAR(10) NOT NULL,
|
||||||
|
all_day TINYINT(1) DEFAULT 0,
|
||||||
|
start VARCHAR(5) DEFAULT 0,
|
||||||
|
end VARCHAR(5) DEFAULT 0,
|
||||||
|
comment TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_extra (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id INT NOT NULL,
|
||||||
|
date VARCHAR(10) NOT NULL,
|
||||||
|
all_day TINYINT(1) DEFAULT 0,
|
||||||
|
start VARCHAR(5) DEFAULT 0,
|
||||||
|
end VARCHAR(5) DEFAULT 0,
|
||||||
|
comment TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_50($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("CREATE TABLE hourly_rates (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id INT NOT NULL,
|
||||||
|
rate FLOAT DEFAULT 0,
|
||||||
|
date_effective INTEGER NOT NULL,
|
||||||
|
currency CHAR(3) NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_49($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE subtasks ADD COLUMN position INTEGER DEFAULT 1');
|
||||||
|
|
||||||
|
$task_id = 0;
|
||||||
|
$position = 1;
|
||||||
|
$urq = $pdo->prepare('UPDATE subtasks SET position=? WHERE id=?');
|
||||||
|
|
||||||
|
$rq = $pdo->prepare('SELECT * FROM subtasks ORDER BY task_id, id ASC');
|
||||||
|
$rq->execute();
|
||||||
|
|
||||||
|
foreach ($rq->fetchAll(PDO::FETCH_ASSOC) as $subtask) {
|
||||||
|
|
||||||
|
if ($task_id != $subtask['task_id']) {
|
||||||
|
$position = 1;
|
||||||
|
$task_id = $subtask['task_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$urq->execute(array($position, $subtask['id']));
|
||||||
|
$position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_48($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('RENAME TABLE task_has_files TO files');
|
||||||
|
$pdo->exec('RENAME TABLE task_has_subtasks TO subtasks');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_47($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE projects ADD COLUMN description TEXT');
|
||||||
|
}
|
||||||
|
|
||||||
function version_46($pdo)
|
function version_46($pdo)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,183 @@ use PDO;
|
||||||
use Core\Security;
|
use Core\Security;
|
||||||
use Model\Link;
|
use Model\Link;
|
||||||
|
|
||||||
const VERSION = 27;
|
const VERSION = 42;
|
||||||
|
|
||||||
|
function version_42($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE users ADD COLUMN twofactor_activated BOOLEAN DEFAULT \'0\'');
|
||||||
|
$pdo->exec('ALTER TABLE users ADD COLUMN twofactor_secret CHAR(16)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_41($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_gravatar', '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_40($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_hipchat', '0'));
|
||||||
|
$rq->execute(array('integration_hipchat_api_url', 'https://api.hipchat.com'));
|
||||||
|
$rq->execute(array('integration_hipchat_room_id', ''));
|
||||||
|
$rq->execute(array('integration_hipchat_room_token', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_39($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_slack_webhook', '0'));
|
||||||
|
$rq->execute(array('integration_slack_webhook_url', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_38($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE currencies ("currency" CHAR(3) NOT NULL UNIQUE, "rate" REAL DEFAULT 0)');
|
||||||
|
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('application_currency', 'USD'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_37($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE transitions (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"project_id" INTEGER NOT NULL,
|
||||||
|
"task_id" INTEGER NOT NULL,
|
||||||
|
"src_column_id" INTEGER NOT NULL,
|
||||||
|
"dst_column_id" INTEGER NOT NULL,
|
||||||
|
"date" INTEGER NOT NULL,
|
||||||
|
"time_spent" INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY(src_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(dst_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec("CREATE INDEX transitions_task_index ON transitions(task_id)");
|
||||||
|
$pdo->exec("CREATE INDEX transitions_project_index ON transitions(project_id)");
|
||||||
|
$pdo->exec("CREATE INDEX transitions_user_index ON transitions(user_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_36($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('subtask_forecast', '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_35($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('application_stylesheet', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_34($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("ALTER TABLE subtask_time_tracking ADD COLUMN time_spent REAL DEFAULT 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_33($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE budget_lines (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"project_id" INTEGER NOT NULL,
|
||||||
|
"amount" REAL NOT NULL,
|
||||||
|
"date" VARCHAR(10) NOT NULL,
|
||||||
|
"comment" TEXT,
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_32($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE timetable_day (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"start" VARCHAR(5) NOT NULL,
|
||||||
|
"end" VARCHAR(5) NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_week (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"day" INTEGER NOT NULL,
|
||||||
|
"start" VARCHAR(5) NOT NULL,
|
||||||
|
"end" VARCHAR(5) NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_off (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"date" VARCHAR(10) NOT NULL,
|
||||||
|
"all_day" BOOLEAN DEFAULT \'0\',
|
||||||
|
"start" VARCHAR(5) DEFAULT 0,
|
||||||
|
"end" VARCHAR(5) DEFAULT 0,
|
||||||
|
"comment" TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_extra (
|
||||||
|
"id" SERIAL PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"date" VARCHAR(10) NOT NULL,
|
||||||
|
"all_day" BOOLEAN DEFAULT \'0\',
|
||||||
|
"start" VARCHAR(5) DEFAULT 0,
|
||||||
|
"end" VARCHAR(5) DEFAULT 0,
|
||||||
|
"comment" TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_31($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("CREATE TABLE hourly_rates (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
rate REAL DEFAULT 0,
|
||||||
|
date_effective INTEGER NOT NULL,
|
||||||
|
currency CHAR(3) NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_30($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE subtasks ADD COLUMN position INTEGER DEFAULT 1');
|
||||||
|
|
||||||
|
$task_id = 0;
|
||||||
|
$position = 1;
|
||||||
|
$urq = $pdo->prepare('UPDATE subtasks SET position=? WHERE id=?');
|
||||||
|
|
||||||
|
$rq = $pdo->prepare('SELECT * FROM subtasks ORDER BY task_id, id ASC');
|
||||||
|
$rq->execute();
|
||||||
|
|
||||||
|
foreach ($rq->fetchAll(PDO::FETCH_ASSOC) as $subtask) {
|
||||||
|
|
||||||
|
if ($task_id != $subtask['task_id']) {
|
||||||
|
$position = 1;
|
||||||
|
$task_id = $subtask['task_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$urq->execute(array($position, $subtask['id']));
|
||||||
|
$position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_29($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE task_has_files RENAME TO files');
|
||||||
|
$pdo->exec('ALTER TABLE task_has_subtasks RENAME TO subtasks');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_28($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE projects ADD COLUMN description TEXT');
|
||||||
|
}
|
||||||
|
|
||||||
function version_27($pdo)
|
function version_27($pdo)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,185 @@ use Core\Security;
|
||||||
use PDO;
|
use PDO;
|
||||||
use Model\Link;
|
use Model\Link;
|
||||||
|
|
||||||
const VERSION = 45;
|
const VERSION = 60;
|
||||||
|
|
||||||
|
function version_60($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE users ADD COLUMN twofactor_activated INTEGER DEFAULT 0');
|
||||||
|
$pdo->exec('ALTER TABLE users ADD COLUMN twofactor_secret TEXT');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_59($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_gravatar', '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_58($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_hipchat', '0'));
|
||||||
|
$rq->execute(array('integration_hipchat_api_url', 'https://api.hipchat.com'));
|
||||||
|
$rq->execute(array('integration_hipchat_room_id', ''));
|
||||||
|
$rq->execute(array('integration_hipchat_room_token', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_57($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_slack_webhook', '0'));
|
||||||
|
$rq->execute(array('integration_slack_webhook_url', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_56($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE currencies ("currency" TEXT NOT NULL UNIQUE, "rate" REAL DEFAULT 0)');
|
||||||
|
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('application_currency', 'USD'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_55($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE transitions (
|
||||||
|
"id" INTEGER PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"project_id" INTEGER NOT NULL,
|
||||||
|
"task_id" INTEGER NOT NULL,
|
||||||
|
"src_column_id" INTEGER NOT NULL,
|
||||||
|
"dst_column_id" INTEGER NOT NULL,
|
||||||
|
"date" INTEGER NOT NULL,
|
||||||
|
"time_spent" INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY(src_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(dst_column_id) REFERENCES columns(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec("CREATE INDEX transitions_task_index ON transitions(task_id)");
|
||||||
|
$pdo->exec("CREATE INDEX transitions_project_index ON transitions(project_id)");
|
||||||
|
$pdo->exec("CREATE INDEX transitions_user_index ON transitions(user_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_54($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('subtask_forecast', '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_53($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('application_stylesheet', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_52($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("ALTER TABLE subtask_time_tracking ADD COLUMN time_spent REAL DEFAULT 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_51($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE budget_lines (
|
||||||
|
"id" INTEGER PRIMARY KEY,
|
||||||
|
"project_id" INTEGER NOT NULL,
|
||||||
|
"amount" REAL NOT NULL,
|
||||||
|
"date" TEXT NOT NULL,
|
||||||
|
"comment" TEXT,
|
||||||
|
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_50($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('CREATE TABLE timetable_day (
|
||||||
|
"id" INTEGER PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"start" TEXT NOT NULL,
|
||||||
|
"end" TEXT NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_week (
|
||||||
|
"id" INTEGER PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"day" INTEGER NOT NULL,
|
||||||
|
"start" TEXT NOT NULL,
|
||||||
|
"end" TEXT NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_off (
|
||||||
|
"id" INTEGER PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"date" TEXT NOT NULL,
|
||||||
|
"all_day" INTEGER DEFAULT 0,
|
||||||
|
"start" TEXT DEFAULT 0,
|
||||||
|
"end" TEXT DEFAULT 0,
|
||||||
|
"comment" TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
|
||||||
|
$pdo->exec('CREATE TABLE timetable_extra (
|
||||||
|
"id" INTEGER PRIMARY KEY,
|
||||||
|
"user_id" INTEGER NOT NULL,
|
||||||
|
"date" TEXT NOT NULL,
|
||||||
|
"all_day" INTEGER DEFAULT 0,
|
||||||
|
"start" TEXT DEFAULT 0,
|
||||||
|
"end" TEXT DEFAULT 0,
|
||||||
|
"comment" TEXT,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_49($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("CREATE TABLE hourly_rates (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
rate REAL DEFAULT 0,
|
||||||
|
date_effective INTEGER NOT NULL,
|
||||||
|
currency TEXT NOT NULL,
|
||||||
|
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_48($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE subtasks ADD COLUMN position INTEGER DEFAULT 1');
|
||||||
|
|
||||||
|
// Migrate all subtasks position
|
||||||
|
|
||||||
|
$task_id = 0;
|
||||||
|
$position = 1;
|
||||||
|
$urq = $pdo->prepare('UPDATE subtasks SET position=? WHERE id=?');
|
||||||
|
|
||||||
|
$rq = $pdo->prepare('SELECT * FROM subtasks ORDER BY task_id, id ASC');
|
||||||
|
$rq->execute();
|
||||||
|
|
||||||
|
foreach ($rq->fetchAll(PDO::FETCH_ASSOC) as $subtask) {
|
||||||
|
|
||||||
|
if ($task_id != $subtask['task_id']) {
|
||||||
|
$position = 1;
|
||||||
|
$task_id = $subtask['task_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$urq->execute(array($position, $subtask['id']));
|
||||||
|
$position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_47($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE task_has_files RENAME TO files');
|
||||||
|
$pdo->exec('ALTER TABLE task_has_subtasks RENAME TO subtasks');
|
||||||
|
}
|
||||||
|
|
||||||
|
function version_46($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE projects ADD COLUMN description TEXT');
|
||||||
|
}
|
||||||
|
|
||||||
function version_45($pdo)
|
function version_45($pdo)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,12 +17,15 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'Action',
|
'Action',
|
||||||
'Authentication',
|
'Authentication',
|
||||||
'Board',
|
'Board',
|
||||||
|
'Budget',
|
||||||
'Category',
|
'Category',
|
||||||
'Color',
|
'Color',
|
||||||
'Comment',
|
'Comment',
|
||||||
'Config',
|
'Config',
|
||||||
|
'Currency',
|
||||||
'DateParser',
|
'DateParser',
|
||||||
'File',
|
'File',
|
||||||
|
'HourlyRate',
|
||||||
'LastLogin',
|
'LastLogin',
|
||||||
'Link',
|
'Link',
|
||||||
'Notification',
|
'Notification',
|
||||||
|
@ -34,6 +37,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'ProjectPermission',
|
'ProjectPermission',
|
||||||
'Subtask',
|
'Subtask',
|
||||||
'SubtaskExport',
|
'SubtaskExport',
|
||||||
|
'SubtaskForecast',
|
||||||
'SubtaskTimeTracking',
|
'SubtaskTimeTracking',
|
||||||
'Swimlane',
|
'Swimlane',
|
||||||
'Task',
|
'Task',
|
||||||
|
@ -48,7 +52,12 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'TaskPosition',
|
'TaskPosition',
|
||||||
'TaskStatus',
|
'TaskStatus',
|
||||||
'TaskValidator',
|
'TaskValidator',
|
||||||
'TimeTracking',
|
'Timetable',
|
||||||
|
'TimetableDay',
|
||||||
|
'TimetableWeek',
|
||||||
|
'TimetableOff',
|
||||||
|
'TimetableExtra',
|
||||||
|
'Transition',
|
||||||
'User',
|
'User',
|
||||||
'UserSession',
|
'UserSession',
|
||||||
'Webhook',
|
'Webhook',
|
||||||
|
@ -60,11 +69,14 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'MemoryCache',
|
'MemoryCache',
|
||||||
'FileCache',
|
'FileCache',
|
||||||
'Request',
|
'Request',
|
||||||
|
'HttpClient',
|
||||||
),
|
),
|
||||||
'Integration' => array(
|
'Integration' => array(
|
||||||
'GitlabWebhook',
|
'GitlabWebhook',
|
||||||
'GithubWebhook',
|
'GithubWebhook',
|
||||||
'BitbucketWebhook',
|
'BitbucketWebhook',
|
||||||
|
'Hipchat',
|
||||||
|
'SlackWebhook',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,7 @@ class DatabaseProvider implements ServiceProviderInterface
|
||||||
'password' => DB_PASSWORD,
|
'password' => DB_PASSWORD,
|
||||||
'database' => DB_NAME,
|
'database' => DB_NAME,
|
||||||
'charset' => 'utf8',
|
'charset' => 'utf8',
|
||||||
|
'port' => DB_PORT,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ class DatabaseProvider implements ServiceProviderInterface
|
||||||
'username' => DB_USERNAME,
|
'username' => DB_USERNAME,
|
||||||
'password' => DB_PASSWORD,
|
'password' => DB_PASSWORD,
|
||||||
'database' => DB_NAME,
|
'database' => DB_NAME,
|
||||||
|
'port' => DB_PORT,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use Subscriber\ProjectModificationDateSubscriber;
|
||||||
use Subscriber\WebhookSubscriber;
|
use Subscriber\WebhookSubscriber;
|
||||||
use Subscriber\SubtaskTimesheetSubscriber;
|
use Subscriber\SubtaskTimesheetSubscriber;
|
||||||
use Subscriber\TaskMovedDateSubscriber;
|
use Subscriber\TaskMovedDateSubscriber;
|
||||||
|
use Subscriber\TransitionSubscriber;
|
||||||
|
|
||||||
class EventDispatcherProvider implements ServiceProviderInterface
|
class EventDispatcherProvider implements ServiceProviderInterface
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,7 @@ class EventDispatcherProvider implements ServiceProviderInterface
|
||||||
$container['dispatcher']->addSubscriber(new NotificationSubscriber($container));
|
$container['dispatcher']->addSubscriber(new NotificationSubscriber($container));
|
||||||
$container['dispatcher']->addSubscriber(new SubtaskTimesheetSubscriber($container));
|
$container['dispatcher']->addSubscriber(new SubtaskTimesheetSubscriber($container));
|
||||||
$container['dispatcher']->addSubscriber(new TaskMovedDateSubscriber($container));
|
$container['dispatcher']->addSubscriber(new TaskMovedDateSubscriber($container));
|
||||||
|
$container['dispatcher']->addSubscriber(new TransitionSubscriber($container));
|
||||||
|
|
||||||
// Automatic actions
|
// Automatic actions
|
||||||
$container['action']->attachEvents();
|
$container['action']->attachEvents();
|
||||||
|
|
|
@ -10,6 +10,8 @@ use Pimple\Container;
|
||||||
* @package subscriber
|
* @package subscriber
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*
|
*
|
||||||
|
* @property \Integration\SlackWebhook $slackWebhook
|
||||||
|
* @property \Integration\Hipchat $hipchat
|
||||||
* @property \Model\Board $board
|
* @property \Model\Board $board
|
||||||
* @property \Model\Config $config
|
* @property \Model\Config $config
|
||||||
* @property \Model\Comment $comment
|
* @property \Model\Comment $comment
|
||||||
|
|
|
@ -47,12 +47,15 @@ class NotificationSubscriber extends Base implements EventSubscriberInterface
|
||||||
public function execute(GenericEvent $event, $event_name)
|
public function execute(GenericEvent $event, $event_name)
|
||||||
{
|
{
|
||||||
$values = $this->getTemplateData($event);
|
$values = $this->getTemplateData($event);
|
||||||
|
|
||||||
|
if (isset($values['task']['project_id'])) {
|
||||||
$users = $this->notification->getUsersList($values['task']['project_id']);
|
$users = $this->notification->getUsersList($values['task']['project_id']);
|
||||||
|
|
||||||
if ($users) {
|
if (! empty($users)) {
|
||||||
$this->notification->sendEmails($this->templates[$event_name], $users, $values);
|
$this->notification->sendEmails($this->templates[$event_name], $users, $values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getTemplateData(GenericEvent $event)
|
public function getTemplateData(GenericEvent $event)
|
||||||
{
|
{
|
||||||
|
@ -64,11 +67,11 @@ class NotificationSubscriber extends Base implements EventSubscriberInterface
|
||||||
break;
|
break;
|
||||||
case 'Event\SubtaskEvent':
|
case 'Event\SubtaskEvent':
|
||||||
$values['subtask'] = $this->subtask->getById($event['id'], true);
|
$values['subtask'] = $this->subtask->getById($event['id'], true);
|
||||||
$values['task'] = $this->taskFinder->getDetails($event['task_id']);
|
$values['task'] = $this->taskFinder->getDetails($values['subtask']['task_id']);
|
||||||
break;
|
break;
|
||||||
case 'Event\FileEvent':
|
case 'Event\FileEvent':
|
||||||
$values['file'] = $event->getAll();
|
$values['file'] = $event->getAll();
|
||||||
$values['task'] = $this->taskFinder->getDetails($event['task_id']);
|
$values['task'] = $this->taskFinder->getDetails($values['file']['task_id']);
|
||||||
break;
|
break;
|
||||||
case 'Event\CommentEvent':
|
case 'Event\CommentEvent':
|
||||||
$values['comment'] = $this->comment->getById($event['id']);
|
$values['comment'] = $this->comment->getById($event['id']);
|
||||||
|
|
|
@ -41,6 +41,33 @@ class ProjectActivitySubscriber extends Base implements EventSubscriberInterface
|
||||||
$event_name,
|
$event_name,
|
||||||
$values
|
$values
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->sendSlackNotification($event_name, $values);
|
||||||
|
$this->sendHipchatNotification($event_name, $values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendSlackNotification($event_name, array $values)
|
||||||
|
{
|
||||||
|
if ($this->config->get('integration_slack_webhook') == 1) {
|
||||||
|
$this->slackWebhook->notify(
|
||||||
|
$values['task']['project_id'],
|
||||||
|
$values['task']['id'],
|
||||||
|
$event_name,
|
||||||
|
$values
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendHipchatNotification($event_name, array $values)
|
||||||
|
{
|
||||||
|
if ($this->config->get('integration_hipchat') == 1) {
|
||||||
|
$this->hipchat->notify(
|
||||||
|
$values['task']['project_id'],
|
||||||
|
$values['task']['id'],
|
||||||
|
$event_name,
|
||||||
|
$values
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
sources/app/Subscriber/TransitionSubscriber.php
Normal file
26
sources/app/Subscriber/TransitionSubscriber.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Subscriber;
|
||||||
|
|
||||||
|
use Event\TaskEvent;
|
||||||
|
use Model\Task;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
|
||||||
|
class TransitionSubscriber extends Base implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
public static function getSubscribedEvents()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
Task::EVENT_MOVE_COLUMN => array('execute', 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(TaskEvent $event)
|
||||||
|
{
|
||||||
|
$user_id = $this->userSession->getId();
|
||||||
|
|
||||||
|
if (! empty($user_id)) {
|
||||||
|
$this->transition->save($user_id, $event->getAll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue