diff options
Diffstat (limited to 'app')
83 files changed, 2211 insertions, 1202 deletions
diff --git a/app/Action/CommentCreation.php b/app/Action/CommentCreation.php index 5dfd1c89..4029c875 100644 --- a/app/Action/CommentCreation.php +++ b/app/Action/CommentCreation.php @@ -28,6 +28,7 @@ class CommentCreation extends Base BitbucketWebhook::EVENT_ISSUE_COMMENT, BitbucketWebhook::EVENT_COMMIT, GitlabWebhook::EVENT_COMMIT, + GitlabWebhook::EVENT_ISSUE_COMMENT, ); } diff --git a/app/Api/Project.php b/app/Api/Project.php index faf2a3da..4e4e10b8 100644 --- a/app/Api/Project.php +++ b/app/Api/Project.php @@ -87,9 +87,9 @@ class Project extends Base { if (! empty($project)) { $project['url'] = array( - 'board' => $this->helper->url->base().$this->helper->url->to('board', 'show', array('project_id' => $project['id'])), - 'calendar' => $this->helper->url->base().$this->helper->url->to('calendar', 'show', array('project_id' => $project['id'])), - 'list' => $this->helper->url->base().$this->helper->url->to('listing', 'show', array('project_id' => $project['id'])), + 'board' => $this->helper->url->to('board', 'show', array('project_id' => $project['id']), '', true), + 'calendar' => $this->helper->url->to('calendar', 'show', array('project_id' => $project['id']), '', true), + 'list' => $this->helper->url->to('listing', 'show', array('project_id' => $project['id']), '', true), ); } diff --git a/app/Api/Task.php b/app/Api/Task.php index ade49a6d..3b8c1ec8 100644 --- a/app/Api/Task.php +++ b/app/Api/Task.php @@ -119,7 +119,7 @@ class Task extends Base private function formatTask($task) { if (! empty($task)) { - $task['url'] = $this->helper->url->base().$this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])); + $task['url'] = $this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), '', true); } return $task; diff --git a/app/Auth/GitHub.php b/app/Auth/GitHub.php deleted file mode 100644 index 816cc9c1..00000000 --- a/app/Auth/GitHub.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php - -namespace Auth; - -use Event\AuthEvent; -use OAuth\Common\Storage\Session; -use OAuth\Common\Consumer\Credentials; -use OAuth\Common\Http\Uri\UriFactory; -use OAuth\ServiceFactory; -use OAuth\Common\Http\Exception\TokenResponseException; - -/** - * GitHub backend - * - * @package auth - */ -class GitHub extends Base -{ - /** - * Backend name - * - * @var string - */ - const AUTH_NAME = 'Github'; - - /** - * Authenticate a GitHub user - * - * @access public - * @param string $github_id GitHub user id - * @return boolean - */ - public function authenticate($github_id) - { - $user = $this->user->getByGitHubId($github_id); - - if (! empty($user)) { - $this->userSession->refresh($user); - $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); - return true; - } - - return false; - } - - /** - * Unlink a GitHub account for a given user - * - * @access public - * @param integer $user_id User id - * @return boolean - */ - public function unlink($user_id) - { - return $this->user->update(array( - 'id' => $user_id, - 'github_id' => '', - )); - } - - /** - * Update the user table based on the GitHub profile information - * - * @access public - * @param integer $user_id User id - * @param array $profile GitHub profile - * @return boolean - * @todo Don't overwrite existing email/name with empty GitHub data - */ - public function updateUser($user_id, array $profile) - { - return $this->user->update(array( - 'id' => $user_id, - 'github_id' => $profile['id'], - 'email' => $profile['email'], - 'name' => $profile['name'], - )); - } - - /** - * Get the GitHub service instance - * - * @access public - * @return \OAuth\OAuth2\Service\GitHub - */ - public function getService() - { - $uriFactory = new UriFactory(); - $currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); - $currentUri->setQuery('controller=user&action=gitHub'); - - $storage = new Session(false); - - $credentials = new Credentials( - GITHUB_CLIENT_ID, - GITHUB_CLIENT_SECRET, - $currentUri->getAbsoluteUri() - ); - - $serviceFactory = new ServiceFactory(); - - return $serviceFactory->createService( - 'gitHub', - $credentials, - $storage, - array('') - ); - } - - /** - * Get the authorization URL - * - * @access public - * @return \OAuth\Common\Http\Uri\Uri - */ - public function getAuthorizationUrl() - { - return $this->getService()->getAuthorizationUri(); - } - - /** - * Get GitHub profile information from the API - * - * @access public - * @param string $code GitHub authorization code - * @return bool|array - */ - public function getGitHubProfile($code) - { - try { - $gitHubService = $this->getService(); - $gitHubService->requestAccessToken($code); - - return json_decode($gitHubService->request('user'), true); - } - catch (TokenResponseException $e) { - return false; - } - } - - /** - * Revokes this user's GitHub tokens for Kanboard - * - * @access public - * @return bool|array - * @todo Currently this simply removes all our tokens for this user, ideally it should - * restrict itself to the one in question - */ - public function revokeGitHubAccess() - { - try { - $gitHubService = $this->getService(); - - $basicAuthHeader = array('Authorization' => 'Basic ' . - base64_encode(GITHUB_CLIENT_ID.':'.GITHUB_CLIENT_SECRET)); - - return json_decode($gitHubService->request('/applications/'.GITHUB_CLIENT_ID.'/tokens', 'DELETE', null, $basicAuthHeader), true); - } - catch (TokenResponseException $e) { - return false; - } - } -} diff --git a/app/Auth/Github.php b/app/Auth/Github.php new file mode 100644 index 00000000..44bcc6c8 --- /dev/null +++ b/app/Auth/Github.php @@ -0,0 +1,122 @@ +<?php + +namespace Auth; + +use Event\AuthEvent; + +/** + * Github backend + * + * @package auth + */ +class Github extends Base +{ + /** + * Backend name + * + * @var string + */ + const AUTH_NAME = 'Github'; + + /** + * OAuth2 instance + * + * @access private + * @var \Core\OAuth2 + */ + private $service; + + /** + * Authenticate a Github user + * + * @access public + * @param string $github_id Github user id + * @return boolean + */ + public function authenticate($github_id) + { + $user = $this->user->getByGithubId($github_id); + + if (! empty($user)) { + $this->userSession->refresh($user); + $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); + return true; + } + + return false; + } + + /** + * Unlink a Github account for a given user + * + * @access public + * @param integer $user_id User id + * @return boolean + */ + public function unlink($user_id) + { + return $this->user->update(array( + 'id' => $user_id, + 'github_id' => '', + )); + } + + /** + * Update the user table based on the Github profile information + * + * @access public + * @param integer $user_id User id + * @param array $profile Github profile + * @return boolean + */ + public function updateUser($user_id, array $profile) + { + $user = $this->user->getById($user_id); + + return $this->user->update(array( + 'id' => $user_id, + 'github_id' => $profile['id'], + 'email' => $profile['email'] ?: $user['email'], + 'name' => $profile['name'] ?: $user['name'], + )); + } + + /** + * Get OAuth2 configured service + * + * @access public + * @return \Core\OAuth2 + */ + public function getService() + { + if (empty($this->service)) { + $this->service = $this->oauth->createService( + GITHUB_CLIENT_ID, + GITHUB_CLIENT_SECRET, + $this->helper->url->to('oauth', 'github', array(), '', true), + 'https://github.com/login/oauth/authorize', + 'https://github.com/login/oauth/access_token', + array() + ); + } + + return $this->service; + } + + /** + * Get Github profile + * + * @access public + * @param string $code + * @return array + */ + public function getProfile($code) + { + $this->getService()->getAccessToken($code); + + return $this->httpClient->getJson( + 'https://api.github.com/user', + array($this->getService()->getAuthorizationHeader()) + ); + } +} diff --git a/app/Auth/Google.php b/app/Auth/Google.php index 9a977037..972dd748 100644 --- a/app/Auth/Google.php +++ b/app/Auth/Google.php @@ -3,11 +3,6 @@ namespace Auth; use Event\AuthEvent; -use OAuth\Common\Storage\Session; -use OAuth\Common\Consumer\Credentials; -use OAuth\Common\Http\Uri\UriFactory; -use OAuth\ServiceFactory; -use OAuth\Common\Http\Exception\TokenResponseException; /** * Google backend @@ -25,6 +20,14 @@ class Google extends Base const AUTH_NAME = 'Google'; /** + * OAuth2 instance + * + * @access private + * @var \Core\OAuth2 + */ + private $service; + + /** * Authenticate a Google user * * @access public @@ -69,72 +72,52 @@ class Google extends Base */ public function updateUser($user_id, array $profile) { + $user = $this->user->getById($user_id); + return $this->user->update(array( 'id' => $user_id, 'google_id' => $profile['id'], - 'email' => $profile['email'], - 'name' => $profile['name'], + 'email' => $profile['email'] ?: $user['email'], + 'name' => $profile['name'] ?: $user['name'], )); } /** - * Get the Google service instance + * Get OAuth2 configured service * * @access public - * @return \OAuth\OAuth2\Service\Google + * @return \Core\OAuth2 */ public function getService() { - $uriFactory = new UriFactory(); - $currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); - $currentUri->setQuery('controller=user&action=google'); - - $storage = new Session(false); - - $credentials = new Credentials( - GOOGLE_CLIENT_ID, - GOOGLE_CLIENT_SECRET, - $currentUri->getAbsoluteUri() - ); - - $serviceFactory = new ServiceFactory(); - - return $serviceFactory->createService( - 'google', - $credentials, - $storage, - array('userinfo_email', 'userinfo_profile') - ); - } + if (empty($this->service)) { + $this->service = $this->oauth->createService( + GOOGLE_CLIENT_ID, + GOOGLE_CLIENT_SECRET, + $this->helper->url->to('oauth', 'google', array(), '', true), + 'https://accounts.google.com/o/oauth2/auth', + 'https://accounts.google.com/o/oauth2/token', + array('https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile') + ); + } - /** - * Get the authorization URL - * - * @access public - * @return \OAuth\Common\Http\Uri\Uri - */ - public function getAuthorizationUrl() - { - return $this->getService()->getAuthorizationUri(); + return $this->service; } /** - * Get Google profile information from the API + * Get Google profile * * @access public - * @param string $code Google authorization code - * @return bool|array + * @param string $code + * @return array */ - public function getGoogleProfile($code) + public function getProfile($code) { - try { + $this->getService()->getAccessToken($code); - $googleService = $this->getService(); - $googleService->requestAccessToken($code); - return json_decode($googleService->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); - } - catch (TokenResponseException $e) { - return false; - } + return $this->httpClient->getJson( + 'https://www.googleapis.com/oauth2/v1/userinfo', + array($this->getService()->getAuthorizationHeader()) + ); } } diff --git a/app/Auth/Ldap.php b/app/Auth/Ldap.php index 3ee6ec9b..c1459b4e 100644 --- a/app/Auth/Ldap.php +++ b/app/Auth/Ldap.php @@ -46,7 +46,7 @@ class Ldap extends Base else { // We create automatically a new user - if ($this->createUser($username, $result['name'], $result['email'])) { + if (LDAP_ACCOUNT_CREATION && $this->createUser($username, $result['name'], $result['email'])) { $user = $this->user->getByUsername($username); } else { diff --git a/app/Auth/RememberMe.php b/app/Auth/RememberMe.php index eebf4f4b..54e60422 100644 --- a/app/Auth/RememberMe.php +++ b/app/Auth/RememberMe.php @@ -282,7 +282,7 @@ class RememberMe extends Base self::COOKIE_NAME, $this->encodeCookie($token, $sequence), $expiration, - BASE_URL_DIRECTORY, + $this->helper->url->dir(), null, Request::isHTTPS(), true @@ -315,7 +315,7 @@ class RememberMe extends Base self::COOKIE_NAME, '', time() - 3600, - BASE_URL_DIRECTORY, + $this->helper->url->dir(), null, Request::isHTTPS(), true diff --git a/app/Controller/Action.php b/app/Controller/Action.php index cd24453a..74a5326d 100644 --- a/app/Controller/Action.php +++ b/app/Controller/Action.php @@ -46,7 +46,7 @@ class Action extends Base $values = $this->request->getValues(); if (empty($values['action_name']) || empty($values['project_id'])) { - $this->response->redirect('?controller=action&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); } $this->response->html($this->projectLayout('action/event', array( @@ -68,7 +68,7 @@ class Action extends Base $values = $this->request->getValues(); if (empty($values['action_name']) || empty($values['project_id']) || empty($values['event_name'])) { - $this->response->redirect('?controller=action&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); } $action = $this->action->load($values['action_name'], $values['project_id'], $values['event_name']); @@ -125,7 +125,7 @@ class Action extends Base } } - $this->response->redirect('?controller=action&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); } /** @@ -163,6 +163,6 @@ class Action extends Base $this->session->flashError(t('Unable to remove this action.')); } - $this->response->redirect('?controller=action&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); } } diff --git a/app/Controller/Auth.php b/app/Controller/Auth.php index 24e6e242..e8889b7f 100644 --- a/app/Controller/Auth.php +++ b/app/Controller/Auth.php @@ -25,7 +25,6 @@ class Auth extends Base 'errors' => $errors, 'values' => $values, 'no_layout' => true, - 'redirect_query' => $this->request->getStringParam('redirect_query'), 'title' => t('Login') ))); } @@ -37,14 +36,15 @@ class Auth extends Base */ public function check() { - $redirect_query = $this->request->getStringParam('redirect_query'); $values = $this->request->getValues(); list($valid, $errors) = $this->authentication->validateForm($values); if ($valid) { - if ($redirect_query !== '') { - $this->response->redirect('?'.urldecode($redirect_query)); + if (! empty($this->session['login_redirect']) && ! filter_var($this->session['login_redirect'], FILTER_VALIDATE_URL)) { + $redirect = $this->session['login_redirect']; + unset($this->session['login_redirect']); + $this->response->redirect($redirect); } $this->response->redirect($this->helper->url->to('app', 'index')); diff --git a/app/Controller/Base.php b/app/Controller/Base.php index 9f5d6dc6..31eb023d 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -101,7 +101,7 @@ abstract class Base extends \Core\Base public function beforeAction($controller, $action) { // Start the session - $this->session->open(BASE_URL_DIRECTORY); + $this->session->open($this->helper->url->dir()); $this->sendHeaders($action); $this->container['dispatcher']->dispatch('session.bootstrap', new Event); @@ -127,7 +127,8 @@ abstract class Base extends \Core\Base $this->response->text('Not Authorized', 401); } - $this->response->redirect($this->helper->url->to('auth', 'login', array('redirect_query' => urlencode($this->request->getQueryString())))); + $this->session['login_redirect'] = $this->request->getUri(); + $this->response->redirect($this->helper->url->to('auth', 'login')); } } @@ -223,17 +224,6 @@ abstract class Base extends \Core\Base } /** - * Redirection when there is no project in the database - * - * @access protected - */ - protected function redirectNoProject() - { - $this->session->flash(t('There is no active project, the first step is to create a new project.')); - $this->response->redirect('?controller=project&action=create'); - } - - /** * Common layout for task views * * @access protected @@ -301,7 +291,7 @@ abstract class Base extends \Core\Base if (empty($project)) { $this->session->flashError(t('Project not found.')); - $this->response->redirect('?controller=project'); + $this->response->redirect($this->helper->url->to('project', 'index')); } return $project; @@ -344,10 +334,10 @@ abstract class Base extends \Core\Base 'controller' => $controller, 'action' => $action, 'project_id' => $project['id'], - 'search' => $search, + 'search' => urldecode($search), ); - $this->userSession->setFilters($project['id'], $search); + $this->userSession->setFilters($project['id'], $filters['search']); return array( 'project' => $project, diff --git a/app/Controller/Board.php b/app/Controller/Board.php index ac80a192..50d9c62e 100644 --- a/app/Controller/Board.php +++ b/app/Controller/Board.php @@ -88,15 +88,7 @@ class Board extends Base return $this->response->status(400); } - $this->response->html( - $this->template->render('board/table_container', array( - 'project' => $this->project->getById($project_id), - 'swimlanes' => $this->taskFilter->search($this->userSession->getFilters($project_id))->getBoard($project_id), - 'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'), - 'board_highlight_period' => $this->config->get('board_highlight_period'), - )), - 201 - ); + $this->response->html($this->renderBoard($project_id), 201); } /** @@ -121,14 +113,7 @@ class Board extends Base return $this->response->status(304); } - $this->response->html( - $this->template->render('board/table_container', array( - 'project' => $this->project->getById($project_id), - 'swimlanes' => $this->taskFilter->search($this->userSession->getFilters($project_id))->getBoard($project_id), - 'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'), - 'board_highlight_period' => $this->config->get('board_highlight_period'), - )) - ); + $this->response->html($this->renderBoard($project_id)); } /** @@ -318,9 +303,7 @@ class Board extends Base */ public function collapse() { - $project_id = $this->request->getIntegerParam('project_id'); - $this->userSession->setBoardDisplayMode($project_id, true); - $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project_id))); + $this->changeDisplayMode(true); } /** @@ -330,8 +313,39 @@ class Board extends Base */ public function expand() { + $this->changeDisplayMode(false); + } + + /** + * Change display mode + * + * @access private + */ + private function changeDisplayMode($mode) + { $project_id = $this->request->getIntegerParam('project_id'); - $this->userSession->setBoardDisplayMode($project_id, false); - $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project_id))); + $this->userSession->setBoardDisplayMode($project_id, $mode); + + if ($this->request->isAjax()) { + $this->response->html($this->renderBoard($project_id)); + } + else { + $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project_id))); + } + } + + /** + * Render board + * + * @access private + */ + private function renderBoard($project_id) + { + return $this->template->render('board/table_container', array( + 'project' => $this->project->getById($project_id), + 'swimlanes' => $this->taskFilter->search($this->userSession->getFilters($project_id))->getBoard($project_id), + 'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'), + 'board_highlight_period' => $this->config->get('board_highlight_period'), + )); } } diff --git a/app/Controller/Category.php b/app/Controller/Category.php index 515cc9c8..e8d83f2d 100644 --- a/app/Controller/Category.php +++ b/app/Controller/Category.php @@ -23,7 +23,7 @@ class Category extends Base if (empty($category)) { $this->session->flashError(t('Category not found.')); - $this->response->redirect('?controller=category&action=index&project_id='.$project_id); + $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project_id))); } return $category; @@ -63,7 +63,7 @@ class Category extends Base if ($this->category->create($values)) { $this->session->flash(t('Your category have been created successfully.')); - $this->response->redirect('?controller=category&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id']))); } else { $this->session->flashError(t('Unable to create your category.')); @@ -107,7 +107,7 @@ class Category extends Base if ($this->category->update($values)) { $this->session->flash(t('Your category have been updated successfully.')); - $this->response->redirect('?controller=category&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id']))); } else { $this->session->flashError(t('Unable to update your category.')); @@ -151,6 +151,6 @@ class Category extends Base $this->session->flashError(t('Unable to remove this category.')); } - $this->response->redirect('?controller=category&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id']))); } } diff --git a/app/Controller/Comment.php b/app/Controller/Comment.php index a5f6b1f8..ca701a88 100644 --- a/app/Controller/Comment.php +++ b/app/Controller/Comment.php @@ -90,10 +90,10 @@ class Comment extends Base } if ($ajax) { - $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#comments'); + $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), 'comments'); } $this->create($values, $errors); @@ -140,7 +140,7 @@ class Comment extends Base $this->session->flashError(t('Unable to update your comment.')); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#comment-'.$comment['id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), 'comment-'.$comment['id']); } $this->edit($values, $errors); @@ -181,6 +181,6 @@ class Comment extends Base $this->session->flashError(t('Unable to remove this comment.')); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#comments'); + $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), 'comments'); } } diff --git a/app/Controller/Config.php b/app/Controller/Config.php index 19bc2767..1e6b3dc8 100644 --- a/app/Controller/Config.php +++ b/app/Controller/Config.php @@ -60,7 +60,7 @@ class Config extends Base $this->session->flashError(t('Unable to save your settings.')); } - $this->response->redirect('?controller=config&action='.$redirect); + $this->response->redirect($this->helper->url->to('config', $redirect)); } } @@ -199,7 +199,7 @@ class Config extends Base $this->checkCSRFParam(); $this->config->optimizeDatabase(); $this->session->flash(t('Database optimization done.')); - $this->response->redirect('?controller=config'); + $this->response->redirect($this->helper->url->to('config', 'index')); } /** @@ -215,6 +215,6 @@ class Config extends Base $this->config->regenerateToken($type.'_token'); $this->session->flash(t('Token regenerated.')); - $this->response->redirect('?controller=config&action='.$type); + $this->response->redirect($this->helper->url->to('config', $type)); } } diff --git a/app/Controller/Oauth.php b/app/Controller/Oauth.php new file mode 100644 index 00000000..8ba5b252 --- /dev/null +++ b/app/Controller/Oauth.php @@ -0,0 +1,123 @@ +<?php + +namespace Controller; + +/** + * OAuth controller + * + * @package controller + * @author Frederic Guillot + */ +class Oauth extends Base +{ + /** + * Link or authenticate a Google account + * + * @access public + */ + public function google() + { + $this->step1('google'); + } + + /** + * Link or authenticate a Github account + * + * @access public + */ + public function github() + { + $this->step1('github'); + } + + /** + * Unlink external account + * + * @access public + */ + public function unlink($backend = '') + { + $backend = $this->request->getStringParam('backend', $backend); + $this->checkCSRFParam(); + + if ($this->authentication->backend($backend)->unlink($this->userSession->getId())) { + $this->session->flash(t('Your external account is not linked anymore to your profile.')); + } + else { + $this->session->flashError(t('Unable to unlink your external account.')); + } + + $this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId()))); + } + + /** + * Redirect to the provider if no code received + * + * @access private + */ + private function step1($backend) + { + $code = $this->request->getStringParam('code'); + + if (! empty($code)) { + $this->step2($backend, $code); + } + else { + $this->response->redirect($this->authentication->backend($backend)->getService()->getAuthorizationUrl()); + } + } + + /** + * Link or authenticate the user + * + * @access private + */ + private function step2($backend, $code) + { + $profile = $this->authentication->backend($backend)->getProfile($code); + + if ($this->userSession->isLogged()) { + $this->link($backend, $profile); + } + + $this->authenticate($backend, $profile); + } + + /** + * Link the account + * + * @access private + */ + private function link($backend, $profile) + { + if (empty($profile)) { + $this->session->flashError(t('External authentication failed')); + } + else { + $this->session->flash(t('Your external account is linked to your profile successfully.')); + $this->authentication->backend($backend)->updateUser($this->userSession->getId(), $profile); + } + + $this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId()))); + } + + /** + * Authenticate the account + * + * @access private + */ + private function authenticate($backend, $profile) + { + if (! empty($profile) && $this->authentication->backend($backend)->authenticate($profile['id'])) { + $this->response->redirect($this->helper->url->to('app', 'index')); + } + else { + $this->response->html($this->template->layout('auth/index', array( + 'errors' => array('login' => t('External authentication failed')), + 'values' => array(), + 'no_layout' => true, + 'title' => t('Login') + ))); + } + } +} diff --git a/app/Controller/Project.php b/app/Controller/Project.php index faebac38..45bc2a46 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -73,11 +73,12 @@ class Project extends Base if ($this->project->{$switch.'PublicAccess'}($project['id'])) { $this->session->flash(t('Project updated successfully.')); - } else { + } + else { $this->session->flashError(t('Unable to update this project.')); } - $this->response->redirect('?controller=project&action=share&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('project', 'share', array('project_id' => $project['id']))); } $this->response->html($this->projectLayout('project/share', array( @@ -150,7 +151,7 @@ class Project extends Base if ($this->project->update($values)) { $this->session->flash(t('Project updated successfully.')); - $this->response->redirect('?controller=project&action=edit&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('project', 'edit', array('project_id' => $project['id']))); } else { $this->session->flashError(t('Unable to update this project.')); @@ -197,7 +198,7 @@ class Project extends Base } } - $this->response->redirect('?controller=project&action=users&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('project', 'users', array('project_id' => $project['id']))); } /** @@ -220,7 +221,7 @@ class Project extends Base } } - $this->response->redirect('?controller=project&action=users&project_id='.$values['project_id']); + $this->response->redirect($this->helper->url->to('project', 'users', array('project_id' => $values['project_id']))); } /** @@ -250,7 +251,7 @@ class Project extends Base } } - $this->response->redirect('?controller=project&action=users&project_id='.$values['project_id']); + $this->response->redirect($this->helper->url->to('project', 'users', array('project_id' => $values['project_id']))); } /** @@ -279,7 +280,7 @@ class Project extends Base } } - $this->response->redirect('?controller=project&action=users&project_id='.$values['project_id']); + $this->response->redirect($this->helper->url->to('project', 'users', array('project_id' => $values['project_id']))); } /** @@ -301,7 +302,7 @@ class Project extends Base $this->session->flashError(t('Unable to remove this project.')); } - $this->response->redirect('?controller=project'); + $this->response->redirect($this->helper->url->to('project', 'index')); } $this->response->html($this->projectLayout('project/remove', array( @@ -329,7 +330,7 @@ class Project extends Base $this->session->flashError(t('Unable to clone this project.')); } - $this->response->redirect('?controller=project'); + $this->response->redirect($this->helper->url->to('project', 'index')); } $this->response->html($this->projectLayout('project/duplicate', array( @@ -357,7 +358,7 @@ class Project extends Base $this->session->flashError(t('Unable to disable this project.')); } - $this->response->redirect('?controller=project&action=show&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id']))); } $this->response->html($this->projectLayout('project/disable', array( @@ -385,7 +386,7 @@ class Project extends Base $this->session->flashError(t('Unable to activate this project.')); } - $this->response->redirect('?controller=project&action=show&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id']))); } $this->response->html($this->projectLayout('project/enable', array( @@ -428,7 +429,7 @@ class Project extends Base if ($project_id > 0) { $this->session->flash(t('Your project have been created successfully.')); - $this->response->redirect('?controller=project&action=show&project_id='.$project_id); + $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id))); } $this->session->flashError(t('Unable to create your project.')); diff --git a/app/Controller/Search.php b/app/Controller/Search.php index 519f9ce4..f6dc7a32 100644 --- a/app/Controller/Search.php +++ b/app/Controller/Search.php @@ -13,7 +13,7 @@ class Search extends Base public function index() { $projects = $this->projectPermission->getAllowedProjects($this->userSession->getId()); - $search = $this->request->getStringParam('search'); + $search = urldecode($this->request->getStringParam('search')); $nb_tasks = 0; $paginator = $this->paginator diff --git a/app/Controller/Subtask.php b/app/Controller/Subtask.php index 6ee94333..87f3fcb4 100644 --- a/app/Controller/Subtask.php +++ b/app/Controller/Subtask.php @@ -75,10 +75,10 @@ class Subtask extends Base } if (isset($values['another_subtask']) && $values['another_subtask'] == 1) { - $this->response->redirect('?controller=subtask&action=create&task_id='.$task['id'].'&another_subtask=1&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('subtask', 'create', array('project_id' => $task['project_id'], 'task_id' => $task['id'], 'another_subtask' => 1))); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#subtasks'); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks')); } $this->create($values, $errors); @@ -126,7 +126,7 @@ class Subtask extends Base $this->session->flashError(t('Unable to update your sub-task.')); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#subtasks'); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks')); } $this->edit($values, $errors); @@ -166,7 +166,7 @@ class Subtask extends Base $this->session->flashError(t('Unable to remove this sub-task.')); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#subtasks'); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks')); } /** @@ -256,7 +256,7 @@ class Subtask extends Base case 'dashboard': $this->response->redirect($this->helper->url->to('app', 'index')); default: - $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#subtasks'); + $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'subtasks')); } } @@ -275,6 +275,6 @@ class Subtask extends Base $method = $direction === 'up' ? 'moveUp' : 'moveDown'; $this->subtask->$method($task_id, $subtask_id); - $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $project_id, 'task_id' => $task_id)).'#subtasks'); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $project_id, 'task_id' => $task_id), 'subtasks')); } } diff --git a/app/Controller/Swimlane.php b/app/Controller/Swimlane.php index c6862d47..054fa4ba 100644 --- a/app/Controller/Swimlane.php +++ b/app/Controller/Swimlane.php @@ -25,7 +25,7 @@ class Swimlane extends Base if (empty($swimlane)) { $this->session->flashError(t('Swimlane not found.')); - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project_id); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project_id))); } return $swimlane; @@ -67,7 +67,7 @@ class Swimlane extends Base if ($this->swimlane->create($project['id'], $values['name'])) { $this->session->flash(t('Your swimlane have been created successfully.')); - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } else { $this->session->flashError(t('Unable to create your swimlane.')); @@ -93,7 +93,7 @@ class Swimlane extends Base if ($this->swimlane->updateDefault($values)) { $this->session->flash(t('The default swimlane have been updated successfully.')); - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } else { $this->session->flashError(t('Unable to update this swimlane.')); @@ -137,7 +137,7 @@ class Swimlane extends Base if ($this->swimlane->rename($values['id'], $values['name'])) { $this->session->flash(t('Swimlane updated successfully.')); - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } else { $this->session->flashError(t('Unable to update this swimlane.')); @@ -181,7 +181,7 @@ class Swimlane extends Base $this->session->flashError(t('Unable to remove this swimlane.')); } - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } /** @@ -201,7 +201,7 @@ class Swimlane extends Base $this->session->flashError(t('Unable to update this swimlane.')); } - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } /** @@ -221,7 +221,7 @@ class Swimlane extends Base $this->session->flashError(t('Unable to update this swimlane.')); } - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } /** @@ -236,7 +236,7 @@ class Swimlane extends Base $swimlane_id = $this->request->getIntegerParam('swimlane_id'); $this->swimlane->moveUp($project['id'], $swimlane_id); - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } /** @@ -251,6 +251,6 @@ class Swimlane extends Base $swimlane_id = $this->request->getIntegerParam('swimlane_id'); $this->swimlane->moveDown($project['id'], $swimlane_id); - $this->response->redirect('?controller=swimlane&action=index&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } } diff --git a/app/Controller/Task.php b/app/Controller/Task.php index 0d85f411..676dccbe 100644 --- a/app/Controller/Task.php +++ b/app/Controller/Task.php @@ -163,10 +163,10 @@ class Task extends Base if (isset($values['another_task']) && $values['another_task'] == 1) { unset($values['title']); unset($values['description']); - $this->response->redirect('?controller=task&action=create&'.http_build_query($values)); + $this->response->redirect($this->helper->url->to('task', 'create', $values)); } else { - $this->response->redirect('?controller=board&action=show&project_id='.$project['id']); + $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id']))); } } else { @@ -231,10 +231,10 @@ class Task extends Base $this->session->flash(t('Task updated successfully.')); if ($this->request->getIntegerParam('ajax')) { - $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); } else { - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } } else { @@ -264,7 +264,7 @@ class Task extends Base $this->session->flashError(t('Unable to update your task.')); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } /** @@ -326,7 +326,7 @@ class Task extends Base $this->session->flashError(t('Unable to open this task.')); } - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } $this->response->html($this->taskLayout('task/open', array( @@ -357,7 +357,7 @@ class Task extends Base $this->session->flashError(t('Unable to remove this task.')); } - $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); } $this->response->html($this->taskLayout('task/remove', array( @@ -381,10 +381,10 @@ class Task extends Base if ($task_id) { $this->session->flash(t('Task created successfully.')); - $this->response->redirect('?controller=task&action=show&task_id='.$task_id.'&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } else { $this->session->flashError(t('Unable to create this task.')); - $this->response->redirect('?controller=task&action=duplicate&task_id='.$task['id'].'&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('task', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } } @@ -419,10 +419,10 @@ class Task extends Base } if ($ajax) { - $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); } else { - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } } } @@ -454,7 +454,6 @@ class Task extends Base public function recurrence() { $task = $this->getTask(); - $ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax'); if ($this->request->isPost()) { @@ -471,12 +470,7 @@ class Task extends Base $this->session->flashError(t('Unable to update your task.')); } - if ($ajax) { - $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); - } - else { - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']); - } + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } } else { @@ -488,19 +482,13 @@ class Task extends Base 'values' => $values, 'errors' => $errors, 'task' => $task, - 'ajax' => $ajax, 'recurrence_status_list' => $this->task->getRecurrenceStatusList(), 'recurrence_trigger_list' => $this->task->getRecurrenceTriggerList(), 'recurrence_timeframe_list' => $this->task->getRecurrenceTimeframeList(), 'recurrence_basedate_list' => $this->task->getRecurrenceBasedateList(), ); - if ($ajax) { - $this->response->html($this->template->render('task/edit_recurrence', $params)); - } - else { - $this->response->html($this->taskLayout('task/edit_recurrence', $params)); - } + $this->response->html($this->taskLayout('task/edit_recurrence', $params)); } /** @@ -526,7 +514,7 @@ class Task extends Base if ($this->taskDuplication->moveToProject($task['id'], $values['project_id'])) { $this->session->flash(t('Task updated successfully.')); - $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$values['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } else { $this->session->flashError(t('Unable to update your task.')); @@ -565,7 +553,7 @@ class Task extends Base $task_id = $this->taskDuplication->duplicateToProject($task['id'], $values['project_id']); if ($task_id) { $this->session->flash(t('Task created successfully.')); - $this->response->redirect('?controller=task&action=show&task_id='.$task_id.'&project_id='.$values['project_id']); + $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } else { $this->session->flashError(t('Unable to create your task.')); diff --git a/app/Controller/User.php b/app/Controller/User.php index 119041e5..10a3a931 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -60,7 +60,9 @@ class User extends Base */ public function create(array $values = array(), array $errors = array()) { - $this->response->html($this->template->layout('user/new', array( + $is_remote = $this->request->getIntegerParam('remote') == 1 || (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1); + + $this->response->html($this->template->layout($is_remote ? 'user/create_remote' : 'user/create_local', array( 'timezones' => $this->config->getTimezones(true), 'languages' => $this->config->getLanguages(true), 'board_selector' => $this->projectPermission->getAllowedProjects($this->userSession->getId()), @@ -178,7 +180,7 @@ class User extends Base $this->checkCSRFParam(); $user = $this->getUser(); $this->authentication->backend('rememberMe')->remove($this->request->getIntegerParam('id')); - $this->response->redirect('?controller=user&action=sessions&user_id='.$user['id']); + $this->response->redirect($this->helper->url->to('user', 'session', array('user_id' => $user['id']))); } /** @@ -194,7 +196,7 @@ class User extends Base $values = $this->request->getValues(); $this->notification->saveSettings($user['id'], $values); $this->session->flash(t('User updated successfully.')); - $this->response->redirect('?controller=user&action=notifications&user_id='.$user['id']); + $this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id']))); } $this->response->html($this->layout('user/notifications', array( @@ -272,7 +274,7 @@ class User extends Base $this->session->flashError(t('Unable to change the password.')); } - $this->response->redirect('?controller=user&action=show&user_id='.$user['id']); + $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id']))); } } @@ -298,7 +300,7 @@ class User extends Base if ($this->request->isPost()) { - $values = $this->request->getValues() + array('disable_login_form' => 0); + $values = $this->request->getValues(); if ($this->userSession->isAdmin()) { $values += array('is_admin' => 0); @@ -321,7 +323,7 @@ class User extends Base $this->session->flashError(t('Unable to update your user.')); } - $this->response->redirect('?controller=user&action=show&user_id='.$user['id']); + $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id']))); } } @@ -335,157 +337,67 @@ class User extends Base } /** - * Remove a user + * Display a form to edit authentication * * @access public */ - public function remove() + public function authentication() { $user = $this->getUser(); + $values = $user; + $errors = array(); - if ($this->request->getStringParam('confirmation') === 'yes') { - - $this->checkCSRFParam(); - - if ($this->user->remove($user['id'])) { - $this->session->flash(t('User removed successfully.')); - } else { - $this->session->flashError(t('Unable to remove this user.')); - } - - $this->response->redirect('?controller=user'); - } - - $this->response->html($this->layout('user/remove', array( - 'user' => $user, - ))); - } - - /** - * Google authentication - * - * @access public - */ - public function google() - { - $code = $this->request->getStringParam('code'); - - if ($code) { - - $profile = $this->authentication->backend('google')->getGoogleProfile($code); + unset($values['password']); - if (is_array($profile)) { + if ($this->request->isPost()) { - // If the user is already logged, link the account otherwise authenticate - if ($this->userSession->isLogged()) { + $values = $this->request->getValues() + array('disable_login_form' => 0, 'is_ldap_user' => 0); + list($valid, $errors) = $this->user->validateModification($values); - if ($this->authentication->backend('google')->updateUser($this->userSession->getId(), $profile)) { - $this->session->flash(t('Your Google Account is linked to your profile successfully.')); - } - else { - $this->session->flashError(t('Unable to link your Google Account.')); - } + if ($valid) { - $this->response->redirect('?controller=user&action=external&user_id='.$this->userSession->getId()); - } - else if ($this->authentication->backend('google')->authenticate($profile['id'])) { - $this->response->redirect('?controller=app'); + if ($this->user->update($values)) { + $this->session->flash(t('User updated successfully.')); } else { - $this->response->html($this->template->layout('auth/index', array( - 'errors' => array('login' => t('Google authentication failed')), - 'values' => array(), - 'no_layout' => true, - 'redirect_query' => '', - 'title' => t('Login') - ))); + $this->session->flashError(t('Unable to update your user.')); } - } - } - - $this->response->redirect($this->authentication->backend('google')->getAuthorizationUrl()); - } - /** - * Unlink a Google account - * - * @access public - */ - public function unlinkGoogle() - { - $this->checkCSRFParam(); - if ($this->authentication->backend('google')->unlink($this->userSession->getId())) { - $this->session->flash(t('Your Google Account is not linked anymore to your profile.')); - } - else { - $this->session->flashError(t('Unable to unlink your Google Account.')); + $this->response->redirect($this->helper->url->to('user', 'authentication', array('user_id' => $user['id']))); + } } - $this->response->redirect('?controller=user&action=external&user_id='.$this->userSession->getId()); + $this->response->html($this->layout('user/authentication', array( + 'values' => $values, + 'errors' => $errors, + 'user' => $user, + ))); } /** - * GitHub authentication + * Remove a user * * @access public */ - public function github() + public function remove() { - $code = $this->request->getStringParam('code'); - - if ($code) { - $profile = $this->authentication->backend('gitHub')->getGitHubProfile($code); - - if (is_array($profile)) { + $user = $this->getUser(); - // If the user is already logged, link the account otherwise authenticate - if ($this->userSession->isLogged()) { + if ($this->request->getStringParam('confirmation') === 'yes') { - if ($this->authentication->backend('gitHub')->updateUser($this->userSession->getId(), $profile)) { - $this->session->flash(t('Your GitHub account was successfully linked to your profile.')); - } - else { - $this->session->flashError(t('Unable to link your GitHub Account.')); - } + $this->checkCSRFParam(); - $this->response->redirect('?controller=user&action=external&user_id='.$this->userSession->getId()); - } - else if ($this->authentication->backend('gitHub')->authenticate($profile['id'])) { - $this->response->redirect('?controller=app'); - } - else { - $this->response->html($this->template->layout('auth/index', array( - 'errors' => array('login' => t('GitHub authentication failed')), - 'values' => array(), - 'no_layout' => true, - 'redirect_query' => '', - 'title' => t('Login') - ))); - } + if ($this->user->remove($user['id'])) { + $this->session->flash(t('User removed successfully.')); + } else { + $this->session->flashError(t('Unable to remove this user.')); } - } - - $this->response->redirect($this->authentication->backend('gitHub')->getAuthorizationUrl()); - } - /** - * Unlink a GitHub account - * - * @access public - */ - public function unlinkGithub() - { - $this->checkCSRFParam(); - - $this->authentication->backend('gitHub')->revokeGitHubAccess(); - - if ($this->authentication->backend('gitHub')->unlink($this->userSession->getId())) { - $this->session->flash(t('Your GitHub account is no longer linked to your profile.')); - } - else { - $this->session->flashError(t('Unable to unlink your GitHub Account.')); + $this->response->redirect($this->helper->url->to('user', 'index')); } - $this->response->redirect('?controller=user&action=external&user_id='.$this->userSession->getId()); + $this->response->html($this->layout('user/remove', array( + 'user' => $user, + ))); } } diff --git a/app/Core/HttpClient.php b/app/Core/HttpClient.php index 805c1e5a..b808f756 100644 --- a/app/Core/HttpClient.php +++ b/app/Core/HttpClient.php @@ -32,6 +32,20 @@ class HttpClient extends Base const HTTP_USER_AGENT = 'Kanboard'; /** + * Send a GET HTTP request and parse JSON response + * + * @access public + * @param string $url + * @param string[] $headers + * @return array + */ + public function getJson($url, array $headers = array()) + { + $response = $this->doRequest('GET', $url, '', array_merge(array('Accept: application/json'), $headers)); + return json_decode($response, true) ?: array(); + } + + /** * Send a POST HTTP request encoded in JSON * * @access public @@ -43,6 +57,7 @@ class HttpClient extends Base public function postJson($url, array $data, array $headers = array()) { return $this->doRequest( + 'POST', $url, json_encode($data), array_merge(array('Content-type: application/json'), $headers) @@ -61,6 +76,7 @@ class HttpClient extends Base public function postForm($url, array $data, array $headers = array()) { return $this->doRequest( + 'POST', $url, http_build_query($data), array_merge(array('Content-type: application/x-www-form-urlencoded'), $headers) @@ -71,12 +87,13 @@ class HttpClient extends Base * Make the HTTP request * * @access private + * @param string $method * @param string $url * @param string $content * @param string[] $headers * @return string */ - private function doRequest($url, $content, array $headers) + private function doRequest($method, $url, $content, array $headers) { if (empty($url)) { return ''; @@ -86,7 +103,7 @@ class HttpClient extends Base $context = stream_context_create(array( 'http' => array( - 'method' => 'POST', + 'method' => $method, 'protocol_version' => 1.1, 'timeout' => self::HTTP_TIMEOUT, 'max_redirects' => self::HTTP_MAX_REDIRECTS, diff --git a/app/Core/Lexer.php b/app/Core/Lexer.php index 3887dc82..0a237254 100644 --- a/app/Core/Lexer.php +++ b/app/Core/Lexer.php @@ -33,6 +33,7 @@ class Lexer "/^(category:)/" => 'T_CATEGORY', "/^(column:)/" => 'T_COLUMN', "/^(project:)/" => 'T_PROJECT', + "/^(swimlane:)/" => 'T_SWIMLANE', "/^(ref:)/" => 'T_REFERENCE', "/^(reference:)/" => 'T_REFERENCE', "/^(\s+)/" => 'T_WHITESPACE', @@ -116,6 +117,7 @@ class Lexer case 'T_CATEGORY': case 'T_COLUMN': case 'T_PROJECT': + case 'T_SWIMLANE': $next = next($tokens); if ($next !== false && $next['token'] === 'T_STRING') { diff --git a/app/Core/OAuth2.php b/app/Core/OAuth2.php new file mode 100644 index 00000000..a7d04f33 --- /dev/null +++ b/app/Core/OAuth2.php @@ -0,0 +1,120 @@ +<?php + +namespace Core; + +/** + * OAuth2 client + * + * @package core + * @author Frederic Guillot + */ +class OAuth2 extends Base +{ + private $clientId; + private $secret; + private $callbackUrl; + private $authUrl; + private $tokenUrl; + private $scopes; + private $tokenType; + private $accessToken; + + /** + * Create OAuth2 service + * + * @access public + * @param string $clientId + * @param string $secret + * @param string $callbackUrl + * @param string $authUrl + * @param string $tokenUrl + * @param array $scopes + * @return OAuth2 + */ + public function createService($clientId, $secret, $callbackUrl, $authUrl, $tokenUrl, array $scopes) + { + $this->clientId = $clientId; + $this->secret = $secret; + $this->callbackUrl = $callbackUrl; + $this->authUrl = $authUrl; + $this->tokenUrl = $tokenUrl; + $this->scopes = $scopes; + + return $this; + } + + /** + * Get authorization url + * + * @access public + * @return string + */ + public function getAuthorizationUrl() + { + $params = array( + 'response_type' => 'code', + 'client_id' => $this->clientId, + 'redirect_uri' => $this->callbackUrl, + 'scope' => implode(' ', $this->scopes), + ); + + return $this->authUrl.'?'.http_build_query($params); + } + + /** + * Get authorization header + * + * @access public + * @return string + */ + public function getAuthorizationHeader() + { + if (strtolower($this->tokenType) === 'bearer') { + return 'Authorization: Bearer '.$this->accessToken; + } + + return ''; + } + + /** + * Get access token + * + * @access public + * @param string $code + * @return string + */ + public function getAccessToken($code) + { + if (empty($this->accessToken) && ! empty($code)) { + + $params = array( + 'code' => $code, + 'client_id' => $this->clientId, + 'client_secret' => $this->secret, + 'redirect_uri' => $this->callbackUrl, + 'grant_type' => 'authorization_code', + ); + + $response = json_decode($this->httpClient->postForm($this->tokenUrl, $params, array('Accept: application/json')), true); + + $this->tokenType = isset($response['token_type']) ? $response['token_type'] : ''; + $this->accessToken = isset($response['access_token']) ? $response['access_token'] : ''; + } + + return $this->accessToken; + } + + /** + * Set access token + * + * @access public + * @param string $token + * @param string $type + * @return string + */ + public function setAccessToken($token, $type = 'bearer') + { + $this->accessToken = $token; + $this->tokenType = $type; + } +} diff --git a/app/Core/Request.php b/app/Core/Request.php index b399a1f0..1eff66fa 100644 --- a/app/Core/Request.php +++ b/app/Core/Request.php @@ -163,6 +163,17 @@ class Request } /** + * Returns uri + * + * @access public + * @return string + */ + public function getUri() + { + return isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; + } + + /** * Get the user agent * * @static diff --git a/app/Core/Router.php b/app/Core/Router.php index 36c11a0a..ae989de5 100644 --- a/app/Core/Router.php +++ b/app/Core/Router.php @@ -2,53 +2,151 @@ namespace Core; -use Pimple\Container; - /** * Router class * * @package core * @author Frederic Guillot */ -class Router +class Router extends Base { /** - * Controller name + * Store routes for path lookup * * @access private - * @var string + * @var array */ - private $controller = ''; + private $paths = array(); /** - * Action name + * Store routes for url lookup * * @access private - * @var string + * @var array */ - private $action = ''; + private $urls = array(); /** - * Container instance + * Get the path to compare patterns * - * @access private - * @var \Pimple\Container + * @access public + * @param string $uri + * @param string $query_string + * @return string */ - private $container; + public function getPath($uri, $query_string = '') + { + $path = substr($uri, strlen($this->helper->url->dir())); + + if (! empty($query_string)) { + $path = substr($path, 0, - strlen($query_string) - 1); + } + + if ($path{0} === '/') { + $path = substr($path, 1); + } + + return $path; + } + + /** + * Add route + * + * @access public + * @param string $path + * @param string $controller + * @param string $action + * @param array $params + */ + public function addRoute($path, $controller, $action, array $params = array()) + { + $pattern = explode('/', $path); + + $this->paths[] = array( + 'pattern' => $pattern, + 'count' => count($pattern), + 'controller' => $controller, + 'action' => $action, + ); + + $this->urls[$controller][$action][] = array( + 'path' => $path, + 'params' => array_flip($params), + 'count' => count($params), + ); + } + + /** + * Find a route according to the given path + * + * @access public + * @param string $path + * @return array + */ + public function findRoute($path) + { + $parts = explode('/', $path); + $count = count($parts); + + foreach ($this->paths as $route) { + + if ($count === $route['count']) { + + $params = array(); + + for ($i = 0; $i < $count; $i++) { + + if ($route['pattern'][$i]{0} === ':') { + $params[substr($route['pattern'][$i], 1)] = $parts[$i]; + } + else if ($route['pattern'][$i] !== $parts[$i]) { + break; + } + } + + if ($i === $count) { + $_GET = array_merge($_GET, $params); + return array($route['controller'], $route['action']); + } + } + } + + return array('app', 'index'); + } /** - * Constructor + * Find route url * * @access public - * @param \Pimple\Container $container Container instance - * @param string $controller Controller name - * @param string $action Action name + * @param string $controller + * @param string $action + * @param array $params + * @return string */ - public function __construct(Container $container, $controller = '', $action = '') + public function findUrl($controller, $action, array $params = array()) { - $this->container = $container; - $this->controller = empty($_GET['controller']) ? $controller : $_GET['controller']; - $this->action = empty($_GET['action']) ? $action : $_GET['action']; + if (! isset($this->urls[$controller][$action])) { + return ''; + } + + foreach ($this->urls[$controller][$action] as $pattern) { + + if (array_diff_key($params, $pattern['params']) === array()) { + $url = $pattern['path']; + $i = 0; + + foreach ($params as $variable => $value) { + $url = str_replace(':'.$variable, $value, $url); + $i++; + } + + if ($i === $pattern['count']) { + return $url; + } + } + } + + return ''; } /** @@ -65,15 +163,42 @@ class Router } /** - * Load a controller and execute the action + * Find controller/action from the route table or from get arguments * * @access public - * @param string $filename Controller filename - * @param string $class Class name - * @param string $method Method name + * @param string $uri + * @param string $query_string + * @return boolean + */ + public function dispatch($uri, $query_string = '') + { + if (! empty($_GET['controller']) && ! empty($_GET['action'])) { + $controller = $this->sanitize($_GET['controller'], 'app'); + $action = $this->sanitize($_GET['action'], 'index'); + } + else { + list($controller, $action) = $this->findRoute($this->getPath($uri, $query_string)); + } + + return $this->load( + __DIR__.'/../Controller/'.ucfirst($controller).'.php', + $controller, + '\Controller\\'.ucfirst($controller), + $action + ); + } + + /** + * Load a controller and execute the action + * + * @access private + * @param string $filename + * @param string $controller + * @param string $class + * @param string $method * @return bool */ - public function load($filename, $class, $method) + private function load($filename, $controller, $class, $method) { if (file_exists($filename)) { @@ -84,7 +209,7 @@ class Router } $instance = new $class($this->container); - $instance->beforeAction($this->controller, $this->action); + $instance->beforeAction($controller, $method); $instance->$method(); return true; @@ -92,20 +217,4 @@ class Router return false; } - - /** - * Find a route - * - * @access public - */ - public function execute() - { - $this->controller = $this->sanitize($this->controller, 'app'); - $this->action = $this->sanitize($this->action, 'index'); - $filename = __DIR__.'/../Controller/'.ucfirst($this->controller).'.php'; - - if (! $this->load($filename, '\Controller\\'.$this->controller, $this->action)) { - die('Page not found!'); - } - } } diff --git a/app/Core/Session.php b/app/Core/Session.php index c35014cd..0e5f7426 100644 --- a/app/Core/Session.php +++ b/app/Core/Session.php @@ -41,8 +41,6 @@ class Session implements ArrayAccess */ public function open($base_path = '/') { - $base_path = str_replace('\\', '/', $base_path); - // HttpOnly and secure flags for session cookie session_set_cookie_params( self::SESSION_LIFETIME, diff --git a/app/Helper/Asset.php b/app/Helper/Asset.php index 1b1e47c5..fd555e07 100644 --- a/app/Helper/Asset.php +++ b/app/Helper/Asset.php @@ -18,7 +18,7 @@ class Asset extends \Core\Base */ public function js($filename, $async = false) { - return '<script '.($async ? 'async' : '').' type="text/javascript" src="'.$filename.'?'.filemtime($filename).'"></script>'; + return '<script '.($async ? 'async' : '').' type="text/javascript" src="'.$this->helper->url->dir().$filename.'?'.filemtime($filename).'"></script>'; } /** @@ -31,7 +31,7 @@ class Asset extends \Core\Base */ public function css($filename, $is_file = true, $media = 'screen') { - return '<link rel="stylesheet" href="'.$filename.($is_file ? '?'.filemtime($filename) : '').'" media="'.$media.'">'; + return '<link rel="stylesheet" href="'.$this->helper->url->dir().$filename.($is_file ? '?'.filemtime($filename) : '').'" media="'.$media.'">'; } /** diff --git a/app/Helper/Url.php b/app/Helper/Url.php index 8de63f8d..964e0762 100644 --- a/app/Helper/Url.php +++ b/app/Helper/Url.php @@ -13,6 +13,9 @@ use Core\Security; */ class Url extends \Core\Base { + private $base = ''; + private $directory = ''; + /** * HTML Link tag * @@ -33,7 +36,7 @@ class Url extends \Core\Base } /** - * Hyperlink + * HTML Hyperlink * * @access public * @param string $controller Controller name @@ -41,22 +44,12 @@ class Url extends \Core\Base * @param array $params Url parameters * @param boolean $csrf Add a CSRF token * @param string $anchor Link Anchor + * @param boolean $absolute Absolute or relative link * @return string */ - public function href($controller, $action, array $params = array(), $csrf = false, $anchor = '') + public function href($controller, $action, array $params = array(), $csrf = false, $anchor = '', $absolute = false) { - $values = array( - 'controller' => $controller, - 'action' => $action, - ); - - if ($csrf) { - $params['csrf_token'] = Security::getCSRFToken(); - } - - $values += $params; - - return '?'.http_build_query($values, '', '&').(empty($anchor) ? '' : '#'.$anchor); + return $this->build('&', $controller, $action, $params, $csrf, $anchor, $absolute); } /** @@ -66,18 +59,13 @@ class Url extends \Core\Base * @param string $controller Controller name * @param string $action Action name * @param array $params Url parameters + * @param string $anchor Link Anchor + * @param boolean $absolute Absolute or relative link * @return string */ - public function to($controller, $action, array $params = array()) + public function to($controller, $action, array $params = array(), $anchor = '', $absolute = false) { - $values = array( - 'controller' => $controller, - 'action' => $action, - ); - - $values += $params; - - return '?'.http_build_query($values, '', '&'); + return $this->build('&', $controller, $action, $params, false, $anchor, $absolute); } /** @@ -88,7 +76,28 @@ class Url extends \Core\Base */ public function base() { - return $this->config->get('application_url') ?: $this->server(); + if (empty($this->base)) { + $this->base = $this->config->get('application_url') ?: $this->server(); + } + + return $this->base; + } + + /** + * Get application base directory + * + * @access public + * @return string + */ + public function dir() + { + if (empty($this->directory) && isset($_SERVER['REQUEST_METHOD'])) { + $this->directory = str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])); + $this->directory = $this->directory !== '/' ? $this->directory.'/' : '/'; + $this->directory = str_replace('//', '/', $this->directory); + } + + return $this->directory; } /** @@ -103,13 +112,46 @@ class Url extends \Core\Base return 'http://localhost/'; } - $self = str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])); - $url = Request::isHTTPS() ? 'https://' : 'http://'; $url .= $_SERVER['SERVER_NAME']; $url .= $_SERVER['SERVER_PORT'] == 80 || $_SERVER['SERVER_PORT'] == 443 ? '' : ':'.$_SERVER['SERVER_PORT']; - $url .= $self !== '/' ? $self.'/' : '/'; + $url .= $this->dir() ?: '/'; return $url; } + + /** + * Build relative url + * + * @access private + * @param string $separator Querystring argument separator + * @param string $controller Controller name + * @param string $action Action name + * @param array $params Url parameters + * @param boolean $csrf Add a CSRF token + * @param string $anchor Link Anchor + * @param boolean $absolute Absolute or relative link + * @return string + */ + private function build($separator, $controller, $action, array $params = array(), $csrf = false, $anchor = '', $absolute = false) + { + $path = $this->router->findUrl($controller, $action, $params); + $qs = array(); + + if (empty($path)) { + $qs['controller'] = $controller; + $qs['action'] = $action; + $qs += $params; + } + + if ($csrf) { + $qs['csrf_token'] = Security::getCSRFToken(); + } + + if (! empty($qs)) { + $path .= '?'.http_build_query($qs, '', $separator); + } + + return ($absolute ? $this->base() : $this->dir()).$path.(empty($anchor) ? '' : '#'.$anchor); + } } diff --git a/app/Integration/GitlabWebhook.php b/app/Integration/GitlabWebhook.php index dce7413a..b8925daf 100644 --- a/app/Integration/GitlabWebhook.php +++ b/app/Integration/GitlabWebhook.php @@ -21,14 +21,16 @@ class GitlabWebhook extends \Core\Base const EVENT_ISSUE_OPENED = 'gitlab.webhook.issue.opened'; const EVENT_ISSUE_CLOSED = 'gitlab.webhook.issue.closed'; const EVENT_COMMIT = 'gitlab.webhook.commit'; + const EVENT_ISSUE_COMMENT = 'gitlab.webhook.issue.commented'; /** * Supported webhook events * * @var string */ - const TYPE_PUSH = 'push'; - const TYPE_ISSUE = 'issue'; + const TYPE_PUSH = 'push'; + const TYPE_ISSUE = 'issue'; + const TYPE_COMMENT = 'comment'; /** * Project id @@ -63,6 +65,8 @@ class GitlabWebhook extends \Core\Base return $this->handlePushEvent($payload); case self::TYPE_ISSUE; return $this->handleIssueEvent($payload); + case self::TYPE_COMMENT; + return $this->handleCommentEvent($payload); } return false; @@ -77,15 +81,20 @@ class GitlabWebhook extends \Core\Base */ public function getType(array $payload) { - if (isset($payload['object_kind']) && $payload['object_kind'] === 'issue') { - return self::TYPE_ISSUE; + if (empty($payload['object_kind'])) { + return ''; } - if (isset($payload['commits'])) { - return self::TYPE_PUSH; + switch ($payload['object_kind']) { + case 'issue': + return self::TYPE_ISSUE; + case 'note': + return self::TYPE_COMMENT; + case 'push': + return self::TYPE_PUSH; + default: + return ''; } - - return ''; } /** @@ -213,4 +222,46 @@ class GitlabWebhook extends \Core\Base return false; } + + /** + * Parse comment issue events + * + * @access public + * @param array $payload Event data + * @return boolean + */ + public function handleCommentEvent(array $payload) + { + if (! isset($payload['issue'])) { + return false; + } + + $task = $this->taskFinder->getByReference($this->project_id, $payload['issue']['id']); + + if (! empty($task)) { + + $user = $this->user->getByUsername($payload['user']['username']); + + if (! empty($user) && ! $this->projectPermission->isMember($this->project_id, $user['id'])) { + $user = array(); + } + + $event = array( + 'project_id' => $this->project_id, + 'reference' => $payload['object_attributes']['id'], + 'comment' => $payload['object_attributes']['note']."\n\n[".t('By @%s on Gitlab', $payload['user']['username']).']('.$payload['object_attributes']['url'].')', + 'user_id' => ! empty($user) ? $user['id'] : 0, + 'task_id' => $task['id'], + ); + + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_COMMENT, + new GenericEvent($event) + ); + + return true; + } + + return false; + } } diff --git a/app/Integration/HipchatWebhook.php b/app/Integration/HipchatWebhook.php index f1be0f34..1d08e514 100644 --- a/app/Integration/HipchatWebhook.php +++ b/app/Integration/HipchatWebhook.php @@ -72,8 +72,7 @@ class HipchatWebhook extends \Core\Base $html .= $this->projectActivity->getTitle($event); if ($this->config->get('application_url')) { - $html .= '<br/><a href="'.$this->config->get('application_url'); - $html .= $this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id)).'">'; + $html .= '<br/><a href="'.$this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), false, '', true).'">'; $html .= t('view the task on Kanboard').'</a>'; } diff --git a/app/Integration/Jabber.php b/app/Integration/Jabber.php index a1191662..3e403aab 100644 --- a/app/Integration/Jabber.php +++ b/app/Integration/Jabber.php @@ -81,8 +81,7 @@ class Jabber extends \Core\Base $payload = '['.$project['name'].'] '.str_replace('"', '"', $this->projectActivity->getTitle($event)).(isset($event['task']['title']) ? ' ('.$event['task']['title'].')' : ''); if ($this->config->get('application_url')) { - $payload .= ' '.$this->config->get('application_url'); - $payload .= $this->helper->url->to('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id)); + $payload .= ' '.$this->helper->url->to('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), false, '', true); } $this->sendMessage($project_id, $payload); diff --git a/app/Integration/SlackWebhook.php b/app/Integration/SlackWebhook.php index 498cea09..d238652f 100644 --- a/app/Integration/SlackWebhook.php +++ b/app/Integration/SlackWebhook.php @@ -83,8 +83,7 @@ class SlackWebhook extends \Core\Base ); if ($this->config->get('application_url')) { - $payload['text'] .= ' - <'.$this->config->get('application_url'); - $payload['text'] .= $this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id)); + $payload['text'] .= ' - <'.$this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), false, '', true); $payload['text'] .= '|'.t('view the task on Kanboard').'>'; } diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 91d7b98a..5f55f3e8 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Projektets navn er krævet', 'This project must be unique' => 'Projektets navn skal være unikt', 'The title is required' => 'Titel er krævet', - 'There is no active project, the first step is to create a new project.' => 'Der er ingen aktive projekter. Første step er at oprette et nyt projekt.', 'Settings saved successfully.' => 'Indstillinger gemt.', 'Unable to save your settings.' => 'Indstillinger kunne ikke gemmes.', 'Database optimization done.' => 'Databaseoptimeringen er fuldført.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d kommentarer', '%d comment' => '%d kommentar', 'Email address invalid' => 'Ugyldig email', - 'Your Google Account is not linked anymore to your profile.' => 'Din Google-konto er ikke længere forbundet til din profil.', - 'Unable to unlink your Google Account.' => 'Det var ikke muligt at fjerne din Google-konto.', - 'Google authentication failed' => 'Google autentificering mislykkedes', - 'Unable to link your Google Account.' => 'Det var ikke muligt at forbinde til din Google-konto.', - 'Your Google Account is linked to your profile successfully.' => 'Din Google-konto er forbundet til din profil.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-Mail', 'Link my Google Account' => 'Forbind min Google-konto', 'Unlink my Google Account' => 'Fjern forbindelsen til min Google-konto', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Maksimum størrelse: ', 'Unable to upload the file.' => 'Filen kunne ikke uploades.', 'Display another project' => 'Vis et andet projekt...', - 'Your GitHub account was successfully linked to your profile.' => 'Din GitHub-konto er forbundet til din profil.', - 'Unable to link your GitHub Account.' => 'Det var ikke muligt er forbinde til din GitHub-konto.', - 'GitHub authentication failed' => 'GitHub autentificering mislykkedes', - 'Your GitHub account is no longer linked to your profile.' => 'Din GitHub-konto er ikke længere forbundet til din profil.', - 'Unable to unlink your GitHub Account.' => 'Det var ikke muligt at fjerne forbindelsen til din GitHub-konto.', - 'Login with my GitHub Account' => 'Login med min GitHub-konto', - 'Link my GitHub Account' => 'Forbind min GitHub-konto', - 'Unlink my GitHub Account' => 'Fjern forbindelsen til min GitHub-konto', + 'Login with my Github Account' => 'Login med min Github-konto', + 'Link my Github Account' => 'Forbind min Github-konto', + 'Unlink my Github Account' => 'Fjern forbindelsen til min Github-konto', 'Created by %s' => 'Oprettet af %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Sidst redigeret %d.%m.%Y - %H:%M', 'Tasks Export' => 'Opgave eksport', @@ -403,7 +396,7 @@ return array( 'Enabled' => 'Aktiv', 'Disabled' => 'Deaktiveret', 'Google account linked' => 'Google-konto forbundet', - 'Github account linked' => 'GitHub-konto forbundet', + 'Github account linked' => 'Github-konto forbundet', 'Username:' => 'Brugernavn', 'Name:' => 'Navn:', 'Email:' => 'Email:', @@ -417,7 +410,7 @@ return array( 'Password modification' => 'Adgangskode ændring', 'External authentications' => 'Ekstern autentificering', 'Google Account' => 'Google-konto', - 'Github Account' => 'GitHub-konto', + 'Github Account' => 'Github-konto', 'Never connected.' => 'Aldrig forbundet.', 'No account linked.' => 'Ingen kontoer forfundet.', 'Account linked.' => 'Konto forbundet.', @@ -615,8 +608,7 @@ return array( // 'Time Tracking' => '', // 'You already have one subtask in progress' => '', // 'Which parts of the project do you want to duplicate?' => '', - // 'Disable login form' => '', - // 'Show/hide calendar' => '', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', // 'Bitbucket webhooks' => '', // 'Help on Bitbucket webhooks' => '', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 100335c5..90c029ba 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -91,7 +91,7 @@ return array( 'Download the database' => 'Datenbank herunterladen', 'Optimize the database' => 'Datenbank optimieren', '(VACUUM command)' => '(VACUUM Befehl)', - '(Gzip compressed Sqlite file)' => '(Gzip-komprimierte Sqlite Datei)', + '(Gzip compressed Sqlite file)' => '(Gzip-komprimierte SQLite-Datei)', 'Close a task' => 'Aufgabe abschließen', 'Edit a task' => 'Aufgabe bearbeiten', 'Column' => 'Spalte', @@ -117,7 +117,7 @@ return array( 'The password is required' => 'Das Passwort wird benötigt', 'This value must be an integer' => 'Dieser Wert muss eine ganze Zahl sein', 'The username must be unique' => 'Der Benutzername muss eindeutig sein', - 'The user id is required' => 'Die Benutzer ID ist anzugeben', + 'The user id is required' => 'Die Benutzer-ID ist anzugeben', 'Passwords don\'t match' => 'Passwörter nicht gleich', 'The confirmation is required' => 'Die Bestätigung ist erforderlich', 'The project is required' => 'Das Projekt ist anzugeben', @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Der Projektname ist anzugeben', 'This project must be unique' => 'Der Projektname muss eindeutig sein', 'The title is required' => 'Der Titel ist anzugeben', - 'There is no active project, the first step is to create a new project.' => 'Es gibt kein aktives Projekt. Zunächst muss ein Projekt erstellt werden.', 'Settings saved successfully.' => 'Einstellungen erfolgreich gespeichert.', 'Unable to save your settings.' => 'Speichern der Einstellungen nicht möglich.', 'Database optimization done.' => 'Optimieren der Datenbank abgeschlossen.', @@ -246,8 +245,8 @@ return array( 'Last logins' => 'Letzte Anmeldungen', 'Login date' => 'Anmeldedatum', 'Authentication method' => 'Authentisierungsmethode', - 'IP address' => 'IP Adresse', - 'User agent' => 'User Agent', + 'IP address' => 'IP-Adresse', + 'User agent' => 'User-Agent', 'Persistent connections' => 'Bestehende Verbindungen', 'No session.' => 'Keine Sitzung.', 'Expiration date' => 'Ablaufdatum', @@ -264,15 +263,14 @@ return array( '%d comments' => '%d Kommentare', '%d comment' => '%d Kommentar', 'Email address invalid' => 'Ungültige E-Mail-Adresse', - 'Your Google Account is not linked anymore to your profile.' => 'Google Account nicht mehr mit dem Profil verbunden.', - 'Unable to unlink your Google Account.' => 'Trennung der Verbindung zum Google Account nicht möglich.', - 'Google authentication failed' => 'Zugriff mit Google fehlgeschlagen', - 'Unable to link your Google Account.' => 'Verbindung mit diesem Google Account nicht möglich.', - 'Your Google Account is linked to your profile successfully.' => 'Der Google Account wurde erfolgreich verbunden.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-Mail', - 'Link my Google Account' => 'Verbinde meinen Google Account', - 'Unlink my Google Account' => 'Verbindung mit meinem Google Account trennen', - 'Login with my Google Account' => 'Anmelden mit meinem Google Account', + 'Link my Google Account' => 'Verbinde meinen Google-Account', + 'Unlink my Google Account' => 'Verbindung mit meinem Google-Account trennen', + 'Login with my Google Account' => 'Anmelden mit meinem Google-Account', 'Project not found.' => 'Das Projekt wurde nicht gefunden.', 'Task removed successfully.' => 'Aufgabe erfolgreich gelöscht.', 'Unable to remove this task.' => 'Löschen der Aufgabe nicht möglich.', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Maximalgröße: ', 'Unable to upload the file.' => 'Hochladen der Datei nicht möglich.', 'Display another project' => 'Zu Projekt wechseln', - 'Your GitHub account was successfully linked to your profile.' => 'GitHub Account erfolgreich mit dem Profil verbunden.', - 'Unable to link your GitHub Account.' => 'Verbindung mit diesem GitHub Account nicht möglich.', - 'GitHub authentication failed' => 'Zugriff mit GitHub fehlgeschlagen', - 'Your GitHub account is no longer linked to your profile.' => 'GitHub Account nicht mehr mit dem Profil verbunden.', - 'Unable to unlink your GitHub Account.' => 'Trennung der Verbindung zum GitHub Account nicht möglich.', - 'Login with my GitHub Account' => 'Anmelden mit meinem GitHub Account', - 'Link my GitHub Account' => 'Mit meinem GitHub Account verbinden', - 'Unlink my GitHub Account' => 'Verbindung mit meinem GitHub Account trennen', + 'Login with my Github Account' => 'Anmelden mit meinem Github-Account', + 'Link my Github Account' => 'Mit meinem Github-Account verbinden', + 'Unlink my Github Account' => 'Verbindung mit meinem Github-Account trennen', 'Created by %s' => 'Erstellt durch %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Letzte Änderung am %d.%m.%Y um %H:%M', 'Tasks Export' => 'Aufgaben exportieren', @@ -360,8 +353,8 @@ return array( 'Clone' => 'duplizieren', 'Project cloned successfully.' => 'Projekt wurde dupliziert.', 'Unable to clone this project.' => 'Duplizieren dieses Projekts schlug fehl.', - 'Email notifications' => 'E-Mail Benachrichtigungen', - 'Enable email notifications' => 'E-Mail Benachrichtigungen einschalten', + 'Email notifications' => 'E-Mail-Benachrichtigungen', + 'Enable email notifications' => 'E-Mail-Benachrichtigungen einschalten', 'Task position:' => 'Position der Aufgabe', 'The task #%d have been opened.' => 'Die Aufgabe #%d wurde geöffnet.', 'The task #%d have been closed.' => 'Die Aufgabe #%d wurde geschlossen.', @@ -402,8 +395,8 @@ return array( 'Remote' => 'Remote', 'Enabled' => 'angeschaltet', 'Disabled' => 'abgeschaltet', - 'Google account linked' => 'Mit Googleaccount verbunden', - 'Github account linked' => 'Mit Githubaccount verbunden', + 'Google account linked' => 'Mit Google-Account verbunden', + 'Github account linked' => 'Mit Github-Account verbunden', 'Username:' => 'Benutzername', 'Name:' => 'Name', 'Email:' => 'E-Mail', @@ -416,8 +409,8 @@ return array( 'Change password' => 'Passwort ändern', 'Password modification' => 'Passwortänderung', 'External authentications' => 'Externe Authentisierungsmethoden', - 'Google Account' => 'Googleaccount', - 'Github Account' => 'Githubaccount', + 'Google Account' => 'Google-Account', + 'Github Account' => 'Github-Account', 'Never connected.' => 'Noch nie verbunden.', 'No account linked.' => 'Kein Account verbunden.', 'Account linked.' => 'Account verbunden', @@ -475,17 +468,17 @@ return array( 'Database driver:' => 'Datenbanktreiber', 'Board settings' => 'Pinnwandeinstellungen', 'URL and token' => 'URL und Token', - 'Webhook settings' => 'Webhook Einstellungen', + 'Webhook settings' => 'Webhook-Einstellungen', 'URL for task creation:' => 'URL zur Aufgabenerstellung', 'Reset token' => 'Token zurücksetzen', - 'API endpoint:' => 'API Endpunkt', + 'API endpoint:' => 'API-Endpunkt', 'Refresh interval for private board' => 'Aktualisierungsintervall für private Pinnwände', 'Refresh interval for public board' => 'Aktualisierungsintervall für öffentliche Pinnwände', 'Task highlight period' => 'Aufgaben-Hervorhebungsdauer', 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Dauer (in Sekunden), wie lange eine Aufgabe als kürzlich verändert gilt (0 um diese Funktion zu deaktivieren, standardmäßig 2 Tage)', 'Frequency in second (60 seconds by default)' => 'Frequenz in Sekunden (standardmäßig 60 Sekunden)', 'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frequenz in Sekunden (0 um diese Funktion zu deaktivieren, standardmäßig 10 Sekunden)', - 'Application URL' => 'Applikations URL', + 'Application URL' => 'Applikations-URL', 'Example: http://example.kanboard.net/ (used by email notifications)' => 'Beispiel: http://example.kanboard.net/ (wird für E-Mail-Benachrichtigungen verwendet)', 'Token regenerated.' => 'Token wurde neu generiert.', 'Date format' => 'Datumsformat', @@ -508,10 +501,10 @@ return array( 'Everybody have access to this project.' => 'Jeder hat Zugriff zu diesem Projekt', 'Webhooks' => 'Webhooks', 'API' => 'API', - 'Github webhooks' => 'Github Webhook', - 'Help on Github webhooks' => 'Hilfe für Github Webhooks', + 'Github webhooks' => 'Github-Webhook', + 'Help on Github webhooks' => 'Hilfe für Github-Webhooks', 'Create a comment from an external provider' => 'Kommentar eines externen Providers hinzufügen', - 'Github issue comment created' => 'Github Fehler Kommentar hinzugefügt', + 'Github issue comment created' => 'Kommentar zum Github-Issue hinzugefügt', 'Project management' => 'Projektmanagement', 'My projects' => 'Meine Projekte', 'Columns' => 'Spalten', @@ -533,15 +526,15 @@ return array( 'Not enough data to show the graph.' => 'Nicht genügend Daten, um die Grafik zu zeigen.', 'Previous' => 'Vorherige', 'The id must be an integer' => 'Die Id muss eine ganze Zahl sein', - 'The project id must be an integer' => 'Der Projektid muss eine ganze Zahl sein', + 'The project id must be an integer' => 'Der Projekt-ID muss eine ganze Zahl sein', 'The status must be an integer' => 'Der Status muss eine ganze Zahl sein', - 'The subtask id is required' => 'Die Teilaufgabenid ist benötigt', - 'The subtask id must be an integer' => 'Die Teilaufgabenid muss eine ganze Zahl sein', - 'The task id is required' => 'Die Aufgabenid ist benötigt', - 'The task id must be an integer' => 'Die Aufgabenid muss eine ganze Zahl sein', - 'The user id must be an integer' => 'Die Userid muss eine ganze Zahl sein', + 'The subtask id is required' => 'Die Teilaufgaben-ID ist benötigt', + 'The subtask id must be an integer' => 'Die Teilaufgaben-ID muss eine ganze Zahl sein', + 'The task id is required' => 'Die Aufgaben-ID ist benötigt', + 'The task id must be an integer' => 'Die Aufgaben-ID muss eine ganze Zahl sein', + 'The user id must be an integer' => 'Die User-ID muss eine ganze Zahl sein', 'This value is required' => 'Dieser Wert ist erforderlich', - 'This value must be numeric' => 'Dieser Wert muss numerisch sein', + 'This value must be numeric' => 'Dieser Wert muss nummerisch sein', 'Unable to create this task.' => 'Diese Aufgabe kann nicht erstellt werden', 'Cumulative flow diagram' => 'Kumulatives Flussdiagramm', 'Cumulative flow diagram for "%s"' => 'Kumulatives Flussdiagramm für "%s"', @@ -555,44 +548,44 @@ return array( 'Write' => 'Ändern', 'Active swimlanes' => 'Aktive Swimlane', 'Add a new swimlane' => 'Eine neue Swimlane hinzufügen', - 'Change default swimlane' => 'Standard Swimlane ändern', - 'Default swimlane' => 'Standard Swimlane', + 'Change default swimlane' => 'Standard-Swimlane ändern', + 'Default swimlane' => 'Standard-Swimlane', 'Do you really want to remove this swimlane: "%s"?' => 'Diese Swimlane wirklich ändern: "%s"?', 'Inactive swimlanes' => 'Inaktive Swimlane', 'Set project manager' => 'zum Projektmanager machen', 'Set project member' => 'zum Projektmitglied machen', 'Remove a swimlane' => 'Swimlane entfernen', 'Rename' => 'umbenennen', - 'Show default swimlane' => 'Standard Swimlane anzeigen', - 'Swimlane modification for the project "%s"' => 'Swimlane Änderung für das Projekt "%s"', + 'Show default swimlane' => 'Standard-Swimlane anzeigen', + 'Swimlane modification for the project "%s"' => 'Swimlane-Änderung für das Projekt "%s"', 'Swimlane not found.' => 'Swimlane nicht gefunden', 'Swimlane removed successfully.' => 'Swimlane erfolgreich entfernt.', 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane erfolgreich geändert.', - 'The default swimlane have been updated successfully.' => 'Die standard Swimlane wurden erfolgreich aktualisiert. Die standard Swimlane wurden erfolgreich aktualisiert.', - 'Unable to create your swimlane.' => 'Es ist nicht möglich die Swimlane zu erstellen.', - 'Unable to remove this swimlane.' => 'Es ist nicht möglich die Swimlane zu entfernen.', - 'Unable to update this swimlane.' => 'Es ist nicht möglich die Swimöane zu ändern.', + 'The default swimlane have been updated successfully.' => 'Die Standard-Swimlane wurden erfolgreich aktualisiert. Die Standard-Swimlane wurden erfolgreich aktualisiert.', + 'Unable to create your swimlane.' => 'Es ist nicht möglich, Swimlane zu erstellen.', + 'Unable to remove this swimlane.' => 'Es ist nicht möglich, die Swimlane zu entfernen.', + 'Unable to update this swimlane.' => 'Es ist nicht möglich, die Swimlane zu ändern.', 'Your swimlane have been created successfully.' => 'Die Swimlane wurde erfolgreich angelegt.', '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)', - 'Gitlab commit received' => 'Gitlab commit erhalten', - 'Gitlab issue opened' => 'Gitlab Fehler eröffnet', - 'Gitlab issue closed' => 'Gitlab Fehler geschlossen', - 'Gitlab webhooks' => 'Gitlab Webhook', - 'Help on Gitlab webhooks' => 'Hilfe für Gitlab Webhooks', + 'Default categories for new projects (Comma-separated)' => 'Standard-Kategorien für neue Projekte (Komma-getrennt)', + 'Gitlab commit received' => 'Gitlab-Commit erhalten', + 'Gitlab issue opened' => 'Gitlab-Issue eröffnet', + 'Gitlab issue closed' => 'Gitlab-Issue geschlossen', + 'Gitlab webhooks' => 'Gitlab-Webhook', + 'Help on Gitlab webhooks' => 'Hilfe für Gitlab-Webhooks', 'Integrations' => 'Integration', - 'Integration with third-party services' => 'Integration von Fremdleistungen', + 'Integration with third-party services' => 'Integration von externen Diensten', 'Role for this project' => 'Rolle für dieses Projekt', 'Project manager' => 'Projektmanager', '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.', - 'Gitlab Issue' => 'Gitlab Fehler', - 'Subtask Id' => 'Teilaufgaben Id', + 'Gitlab Issue' => 'Gitlab-Issue', + 'Subtask Id' => 'Teilaufgaben-ID', 'Subtasks' => 'Teilaufgaben', - 'Subtasks Export' => 'Teilaufgaben Export', - 'Subtasks exportation for "%s"' => 'Teilaufgaben Export für "%s"', - 'Task Title' => 'Aufgaben Titel', + 'Subtasks Export' => 'Export von Teilaufgaben', + 'Subtasks exportation for "%s"' => 'Export von Teilaufgaben für "%s"', + 'Task Title' => 'Aufgaben-Titel', 'Untitled' => 'unbetitelt', 'Application default' => 'Anwendungsstandard', 'Language:' => 'Sprache:', @@ -606,20 +599,19 @@ return array( 'All status' => 'Alle Status', 'Moved to column %s' => 'In Spalte %s verschoben', 'Change description' => 'Beschreibung ändern', - 'User dashboard' => 'Benutzer Dashboard', + 'User dashboard' => 'Benutzer-Dashboard', 'Allow only one subtask in progress at the same time for a user' => 'Erlaube nur eine Teilaufgabe pro Benutzer zu bearbeiten', 'Edit column "%s"' => 'Spalte "%s" bearbeiten', 'Select the new status of the subtask: "%s"' => 'Wähle einen neuen Status für Teilaufgabe: "%s"', 'Subtask timesheet' => 'Teilaufgaben Zeiterfassung', 'There is nothing to show.' => 'Es ist nichts zum Anzeigen vorhanden.', 'Time Tracking' => 'Zeiterfassung', - 'You already have one subtask in progress' => 'Bereits eine Teilaufgabe in bearbeitung', + 'You already have one subtask in progress' => 'Bereits eine Teilaufgabe in Bearbeitung', 'Which parts of the project do you want to duplicate?' => 'Welcher Teil des Projekts soll kopiert werden?', - 'Disable login form' => 'Anmeldeformular deaktivieren', - 'Show/hide calendar' => 'Kalender anzeigen/verbergen', - 'Bitbucket commit received' => 'Bitbucket commit erhalten', - 'Bitbucket webhooks' => 'Bitbucket webhooks', - 'Help on Bitbucket webhooks' => 'Hilfe für Bitbucket webhooks', + // 'Disallow login form' => '', + 'Bitbucket commit received' => 'Bitbucket-Commit erhalten', + 'Bitbucket webhooks' => 'Bitbucket-Webhooks', + 'Help on Bitbucket webhooks' => 'Hilfe für Bitbucket-Webhooks', 'Start' => 'Start', 'End' => 'Ende', 'Task age in days' => 'Aufgabenalter in Tagen', @@ -639,7 +631,7 @@ return array( 'Link settings' => 'Verbindungseinstellungen', 'Opposite label' => 'Gegenteil', 'Remove a link' => 'Verbindung entfernen', - 'Task\'s links' => 'Aufgaben Verbindungen', + 'Task\'s links' => 'Aufgaben-Verbindungen', 'The labels must be different' => 'Die Beschriftung muss unterschiedlich sein', 'There is no link.' => 'Es gibt keine Verbindung', 'This label must be unique' => 'Die Beschriftung muss einzigartig sein', @@ -707,18 +699,18 @@ return array( '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.', + 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Dieses Zeitfenster wird verwendet, wenn die Checkbox "ganztägig" für Freizeit und Überstunden angeklickt ist.', 'Files' => 'Dateien', 'Images' => 'Bilder', 'Private project' => 'privates Projekt', 'Amount' => 'Betrag', - // 'AUD - Australian Dollar' => '', + 'AUD - Australian Dollar' => 'AUD - Australische Dollar', 'Budget' => 'Budget', 'Budget line' => 'Budgetlinie', 'Budget line removed successfully.' => 'Budgetlinie erfolgreich entfernt', 'Budget lines' => 'Budgetlinien', - // 'CAD - Canadian Dollar' => '', - // 'CHF - Swiss Francs' => '', + 'CAD - Canadian Dollar' => 'CAD - Kanadische Dollar', + 'CHF - Swiss Francs' => 'CHF - Schweizer Franken', 'Cost' => 'Kosten', 'Cost breakdown' => 'Kostenaufschlüsselung', 'Custom Stylesheet' => 'benutzerdefiniertes Stylesheet', @@ -726,9 +718,9 @@ return array( 'Do you really want to remove this budget line?' => 'Soll diese Budgetlinie wirklich entfernt werden?', 'EUR - Euro' => 'EUR - Euro', 'Expenses' => 'Kosten', - 'GBP - British Pound' => 'GBP - Britische Pfung', + 'GBP - British Pound' => 'GBP - Britische Pfund', 'INR - Indian Rupee' => 'INR - Indische Rupien', - 'JPY - Japanese Yen' => 'JPY - Japanischer Yen', + 'JPY - Japanese Yen' => 'JPY - Japanische Yen', 'New budget line' => 'Neue Budgetlinie', 'NZD - New Zealand Dollar' => 'NZD - Neuseeland-Dollar', 'Remove a budget line' => 'Budgetlinie entfernen', @@ -737,37 +729,37 @@ return array( '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' => 'USD - US Dollar', + 'USD - US Dollar' => '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 (forecast of future work)' => 'Teilaufgaben Schätzungen anzeigen (Prognose)', + 'Show subtask estimates (forecast of future work)' => 'Teilaufgaben-Schätzungen anzeigen (Prognose)', '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', + '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.', + '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.', + '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' => 'Sende Benachrichtigung an Hipchat', - 'API URL' => 'API URL', - 'Room API ID or name' => 'Raum API ID oder Name', - 'Room notification token' => 'Raum Benachrichtigungstoken', - 'Help on Hipchat integration' => 'Hilfe bei Hipchat Integration', - 'Enable Gravatar images' => 'Aktiviere Gravatar Bilder', + 'API URL' => 'API-URL', + 'Room API ID or name' => 'Raum-API-ID oder -Name', + 'Room notification token' => 'Raum-Benachrichtigungstoken', + 'Help on Hipchat integration' => 'Hilfe bei Hipchat-Integration', + 'Enable Gravatar images' => 'Aktiviere Gravatar-Bilder', 'Information' => 'Information', 'Check two factor authentication code' => 'Prüfe Zwei-Faktor-Authentifizierungscode', 'The two factor authentication code is not valid.' => 'Der Zwei-Faktor-Authentifizierungscode ist ungültig.', @@ -810,7 +802,7 @@ return array( 'Recurrent task is scheduled to be generated' => 'Wiederkehrende Aufgabe ist zur Generierung eingeplant', 'Recurring information' => 'Wiederkehrende Information', 'Score' => 'Wertung', - 'The identifier must be unique' => 'Der Schlüssel miss einzigartig sein', + 'The identifier must be unique' => 'Der Schlüssel muss einzigartig sein', 'This linked task id doesn\'t exists' => 'Die verbundene Aufgabe existiert nicht', 'This value must be alphanumeric' => 'Der Wert muss alphanumerisch sein', 'Edit recurrence' => 'Wiederholung bearbeiten', @@ -836,40 +828,40 @@ return array( 'When task is moved to last column' => 'Wenn Aufgabe in letzte Spalte verschoben wird', 'Year(s)' => 'Jahr(e)', // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', - 'Calendar settings' => 'Kalendar Einstellungen', + 'Send notifications to Jabber' => 'Benachrichtigungen an Jabber senden', + 'XMPP server address' => 'XMPP-Server-Adresse', + 'Jabber domain' => 'Jabber-Domain', + 'Jabber nickname' => 'Jabber-Nickname', + 'Multi-user chat room' => 'Multi-User-Chatroom', + 'Help on Jabber integration' => 'Hilfe zur Jabber-Integration', + 'The server address must use this format: "tcp://hostname:5222"' => 'Die Server-Adresse muss in diesem Format sein: "tcp://hostname:5222"', + 'Calendar settings' => 'Kalender-Einstellungen', 'Project calendar view' => 'Projekt-Kalendarsicht', 'Project settings' => 'Projekteinstellungen', 'Show subtasks based on the time tracking' => 'Zeige Teilaufgaben basierend auf Zeiterfassung', 'Show tasks based on the creation date' => 'Zeige Aufgaben basierend auf Erstelldatum', 'Show tasks based on the start date' => 'Zeige Aufgaben basierend auf Beginndatum', - 'Subtasks time tracking' => 'Teilaufgaben Zeiterfassung', - 'User calendar view' => 'Benutzer-Kalendarsicht', + 'Subtasks time tracking' => 'Teilaufgaben-Zeiterfassung', + 'User calendar view' => 'Benutzer-Kalendersicht', 'Automatically update the start date' => 'Beginndatum automatisch aktualisieren', // 'iCal feed' => '', 'Preferences' => 'Einstellungen', 'Security' => 'Sicherheit', - 'Two factor authentication disabled' => 'Zweifaktorauthentifizierung deaktiviert', - 'Two factor authentication enabled' => 'Zweifaktorauthentifizierung aktiviert', - 'Unable to update this user.' => 'User kann nicht bearbeitet werden', + 'Two factor authentication disabled' => 'Zwei-Faktor-Authentifizierung deaktiviert', + 'Two factor authentication enabled' => 'Zwei-Faktor-Authentifizierung aktiviert', + 'Unable to update this user.' => 'Benutzer kann nicht bearbeitet werden', 'There is no user management for private projects.' => 'Es gibt keine Benutzerverwaltung für private Projekte', 'User that will receive the email' => 'Empfänger der E-Mail', - 'Email subject' => 'E-Mail Betreff', + 'Email subject' => 'E-Mail-Betreff', 'Date' => 'Datum', // 'By @%s on Bitbucket' => '', - // 'Bitbucket Issue' => '', + 'Bitbucket Issue' => 'Bitbucket-Issue', // 'Commit made by @%s on Bitbucket' => '', // 'Commit made by @%s on Github' => '', // 'By @%s on Github' => '', // 'Commit made by @%s on Gitlab' => '', - 'Add a comment log when moving the task between columns' => 'Kommentar hinzufügen, wenn Aufgabe in andere Spalte geschoben wird', - 'Move the task to another column when the category is changed' => 'Aufgabe in andere Spalte verschieben, wenn Kategorie geändert', + 'Add a comment log when moving the task between columns' => 'Kommentar hinzufügen, wenn Aufgabe in andere Spalte verschoben wird', + 'Move the task to another column when the category is changed' => 'Aufgabe in andere Spalte verschieben, wenn Kategorie geändert wird', 'Send a task by email to someone' => 'Aufgabe per E-Mail versenden', 'Reopen a task' => 'Aufgabe wieder öffnen', // 'Bitbucket issue opened' => '', @@ -886,16 +878,16 @@ return array( '%s moved the task #%d to the first swimlane' => '%s hat die Aufgabe #%d in die erste Swimlane verschoben', '%s moved the task #%d to the swimlane "%s"' => '%s hat die Aufgabe #%d in die Swimlane "%s" verschoben', // 'Swimlane' => '', - 'Budget overview' => 'Budget Übersicht', + 'Budget overview' => 'Budget-Übersicht', 'Type' => 'Typ', - 'There is not enough data to show something.' => 'Es gibt nicht genug Daten für die Anzeige', + 'There is not enough data to show something.' => 'Es gibt nicht genügend Daten für diese Anzeige', // 'Gravatar' => '', // 'Hipchat' => '', // 'Slack' => '', '%s moved the task %s to the first swimlane' => '%s hat die Aufgabe %s in die erste Swimlane verschoben', '%s moved the task %s to the swimlane "%s"' => '%s hat die Aufgaben %s in die Swimlane "%s" verschoben', - 'This report contains all subtasks information for the given date range.' => 'Der Bericht beinhaltet alle Teilaufgaben im ausgewählten Zeitraum', - 'This report contains all tasks information for the given date range.' => 'Der Bericht beinhaltet alle Aufgaben im ausgewählten Zeitraum', + 'This report contains all subtasks information for the given date range.' => 'Der Bericht beinhaltet alle Teilaufgaben im gewählten Zeitraum', + 'This report contains all tasks information for the given date range.' => 'Der Bericht beinhaltet alle Aufgaben im gewählten Zeitraum', 'Project activities for %s' => 'Projektaktivitäten für %s', 'view the board on Kanboard' => 'Pinnwand in Kanboard anzeigen', 'The task have been moved to the first swimlane' => 'Die Aufgabe wurde in die erste Swimlane verschoben', @@ -909,7 +901,7 @@ return array( 'New color: %s' => 'Neue Farbe: %s', 'New complexity: %d' => 'Neue Komplexität: %d', 'The due date have been removed' => 'Das Ablaufdatum wurde entfernt', - 'There is no description anymore' => 'Es gibt keine BEschreibung mehr', + 'There is no description anymore' => 'Es gibt keine Beschreibung mehr', 'Recurrence settings have been modified' => 'Die Einstellungen für Wiederholung wurden geändert', 'Time spent changed: %sh' => 'Verbrauchte Zeit geändert: %sh', 'Time estimated changed: %sh' => 'Geschätzte Zeit geändert: %sh', @@ -917,7 +909,7 @@ return array( 'The description have been modified' => 'Die Beschreibung wurde geändert', 'Do you really want to close the task "%s" as well as all subtasks?' => 'Soll die Aufgabe "%s" wirklich geschlossen werden? (einschließlich Teilaufgaben)', // 'Swimlane: %s' => '', - 'I want to receive notifications for:' => 'Ich möchte Benachrichtigungn erhalten für:', + 'I want to receive notifications for:' => 'Ich möchte Benachrichtigungen erhalten für:', 'All tasks' => 'Alle Aufgaben', 'Only for tasks assigned to me' => 'nur mir zugeordnete Aufgane', 'Only for tasks created by me' => 'nur von mir erstellte Aufgaben', @@ -936,39 +928,74 @@ return array( 'Start timer' => 'Starte Timer', 'Add project member' => 'Projektmitglied hinzufügen', 'Enable notifications' => 'Benachrichtigung aktivieren', - // 'My activity stream' => '', - // 'My calendar' => '', - // 'Search tasks' => '', - // 'Back to the calendar' => '', - // 'Filters' => '', - // 'Reset filters' => '', - // 'My tasks due tomorrow' => '', - // 'Tasks due today' => '', - // 'Tasks due tomorrow' => '', - // 'Tasks due yesterday' => '', - // 'Closed tasks' => '', - // 'Open tasks' => '', - // 'Not assigned' => '', - // 'View advanced search syntax' => '', - // 'Overview' => '', + 'My activity stream' => 'Aktivitätsstream', + 'My calendar' => 'Mein Kalender', + 'Search tasks' => 'Suche nach Aufgaben', + 'Back to the calendar' => 'Zurück zum Kalender', + 'Filters' => 'Filter', + 'Reset filters' => 'Filter zurücksetzen', + 'My tasks due tomorrow' => 'Meine morgen fälligen Aufgaben', + 'Tasks due today' => 'Heute fällige Aufgaben', + 'Tasks due tomorrow' => 'Morgen fällige Aufgaben', + 'Tasks due yesterday' => 'Gestern fällige Aufgaben', + 'Closed tasks' => 'Abgeschlossene Aufgaben', + 'Open tasks' => 'Offene Aufgaben', + 'Not assigned' => 'Nicht zugewiesen', + 'View advanced search syntax' => 'Zur erweiterten Suchsyntax', + 'Overview' => 'Überblick', // '%b %e %Y' => '', - // 'Board/Calendar/List view' => '', - // 'Switch to the board view' => '', - // 'Switch to the calendar view' => '', - // 'Switch to the list view' => '', - // 'Go to the search/filter box' => '', - // 'There is no activity yet.' => '', - // 'No tasks found.' => '', - // 'Keyboard shortcut: "%s"' => '', - // 'List' => '', - // 'Filter' => '', - // 'Advanced search' => '', - // 'Example of query: ' => '', - // 'Search by project: ' => '', - // 'Search by column: ' => '', - // 'Search by assignee: ' => '', - // 'Search by color: ' => '', - // 'Search by category: ' => '', - // 'Search by description: ' => '', - // 'Search by due date: ' => '', + 'Board/Calendar/List view' => 'Board-/Kalender-/Listen-Ansicht', + 'Switch to the board view' => 'Zur Board-Ansicht', + 'Switch to the calendar view' => 'Zur Kalender-Ansicht', + 'Switch to the list view' => 'Zur Listen-Ansicht', + 'Go to the search/filter box' => 'Zum Such- und Filterfeld', + 'There is no activity yet.' => 'Es gibt bislang keine Aktivitäten.', + 'No tasks found.' => 'Keine Aufgaben gefunden.', + 'Keyboard shortcut: "%s"' => 'Tastaturkürzel: "%s"', + 'List' => 'Liste', + 'Filter' => 'Filter', + 'Advanced search' => 'Fortgeschrittene Suche', + 'Example of query: ' => 'Beispiel einer Abfrage: ', + 'Search by project: ' => 'Suche nach Projekt: ', + 'Search by column: ' => 'Suche nach Spalte: ', + 'Search by assignee: ' => 'Suche nach zugeordnetem Benutzer: ', + 'Search by color: ' => 'Suche nach Farbe: ', + 'Search by category: ' => 'Suche nach Kategorie: ', + 'Search by description: ' => 'Suche nach Beschreibung: ', + 'Search by due date: ' => 'Suche nach Fälligkeitsdatum: ', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 36259a8a..ecaf8a23 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'El nombre del proyecto es obligatorio', 'This project must be unique' => 'El nombre del proyecto debe ser único', 'The title is required' => 'El titulo es obligatorio', - 'There is no active project, the first step is to create a new project.' => 'No hay proyectos activados, la primera etapa consiste en crear un nuevo proyecto.', 'Settings saved successfully.' => 'Parámetros guardados correctamente.', 'Unable to save your settings.' => 'No se pueden guardar sus parámetros.', 'Database optimization done.' => 'Optimización de la base de datos terminada.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d comentarios', '%d comment' => '%d comentario', 'Email address invalid' => 'Dirección de correo inválida', - 'Your Google Account is not linked anymore to your profile.' => 'Tu Cuenta en Google ya no se encuentra vinculada con tu perfil', - 'Unable to unlink your Google Account.' => 'No puedo desvincular tu Cuenta en Google.', - 'Google authentication failed' => 'Ha fallado tu autenticación en Google', - 'Unable to link your Google Account.' => 'No puedo vincular con tu Cuenta en Google.', - 'Your Google Account is linked to your profile successfully.' => 'Se ha vinculado correctamente tu Cuenta en Google con tu perfil.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Correo', 'Link my Google Account' => 'Vincular con mi Cuenta en Google', 'Unlink my Google Account' => 'Desvincular de mi Cuenta en Google', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Tamaño máximo', 'Unable to upload the file.' => 'No pude cargar el fichero.', 'Display another project' => 'Mostrar otro proyecto', - 'Your GitHub account was successfully linked to your profile.' => 'Tu cuenta de GitHub ha sido correctamente vinculada con tu perfil', - 'Unable to link your GitHub Account.' => 'Imposible vincular tu cuenta de GitHub', - 'GitHub authentication failed' => 'Falló la autenticación de GitHub', - 'Your GitHub account is no longer linked to your profile.' => 'Tu cuenta de GitHub ya no está vinculada a tu perfil', - 'Unable to unlink your GitHub Account.' => 'Imposible desvincular tu cuenta de GitHub', - 'Login with my GitHub Account' => 'Ingresar con mi cuenta de GitHub', - 'Link my GitHub Account' => 'Vincular mi cuenta de GitHub', - 'Unlink my GitHub Account' => 'Desvincular mi cuenta de GitHub', + 'Login with my Github Account' => 'Ingresar con mi cuenta de Github', + 'Link my Github Account' => 'Vincular mi cuenta de Github', + 'Unlink my Github Account' => 'Desvincular mi cuenta de Github', 'Created by %s' => 'Creado por %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Última modificación %B %e, %Y a las %k:%M %p', 'Tasks Export' => 'Exportar tareas', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Seguimiento Temporal', 'You already have one subtask in progress' => 'Ya dispones de una subtarea en progreso', 'Which parts of the project do you want to duplicate?' => '¿Qué partes del proyecto deseas duplicar?', - 'Disable login form' => 'Desactivar formulario de ingreso', - 'Show/hide calendar' => 'Mostrar/ocultar calendario', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Recibida envío desde Bitbucket', 'Bitbucket webhooks' => 'Disparadores Web (webhooks) de Bitbucket', 'Help on Bitbucket webhooks' => 'Ayuda sobre disparadores web (webhooks) de Bitbucket', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index beb61d96..ddbb26c3 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Projektin nimi on pakollinen', 'This project must be unique' => 'Projektin nimi täytyy olla uniikki', 'The title is required' => 'Otsikko vaaditaan', - 'There is no active project, the first step is to create a new project.' => 'Aktiivista projektia ei ole, ensimmäinen vaihe on luoda uusi projekti.', 'Settings saved successfully.' => 'Asetukset tallennettu onnistuneesti.', 'Unable to save your settings.' => 'Asetusten tallentaminen epäonnistui.', 'Database optimization done.' => 'Tietokannan optimointi suoritettu.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d kommenttia', '%d comment' => '%d kommentti', 'Email address invalid' => 'Email ei kelpaa', - 'Your Google Account is not linked anymore to your profile.' => 'Google tunnustasi ei ole enää linkattu profiiliisi', - 'Unable to unlink your Google Account.' => 'Google tunnuksen linkkaamisen poistaminen epäonnistui.', - 'Google authentication failed' => 'Google autentikointi epäonnistui', - 'Unable to link your Google Account.' => 'Google tunnuksen linkkaaminen epäonnistui.', - 'Your Google Account is linked to your profile successfully.' => 'Google tunnuksesi linkitettiin profiiliisi onnistuneesti.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Sähköposti', 'Link my Google Account' => 'Linkitä Google-tili', 'Unlink my Google Account' => 'Poista Google-tilin linkitys', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Maksimikoko: ', 'Unable to upload the file.' => 'Tiedoston lataus epäonnistui.', 'Display another project' => 'Näytä toinen projekti', - 'Your GitHub account was successfully linked to your profile.' => 'Github-tilisi on onnistuneesti liitetty profiiliisi', - 'Unable to link your GitHub Account.' => 'Github-tilin liittäminen epäonnistui', - 'GitHub authentication failed' => 'Github-todennus epäonnistui', - 'Your GitHub account is no longer linked to your profile.' => 'Github-tiliäsi ei ole enää liitetty profiiliisi.', - 'Unable to unlink your GitHub Account.' => 'Github-tilisi liitoksen poisto epäonnistui', - 'Login with my GitHub Account' => 'Kirjaudu sisään Github-tililläni', - 'Link my GitHub Account' => 'Liitä Github-tilini', - 'Unlink my GitHub Account' => 'Poista liitos Github-tiliini', + 'Login with my Github Account' => 'Kirjaudu sisään Github-tililläni', + 'Link my Github Account' => 'Liitä Github-tilini', + 'Unlink my Github Account' => 'Poista liitos Github-tiliini', 'Created by %s' => 'Luonut: %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Viimeksi muokattu %B %e, %Y kello %H:%M', 'Tasks Export' => 'Tehtävien vienti', @@ -615,8 +608,7 @@ return array( // 'Time Tracking' => '', // 'You already have one subtask in progress' => '', // 'Which parts of the project do you want to duplicate?' => '', - // 'Disable login form' => '', - // 'Show/hide calendar' => '', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', // 'Bitbucket webhooks' => '', // 'Help on Bitbucket webhooks' => '', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 34839a12..1c4c76ee 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Le nom du projet est obligatoire', 'This project must be unique' => 'Le nom du projet doit être unique', 'The title is required' => 'Le titre est obligatoire', - 'There is no active project, the first step is to create a new project.' => 'Il n\'y a aucun projet actif, la première étape est de créer un nouveau projet.', 'Settings saved successfully.' => 'Paramètres sauvegardés avec succès.', 'Unable to save your settings.' => 'Impossible de sauvegarder vos réglages.', 'Database optimization done.' => 'Optmisation de la base de données terminée.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d commentaires', '%d comment' => '%d commentaire', 'Email address invalid' => 'Adresse email invalide', - 'Your Google Account is not linked anymore to your profile.' => 'Votre compte Google n\'est plus relié à votre profile.', - 'Unable to unlink your Google Account.' => 'Impossible de supprimer votre compte Google.', - 'Google authentication failed' => 'Authentification Google échouée', - 'Unable to link your Google Account.' => 'Impossible de lier votre compte Google.', - 'Your Google Account is linked to your profile successfully.' => 'Votre compte Google est désormais lié à votre profile.', + 'Your external account is not linked anymore to your profile.' => 'Votre compte externe n\'est plus relié à votre profile.', + 'Unable to unlink your external account.' => 'Impossible de supprimer votre compte externe.', + 'External authentication failed' => 'Authentification externe échouée', + 'Your external account is linked to your profile successfully.' => 'Votre compte externe est désormais lié à votre profile.', 'Email' => 'Email', 'Link my Google Account' => 'Lier mon compte Google', 'Unlink my Google Account' => 'Ne plus utiliser mon compte Google', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Taille maximum : ', 'Unable to upload the file.' => 'Impossible de transférer le fichier.', 'Display another project' => 'Afficher un autre projet', - 'Your GitHub account was successfully linked to your profile.' => 'Votre compte Github est désormais lié avec votre profile.', - 'Unable to link your GitHub Account.' => 'Impossible de lier votre compte Github.', - 'GitHub authentication failed' => 'L\'authentification avec Github à échouée', - 'Your GitHub account is no longer linked to your profile.' => 'Votre compte Github n\'est plus relié avec votre profile.', - 'Unable to unlink your GitHub Account.' => 'Impossible de déconnecter votre compte Github.', - 'Login with my GitHub Account' => 'Se connecter avec mon compte Github', - 'Link my GitHub Account' => 'Lier mon compte Github', - 'Unlink my GitHub Account' => 'Ne plus utiliser mon compte Github', + 'Login with my Github Account' => 'Se connecter avec mon compte Github', + 'Link my Github Account' => 'Lier mon compte Github', + 'Unlink my Github Account' => 'Ne plus utiliser mon compte Github', 'Created by %s' => 'Créé par %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Modifié le %d/%m/%Y à %H:%M', 'Tasks Export' => 'Exportation des tâches', @@ -617,8 +610,7 @@ return array( 'Time Tracking' => 'Feuille de temps', 'You already have one subtask in progress' => 'Vous avez déjà une sous-tâche en progrès', 'Which parts of the project do you want to duplicate?' => 'Quelles parties du projet voulez-vous dupliquer ?', - 'Disable login form' => 'Désactiver le formulaire d\'authentification', - 'Show/hide calendar' => 'Afficher/cacher le calendrier', + 'Disallow login form' => 'Interdir le formulaire d\'authentification', 'Bitbucket commit received' => 'Commit reçu via Bitbucket', 'Bitbucket webhooks' => 'Webhook Bitbucket', 'Help on Bitbucket webhooks' => 'Aide sur les webhooks Bitbucket', @@ -899,7 +891,7 @@ return array( 'This report contains all subtasks information for the given date range.' => 'Ce rapport contient les informations de toutes les sous-tâches pour la période selectionnée.', 'This report contains all tasks information for the given date range.' => 'Ce rapport contient les informations de toutes les tâches pour la période selectionnée.', 'Project activities for %s' => 'Activité des projets pour « %s »', - 'view the board on Kanboard' => 'voir la tableau sur Kanboard', + 'view the board on Kanboard' => 'voir le tableau sur Kanboard', 'The task have been moved to the first swimlane' => 'La tâche a été déplacée dans la première swimlane', 'The task have been moved to another swimlane:' => 'La tâche a été déplacée dans une autre swimlane :', 'Overdue tasks for the project "%s"' => 'Tâches en retard pour le projet « %s »', @@ -966,11 +958,46 @@ return array( 'Filter' => 'Filtre', 'Advanced search' => 'Recherche avancée', 'Example of query: ' => 'Exemple de requête : ', - 'Search by project: ' => 'Rechercher par project : ', + 'Search by project: ' => 'Rechercher par projet : ', 'Search by column: ' => 'Rechercher par colonne : ', 'Search by assignee: ' => 'Rechercher par assigné : ', 'Search by color: ' => 'Rechercher par couleur : ', 'Search by category: ' => 'Rechercher par catégorie : ', 'Search by description: ' => 'Rechercher par description : ', 'Search by due date: ' => 'Rechercher par date d\'échéance : ', + 'Lead and Cycle time for "%s"' => 'Lead et cycle time pour « %s »', + 'Average time spent into each column for "%s"' => 'Temps passé moyen dans chaque colonne pour « %s »', + 'Average time spent into each column' => 'Temps moyen passé dans chaque colonne', + 'Average time spent' => 'Temps moyen passé', + 'This chart show the average time spent into each column for the last %d tasks.' => 'Ce graphique montre le temps passé moyen dans chaque colonne pour les %d dernières tâches.', + 'Average Lead and Cycle time' => 'Durée moyenne du lead et cycle time', + 'Average lead time: ' => 'Lead time moyen : ', + 'Average cycle time: ' => 'Cycle time moyen : ', + 'Cycle Time' => 'Cycle time', + 'Lead Time' => 'Lead time', + 'This chart show the average lead and cycle time for the last %d tasks over the time.' => 'Ce graphique montre la durée moyenne du lead et cycle time pour les %d dernières tâches.', + 'Average time into each column' => 'Temps moyen dans chaque colonne', + 'Lead and cycle time' => 'Lead et cycle time', + 'Google Authentication' => 'Authentification Google', + 'Help on Google authentication' => 'Aide sur l\'authentification Google', + 'Github Authentication' => 'Authentification Github', + 'Help on Github authentication' => 'Aide sur l\'authentification Github', + 'Channel/Group/User (Optional)' => 'Cannal/Groupe/Utilisateur (Optionnel)', + 'Lead time: ' => 'Lead time : ', + 'Cycle time: ' => 'Temps de cycle : ', + 'Time spent into each column' => 'Temps passé dans chaque colonne', + 'The lead time is the duration between the task creation and the completion.' => 'Le lead time est la durée entre la création de la tâche et sa complétion.', + 'The cycle time is the duration between the start date and the completion.' => 'Le cycle time est la durée entre la date de début et la complétion.', + 'If the task is not closed the current time is used instead of the completion date.' => 'Si la tâche n\'est pas fermée, l\'heure courante est utilisée à la place de la date de complétion.', + 'Set automatically the start date' => 'Définir automatiquement la date de début', + 'Edit Authentication' => 'Modifier l\'authentification', + 'Google Id' => 'Identifiant Google', + 'Github Id' => 'Identifiant Github', + 'Remote user' => 'Utilisateur distant', + 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => 'Les utilisateurs distants ne stockent pas leur mot de passe dans la base de données de Kanboard, exemples : comptes LDAP, Github ou Google.', + 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => 'Si vous cochez la case « Interdir le formulaire d\'authentification », les identifiants entrés dans le formulaire d\'authentification seront ignorés.', + 'By @%s on Gitlab' => 'Par @%s sur Gitlab', + 'Gitlab issue comment created' => 'Commentaire créé sur un ticket Gitlab', + 'New remote user' => 'Créer un utilisateur distant', + 'New local user' => 'Créer un utilisateur local', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index 73215f89..f1bd1453 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'A projekt nevét meg kell adni', 'This project must be unique' => 'A projekt nevének egyedinek kell lennie', 'The title is required' => 'A címet 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.', 'Settings saved successfully.' => 'A beállítások sikeresen mentve.', 'Unable to save your settings.' => 'A beállítások mentése sikertelen.', 'Database optimization done.' => 'Adatbázis optimalizálás kész.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d megjegyzés', '%d comment' => '%d megjegyzés', 'Email address invalid' => 'Érvénytelen e-mail cím', - '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.', - 'Google authentication failed' => 'Google azonosítás sikertelen', - 'Unable to link your Google Account.' => 'A Google profilhoz kapcsolás sikertelen.', - 'Your Google Account is linked to your profile successfully.' => 'Google fiókkal sikeresen összekapcsolva.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-mail', 'Link my Google Account' => 'Kapcsold össze a Google fiókkal', 'Unlink my Google Account' => 'Válaszd le a Google fiókomat', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Maximális méret: ', 'Unable to upload the file.' => 'Fájl feltöltése nem lehetséges.', 'Display another project' => 'Másik projekt megjelenítése', - 'Your GitHub account was successfully linked to your profile.' => 'GitHub fiók sikeresen csatolva a profilhoz.', - 'Unable to link your GitHub Account.' => 'Nem lehet csatolni a GitHub fiókot.', - 'GitHub authentication failed' => 'GitHub azonosítás sikertelen', - 'Your GitHub account is no longer linked to your profile.' => 'GitHub fiók már nincs profilhoz kapcsolva.', - 'Unable to unlink your GitHub Account.' => 'GitHub fiók leválasztása nem lehetséges.', - 'Login with my GitHub Account' => 'Jelentkezzen be GitHub fiókkal', - 'Link my GitHub Account' => 'GitHub fiók csatolása', - 'Unlink my GitHub Account' => 'GitHub fiók leválasztása', + 'Login with my Github Account' => 'Jelentkezzen be Github fiókkal', + 'Link my Github Account' => 'Github fiók csatolása', + 'Unlink my Github Account' => 'Github fiók leválasztása', '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', 'Tasks Export' => 'Feladatok exportálása', @@ -403,7 +396,7 @@ return array( 'Enabled' => 'Engedélyezve', 'Disabled' => 'Letiltva', 'Google account linked' => 'Google fiók összekapcsolva', - 'Github account linked' => 'GitHub fiók összekapcsolva', + 'Github account linked' => 'Github fiók összekapcsolva', 'Username:' => 'Felhasználónév:', 'Name:' => 'Név:', 'Email:' => 'E-mail:', @@ -458,12 +451,12 @@ return array( '%s changed the assignee of the task %s to %s' => '%s a felelőst %s módosította: %s', 'New password for the user "%s"' => 'Felhasználó új jelszava: %s', 'Choose an event' => 'Válasszon eseményt', - 'Github commit received' => 'GitHub commit érkezett', - 'Github issue opened' => 'GitHub issue nyitás', - 'Github issue closed' => 'GitHub issue zárás', - 'Github issue reopened' => 'GitHub issue újranyitva', - 'Github issue assignee change' => 'GitHub issue felelős változás', - 'Github issue label change' => 'GitHub issue címke változás', + 'Github commit received' => 'Github commit érkezett', + 'Github issue opened' => 'Github issue nyitás', + 'Github issue closed' => 'Github issue zárás', + 'Github issue reopened' => 'Github issue újranyitva', + 'Github issue assignee change' => 'Github issue felelős változás', + 'Github issue label change' => 'Github issue címke változás', 'Create a task from an external provider' => 'Feladat létrehozása külsős számára', 'Change the assignee based on an external username' => 'Felelős módosítása külső felhasználónév alapján', 'Change the category based on an external label' => 'Kategória módosítása külső címke alapján', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Idő követés', '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é másolni?', - 'Disable login form' => 'Bejelentkező képernyő tiltása', - 'Show/hide calendar' => 'Naptár megjelenítés/elrejtés', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Bitbucket commit érkezett', 'Bitbucket webhooks' => 'Bitbucket webhooks', 'Help on Bitbucket webhooks' => 'Bitbucket webhooks súgó', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 0fe5547b..6dd60c18 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Si richiede il nome del progetto', 'This project must be unique' => 'Il nome del progetto deve essere unico', 'The title is required' => 'Si richiede un titolo', - 'There is no active project, the first step is to create a new project.' => 'Non ci sono progetti attivi, il primo passo consiste in creare un nuovo progetto.', 'Settings saved successfully.' => 'Impostazioni salvate correttamente.', 'Unable to save your settings.' => 'Non si possono salvare le impostazioni.', 'Database optimization done.' => 'Ottimizzazione della base dati conclusa.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d commenti', '%d comment' => '%d commento', 'Email address invalid' => 'Indirizzo e-mail sbagliato', - 'Your Google Account is not linked anymore to your profile.' => 'Il suo account Google non è più collegato al suo profilo', - 'Unable to unlink your Google Account.' => 'Non si può svincolare l\'account di Google.', - 'Google authentication failed' => 'Autenticazione con Google non riuscita', - 'Unable to link your Google Account.' => 'Non si può collegare il tuo account di Google.', - 'Your Google Account is linked to your profile successfully.' => 'Il tuo account di Google è stato collegato correttamente al tuo profilo.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-mail', 'Link my Google Account' => 'Collegare il mio Account di Google', 'Unlink my Google Account' => 'Scollegare il mio account di Google', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Dimensioni massime', 'Unable to upload the file.' => 'Non si può caricare il file.', 'Display another project' => 'Mostrare un altro progetto', - 'Your GitHub account was successfully linked to your profile.' => 'Il suo account di Github è stato collegato correttamente col tuo profilo.', - 'Unable to link your GitHub Account.' => 'Non si può collegarre il tuo account di Github.', - 'GitHub authentication failed' => 'Autenticazione con GitHub non riuscita', - 'Your GitHub account is no longer linked to your profile.' => 'Il tuo account di Github non è più collegato al tuo profilo.', - 'Unable to unlink your GitHub Account.' => 'Non si può collegare il tuo account di Github.', - 'Login with my GitHub Account' => 'Entrare col tuo account di Github', - 'Link my GitHub Account' => 'Collegare il mio account Github', - 'Unlink my GitHub Account' => 'Scollegare il mio account di Github', + 'Login with my Github Account' => 'Entrare col tuo account di Github', + 'Link my Github Account' => 'Collegare il mio account Github', + 'Unlink my Github Account' => 'Scollegare il mio account di Github', 'Created by %s' => 'Creato da %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Ultima modifica il %d/%m/%Y alle %H:%M', 'Tasks Export' => 'Esportazione di compiti', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Gestione del tempo', 'You already have one subtask in progress' => 'Hai già un sotto-compito in progresso', 'Which parts of the project do you want to duplicate?' => 'Quali parti del progetto vuoi duplicare?', - 'Disable login form' => 'Disabilita form di login', - 'Show/hide calendar' => 'Mostra/nascondi calendario', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Commit ricevuto da Bitbucket', 'Bitbucket webhooks' => 'Webhooks di Bitbucket', 'Help on Bitbucket webhooks' => 'Guida ai Webhooks di Bitbucket', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 6c9a205e..e52f82b6 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'プロジェクト名が必要です', 'This project must be unique' => 'プロジェクト名がすでに使われています', 'The title is required' => 'タイトルが必要です', - 'There is no active project, the first step is to create a new project.' => '有効なプロジェクトがありません。まず新しいプロジェクトを作ります。', 'Settings saved successfully.' => '設定を保存しました。', 'Unable to save your settings.' => '設定の保存に失敗しました。', 'Database optimization done.' => 'データベースの最適化が終わりました。', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d 個のコメント', '%d comment' => '%d 個のコメント', 'Email address invalid' => 'メールアドレスが正しくありません', - 'Your Google Account is not linked anymore to your profile.' => 'Google アカウントとのリンクが解除されました', - 'Unable to unlink your Google Account.' => 'Google アカウントとのリンク解除に失敗しました', - 'Google authentication failed' => 'Google の認証に失敗しました', - 'Unable to link your Google Account.' => 'Google アカウントとのリンクに失敗しました。', - 'Your Google Account is linked to your profile successfully.' => 'Google アカウントとリンクしました', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Email', 'Link my Google Account' => 'Google アカウントをリンクする', 'Unlink my Google Account' => 'Google アカウントのリンクを解除する', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => '最大: ', 'Unable to upload the file.' => 'ファイルのアップロードに失敗しました。', 'Display another project' => '別のプロジェクトを表示', - 'Your GitHub account was successfully linked to your profile.' => 'GitHub アカウントとリンクしました。', - 'Unable to link your GitHub Account.' => 'GitHub アカウントとリンクできませんでした。', - 'GitHub authentication failed' => 'GitHub アカウントの認証に失敗しました。', - 'Your GitHub account is no longer linked to your profile.' => 'GitHub アカウントへのリンクが解除されました。', - 'Unable to unlink your GitHub Account.' => 'GitHub アカウントのリンク解除に失敗しました。', - 'Login with my GitHub Account' => 'Github アカウントでログインする', - 'Link my GitHub Account' => 'Github アカウントをリンクする', - 'Unlink my GitHub Account' => 'Github アカウントとのリンクを解除する', + 'Login with my Github Account' => 'Github アカウントでログインする', + 'Link my Github Account' => 'Github アカウントをリンクする', + 'Unlink my Github Account' => 'Github アカウントとのリンクを解除する', 'Created by %s' => '%s が作成', 'Last modified on %B %e, %Y at %k:%M %p' => ' %Y/%m/%d %H:%M に変更', 'Tasks Export' => 'タスクの出力', @@ -403,7 +396,7 @@ return array( 'Enabled' => '有効', 'Disabled' => '無効', 'Google account linked' => 'Google アカウントがリンク', - 'Github account linked' => 'GitHub のアカウントがリンク', + 'Github account linked' => 'Github のアカウントがリンク', 'Username:' => 'ユーザ名:', 'Name:' => '名前:', 'Email:' => 'Email:', @@ -417,7 +410,7 @@ return array( 'Password modification' => 'パスワードの変更', 'External authentications' => '外部認証', 'Google Account' => 'Google アカウント', - 'Github Account' => 'GitHub アカウント', + 'Github Account' => 'Github アカウント', 'Never connected.' => '未接続。', 'No account linked.' => 'アカウントがリンクしていません。', 'Account linked.' => 'アカウントがリンクしました。', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'タイムトラッキング', 'You already have one subtask in progress' => 'すでに進行中のサブタスクがあります。', 'Which parts of the project do you want to duplicate?' => 'プロジェクトの何を複製しますか?', - 'Disable login form' => 'ログインフォームの無効化', - 'Show/hide calendar' => 'カレンダーの表示・非表示', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Bitbucket コミットを受信しました', 'Bitbucket webhooks' => 'Bitbucket Webhooks', 'Help on Bitbucket webhooks' => 'Bitbucket Webhooks のヘルプ', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 7a31b975..ed8be05b 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -126,7 +126,6 @@ return array( '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', - '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.', @@ -264,11 +263,10 @@ return array( '%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.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Email', 'Link my Google Account' => 'Link mijn Google Account', 'Unlink my Google Account' => 'Link met Google Account verwijderen', @@ -338,14 +336,9 @@ return array( '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', + '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', @@ -615,8 +608,7 @@ return array( '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?', - 'Disable login form' => 'Schakel login scherm uit', - 'Show/hide calendar' => 'Toon/verberg agenda', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Bitbucket commit ontvangen', 'Bitbucket webhooks' => 'Bitbucket webhooks', 'Help on Bitbucket webhooks' => 'Help bij Bitbucket webhooks', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 637eefb4..9f8641a0 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Nazwa projektu jest wymagana', 'This project must be unique' => 'Projekt musi być unikalny', 'The title is required' => 'Tutył jest wymagany', - 'There is no active project, the first step is to create a new project.' => 'Brak aktywnych projektów. Pierwszym krokiem jest utworzenie nowego projektu.', 'Settings saved successfully.' => 'Ustawienia zapisane.', 'Unable to save your settings.' => 'Nie udało się zapisać ustawień.', 'Database optimization done.' => 'Optymalizacja bazy danych zakończona.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d Komentarzy', '%d comment' => '%d Komentarz', 'Email address invalid' => 'Błędny adres email', - 'Your Google Account is not linked anymore to your profile.' => 'Twoje konto Google nie jest już połączone', - 'Unable to unlink your Google Account.' => 'Nie można odłączyć konta Google', - 'Google authentication failed' => 'Autentykacja Google nieudana', - 'Unable to link your Google Account.' => 'Nie można podłączyć konta Google', - 'Your Google Account is linked to your profile successfully.' => 'Podłączanie konta Google ukończone pomyślnie', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Email', 'Link my Google Account' => 'Połącz z kontem Google', 'Unlink my Google Account' => 'Rozłącz z kontem Google', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Maksymalny rozmiar: ', 'Unable to upload the file.' => 'Nie można wczytać pliku.', 'Display another project' => 'Wyświetl inny projekt', - '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', + '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' => 'Utworzone przez %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Ostatnio zmienione %e %B %Y o %k:%M', 'Tasks Export' => 'Eksport zadań', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Śledzenie czasu', 'You already have one subtask in progress' => 'Masz już zadanie o statusie "w trakcie"', 'Which parts of the project do you want to duplicate?' => 'Które elementy projektu chcesz zduplikować?', - 'Disable login form' => 'Wyłącz formularz logowania', - 'Show/hide calendar' => 'Pokaż/Ukryj kalendarz', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', // 'Bitbucket webhooks' => '', // 'Help on Bitbucket webhooks' => '', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index 1031f1e2..68de0368 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -20,15 +20,15 @@ return array( 'Red' => 'Vermelho', 'Orange' => 'Laranja', 'Grey' => 'Cinza', - // 'Brown' => '', - // 'Deep Orange' => '', - // 'Dark Grey' => '', - // 'Pink' => '', - // 'Teal' => '', - // 'Cyan' => '', - // 'Lime' => '', - // 'Light Green' => '', - // 'Amber' => '', + 'Brown' => 'Marrom', + 'Deep Orange' => 'Laranja escuro', + 'Dark Grey' => 'Cinza escuro', + 'Pink' => 'Roza', + 'Teal' => 'Turquesa', + 'Cyan' => 'Azul intenso', + 'Lime' => 'Verde limão', + 'Light Green' => 'Verde claro', + 'Amber' => 'Âmbar', 'Save' => 'Salvar', 'Login' => 'Login', 'Official website:' => 'Site oficial:', @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'O nome do projeto é obrigatório', 'This project must be unique' => 'Este projeto deve ser único', 'The title is required' => 'O título é obrigatório', - 'There is no active project, the first step is to create a new project.' => 'Não há projeto ativo. O primeiro passo é criar um novo projeto.', 'Settings saved successfully.' => 'Configurações salvas com sucesso.', 'Unable to save your settings.' => 'Não é possível salvar suas configurações.', 'Database optimization done.' => 'Otimização do banco de dados finalizada.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d comentários', '%d comment' => '%d comentário', 'Email address invalid' => 'Endereço de e-mail inválido', - 'Your Google Account is not linked anymore to your profile.' => 'Sua conta do Google não está mais associada ao seu perfil.', - 'Unable to unlink your Google Account.' => 'Não foi possível desassociar a sua Conta do Google.', - 'Google authentication failed' => 'Autenticação do Google falhou.', - 'Unable to link your Google Account.' => 'Não foi possível associar a sua Conta do Google.', - 'Your Google Account is linked to your profile successfully.' => 'Sua Conta do Google foi associada ao seu perfil com sucesso.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-mail', 'Link my Google Account' => 'Vincular minha Conta do Google', 'Unlink my Google Account' => 'Desvincular minha Conta do Google', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Tamanho máximo:', 'Unable to upload the file.' => 'Não foi possível carregar o arquivo.', 'Display another project' => 'Exibir outro projeto', - 'Your GitHub account was successfully linked to your profile.' => 'A sua Conta do GitHub foi associada com sucesso ao seu perfil.', - 'Unable to link your GitHub Account.' => 'Não foi possível associar sua Conta do GitHub.', - 'GitHub authentication failed' => 'Autenticação do GitHub falhou', - 'Your GitHub account is no longer linked to your profile.' => 'A sua Conta do GitHub não está mais associada ao seu perfil.', - 'Unable to unlink your GitHub Account.' => 'Não foi possível desassociar a sua Conta do GitHub.', - 'Login with my GitHub Account' => 'Entrar com minha Conta do GitHub', - 'Link my GitHub Account' => 'Associar à minha Conta do GitHub', - 'Unlink my GitHub Account' => 'Desassociar a minha Conta do GitHub', + 'Login with my Github Account' => 'Entrar com minha Conta do Github', + 'Link my Github Account' => 'Associar à minha Conta do Github', + 'Unlink my Github Account' => 'Desassociar a minha Conta do Github', 'Created by %s' => 'Criado por %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Última modificação em %B %e, %Y às %k: %M %p', 'Tasks Export' => 'Exportar Tarefas', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Gestão de tempo', 'You already have one subtask in progress' => 'Você já tem um subtarefa em andamento', 'Which parts of the project do you want to duplicate?' => 'Quais as partes do projeto você deseja duplicar?', - 'Disable login form' => 'Desativar o formulário de login', - 'Show/hide calendar' => 'Mostrar / ocultar calendário', + // 'Disallow login form' => '', 'Bitbucket commit received' => '"Commit" recebido via Bitbucket', 'Bitbucket webhooks' => 'Webhook Bitbucket', 'Help on Bitbucket webhooks' => 'Ajuda sobre os webhooks Bitbucket', @@ -858,117 +850,152 @@ return array( 'Two factor authentication disabled' => 'Autenticação à fator duplo desativado', 'Two factor authentication enabled' => 'Autenticação à fator duplo activado', 'Unable to update this user.' => 'Impossível de atualizar esse usuário.', - // 'There is no user management for private projects.' => '', - // 'User that will receive the email' => '', - // 'Email subject' => '', - // 'Date' => '', - // 'By @%s on Bitbucket' => '', - // 'Bitbucket Issue' => '', - // 'Commit made by @%s on Bitbucket' => '', - // 'Commit made by @%s on Github' => '', - // 'By @%s on Github' => '', - // 'Commit made by @%s on Gitlab' => '', - // 'Add a comment log when moving the task between columns' => '', - // 'Move the task to another column when the category is changed' => '', - // 'Send a task by email to someone' => '', - // 'Reopen a task' => '', - // 'Bitbucket issue opened' => '', - // 'Bitbucket issue closed' => '', - // 'Bitbucket issue reopened' => '', - // 'Bitbucket issue assignee change' => '', - // 'Bitbucket issue comment created' => '', - // 'Column change' => '', - // 'Position change' => '', - // 'Swimlane change' => '', - // 'Assignee change' => '', - // '[%s] Overdue tasks' => '', - // 'Notification' => '', - // '%s moved the task #%d to the first swimlane' => '', - // '%s moved the task #%d to the swimlane "%s"' => '', - // 'Swimlane' => '', - // 'Budget overview' => '', - // 'Type' => '', - // 'There is not enough data to show something.' => '', - // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', - // '%s moved the task %s to the first swimlane' => '', - // '%s moved the task %s to the swimlane "%s"' => '', - // 'This report contains all subtasks information for the given date range.' => '', - // 'This report contains all tasks information for the given date range.' => '', - // 'Project activities for %s' => '', - // 'view the board on Kanboard' => '', - // 'The task have been moved to the first swimlane' => '', - // 'The task have been moved to another swimlane:' => '', - // 'Overdue tasks for the project "%s"' => '', - // 'New title: %s' => '', - // 'The task is not assigned anymore' => '', - // 'New assignee: %s' => '', - // 'There is no category now' => '', - // 'New category: %s' => '', - // 'New color: %s' => '', - // 'New complexity: %d' => '', - // 'The due date have been removed' => '', - // 'There is no description anymore' => '', - // 'Recurrence settings have been modified' => '', - // 'Time spent changed: %sh' => '', - // 'Time estimated changed: %sh' => '', - // 'The field "%s" have been updated' => '', - // 'The description have been modified' => '', - // 'Do you really want to close the task "%s" as well as all subtasks?' => '', - // 'Swimlane: %s' => '', - // 'I want to receive notifications for:' => '', - // 'All tasks' => '', - // 'Only for tasks assigned to me' => '', - // 'Only for tasks created by me' => '', - // 'Only for tasks created by me and assigned to me' => '', - // '%A' => '', - // '%b %e, %Y, %k:%M %p' => '', - // 'New due date: %B %e, %Y' => '', - // 'Start date changed: %B %e, %Y' => '', - // '%k:%M %p' => '', - // '%%Y-%%m-%%d' => '', - // 'Total for all columns' => '', - // 'You need at least 2 days of data to show the chart.' => '', - // '<15m' => '', - // '<30m' => '', - // 'Stop timer' => '', - // 'Start timer' => '', - // 'Add project member' => '', - // 'Enable notifications' => '', - // 'My activity stream' => '', - // 'My calendar' => '', - // 'Search tasks' => '', - // 'Back to the calendar' => '', - // 'Filters' => '', - // 'Reset filters' => '', - // 'My tasks due tomorrow' => '', - // 'Tasks due today' => '', - // 'Tasks due tomorrow' => '', - // 'Tasks due yesterday' => '', - // 'Closed tasks' => '', - // 'Open tasks' => '', - // 'Not assigned' => '', - // 'View advanced search syntax' => '', - // 'Overview' => '', - // '%b %e %Y' => '', - // 'Board/Calendar/List view' => '', - // 'Switch to the board view' => '', - // 'Switch to the calendar view' => '', - // 'Switch to the list view' => '', - // 'Go to the search/filter box' => '', - // 'There is no activity yet.' => '', - // 'No tasks found.' => '', - // 'Keyboard shortcut: "%s"' => '', - // 'List' => '', - // 'Filter' => '', - // 'Advanced search' => '', - // 'Example of query: ' => '', - // 'Search by project: ' => '', - // 'Search by column: ' => '', - // 'Search by assignee: ' => '', - // 'Search by color: ' => '', - // 'Search by category: ' => '', - // 'Search by description: ' => '', - // 'Search by due date: ' => '', + 'There is no user management for private projects.' => 'Não há gerenciamento de usuários para projetos privados.', + 'User that will receive the email' => 'O usuário que vai receber o e-mail', + 'Email subject' => 'Assunto do e-mail', + 'Date' => 'Data', + 'By @%s on Bitbucket' => 'Por @%s no Bitbucket', + 'Bitbucket Issue' => 'Bitbucket Issue', + 'Commit made by @%s on Bitbucket' => 'Commit feito por @%s no Bitbucket', + 'Commit made by @%s on Github' => 'Commit feito por @%s no Github', + 'By @%s on Github' => 'Por @%s no Github', + 'Commit made by @%s on Gitlab' => 'Commit feito por @%s no Gitlab', + 'Add a comment log when moving the task between columns' => 'Adicionar um comentário de log quando uma tarefa é movida para uma outra coluna', + 'Move the task to another column when the category is changed' => 'Mover uma tarefa para outra coluna quando a categoria mudou', + 'Send a task by email to someone' => 'Enviar uma tarefa por e-mail a alguém', + 'Reopen a task' => 'Reabrir uma tarefa', + 'Bitbucket issue opened' => 'Bitbucket issue opened', + 'Bitbucket issue closed' => 'Bitbucket issue closed', + 'Bitbucket issue reopened' => 'Bitbucket issue reopened', + 'Bitbucket issue assignee change' => 'Bitbucket issue assignee change', + 'Bitbucket issue comment created' => 'Bitbucket issue comment created', + 'Column change' => 'Mudança de coluna', + 'Position change' => 'Mudança de posição', + 'Swimlane change' => 'Mudança de swimlane', + 'Assignee change' => 'Mudança do designado', + '[%s] Overdue tasks' => '[%s] Tarefas atrasadas', + 'Notification' => 'Notificação', + '%s moved the task #%d to the first swimlane' => '%s moveu a tarefa n° %d no primeiro swimlane', + '%s moved the task #%d to the swimlane "%s"' => '%s moveu a tarefa n° %d no swimlane "%s"', + 'Swimlane' => 'Swimlane', + 'Budget overview' => 'Visão geral do orçamento', + 'Type' => 'Tipo', + 'There is not enough data to show something.' => 'Não há dados suficientes para mostrar alguma coisa.', + 'Gravatar' => 'Gravatar', + 'Hipchat' => 'Hipchat', + 'Slack' => 'Slack', + '%s moved the task %s to the first swimlane' => '%s moveu a tarefa %s no primeiro swimlane', + '%s moved the task %s to the swimlane "%s"' => '%s moveu a tarefa %s no swimlane "%s"', + 'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as sub-tarefas para o período selecionado.', + 'This report contains all tasks information for the given date range.' => 'Este relatório contém informações de todas as tarefas para o período selecionado.', + 'Project activities for %s' => 'Atividade do projeto "%s"', + 'view the board on Kanboard' => 'ver o painel no Kanboard', + 'The task have been moved to the first swimlane' => 'A tarefa foi movida para o primeiro Swimlane', + 'The task have been moved to another swimlane:' => 'A tarefa foi movida para outro Swimlane', + 'Overdue tasks for the project "%s"' => 'Tarefas atrasadas para o projeto "%s"', + 'New title: %s' => 'Novo título: %s', + 'The task is not assigned anymore' => 'Agora a tarefa não está mais atribuída', + 'New assignee: %s' => 'Novo designado: %s', + 'There is no category now' => 'Agora não tem mais categoria', + 'New category: %s' => 'Nova categoria: %s', + 'New color: %s' => 'Nova cor: %s', + 'New complexity: %d' => 'Nova complexidade: %d', + 'The due date have been removed' => 'A data limite foi retirada', + 'There is no description anymore' => 'Agora não tem mais descrição', + 'Recurrence settings have been modified' => 'As configurações da recorrência foram modificadas', + 'Time spent changed: %sh' => 'O tempo despendido foi mudado: %sh', + 'Time estimated changed: %sh' => 'O tempo estimado foi mudado/ %sh', + 'The field "%s" have been updated' => 'O campo "%s" foi atualizada', + 'The description have been modified' => 'A descrição foi modificada', + 'Do you really want to close the task "%s" as well as all subtasks?' => 'Você realmente quer fechar a tarefa "%s" e todas as suas sub-tarefas?', + 'Swimlane: %s' => 'Swimlane: %s', + 'I want to receive notifications for:' => 'Eu quero receber as notificações para:', + 'All tasks' => 'Todas as tarefas', + 'Only for tasks assigned to me' => 'Somente as tarefas atribuídas a mim', + 'Only for tasks created by me' => 'Apenas as tarefas que eu criei', + 'Only for tasks created by me and assigned to me' => 'Apenas as tarefas que eu criei e aquelas atribuídas a mim', + '%A' => '%A', + '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M', + 'New due date: %B %e, %Y' => 'Nova data limite: %d/%m/%Y', + 'Start date changed: %B %e, %Y' => 'Data de início alterada: %d/%m/%Y', + '%k:%M %p' => '%H:%M', + '%%Y-%%m-%%d' => '%%d/%%m/%%Y', + 'Total for all columns' => 'Total para todas as colunas', + 'You need at least 2 days of data to show the chart.' => 'Você precisa de pelo menos 2 dias de dados para visualizar o gráfico.', + '<15m' => '<15m', + '<30m' => '<30m', + 'Stop timer' => 'Stop timer', + 'Start timer' => 'Start timer', + 'Add project member' => 'Adicionar um membro ao projeto', + 'Enable notifications' => 'Ativar as notificações', + 'My activity stream' => 'Meu feed de atividade', + 'My calendar' => 'Minha agenda', + 'Search tasks' => 'Pesquisar tarefas', + 'Back to the calendar' => 'Voltar ao calendário', + 'Filters' => 'Filtros', + 'Reset filters' => 'Redefinir os filtros', + 'My tasks due tomorrow' => 'Minhas tarefas que expiram amanhã', + 'Tasks due today' => 'Tarefas que expiram hoje', + 'Tasks due tomorrow' => 'Tarefas que expiram amanhã', + 'Tasks due yesterday' => 'Tarefas que expiraram ontem', + 'Closed tasks' => 'Tarefas fechadas', + 'Open tasks' => 'Tarefas abertas', + 'Not assigned' => 'Não designada', + 'View advanced search syntax' => 'Ver a sintaxe para pesquisa avançada', + 'Overview' => 'Visão global', + '%b %e %Y' => '%b %e %Y', + 'Board/Calendar/List view' => 'Vista Painel/Calendário/Lista', + 'Switch to the board view' => 'Mudar para o modo Painel', + 'Switch to the calendar view' => 'Mudar par o modo Calendário', + 'Switch to the list view' => 'Mudar par o modo Lista', + 'Go to the search/filter box' => 'Ir para o campo de pesquisa', + 'There is no activity yet.' => 'Não há nenhuma atividade ainda.', + 'No tasks found.' => 'Nenhuma tarefa encontrada', + 'Keyboard shortcut: "%s"' => 'Tecla de atalho: "%s"', + 'List' => 'Lista', + 'Filter' => 'Filtro', + 'Advanced search' => 'Pesquisa avançada', + 'Example of query: ' => 'Exemplo de consulta: ', + 'Search by project: ' => 'Pesquisar por projet: ', + 'Search by column: ' => 'Pesquisar por coluna: ', + 'Search by assignee: ' => 'Pesquisar por designado: ', + 'Search by color: ' => 'Pesquisar por cor: ', + 'Search by category: ' => 'Pesquisar por categoria: ', + 'Search by description: ' => 'Pesquisar por descrição: ', + 'Search by due date: ' => 'Pesquisar por data de expiração: ', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 9b8b3e4f..3b7d678c 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Требуется имя проекта', 'This project must be unique' => 'Проект должен быть уникальным', 'The title is required' => 'Требуется заголовок', - 'There is no active project, the first step is to create a new project.' => 'Нет активного проекта, сначала создайте новый проект.', 'Settings saved successfully.' => 'Параметры успешно сохранены.', 'Unable to save your settings.' => 'Невозможно сохранить параметры.', 'Database optimization done.' => 'База данных оптимизирована.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d комментариев', '%d comment' => '%d комментарий', 'Email address invalid' => 'Некорректный e-mail адрес', - 'Your Google Account is not linked anymore to your profile.' => 'Ваш аккаунт в Google больше не привязан к вашему профилю.', - 'Unable to unlink your Google Account.' => 'Не удалось отвязать ваш профиль от Google.', - 'Google authentication failed' => 'Аутентификация Google не удалась', - 'Unable to link your Google Account.' => 'Не удалось привязать ваш профиль к Google.', - 'Your Google Account is linked to your profile successfully.' => 'Ваш профиль успешно привязан к Google.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-mail', 'Link my Google Account' => 'Привязать мой профиль к Google', 'Unlink my Google Account' => 'Отвязать мой профиль от Google', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Максимальный размер: ', 'Unable to upload the file.' => 'Не удалось загрузить файл.', 'Display another project' => 'Показать другой проект', - 'Your GitHub account was successfully linked to your profile.' => 'Ваш GitHub привязан к вашему профилю.', - 'Unable to link your GitHub Account.' => 'Не удалось привязать ваш профиль к GitHub.', - 'GitHub authentication failed' => 'Аутентификация в GitHub не удалась', - 'Your GitHub account is no longer linked to your profile.' => 'Ваш GitHub отвязан от вашего профиля.', - 'Unable to unlink your GitHub Account.' => 'Не удалось отвязать ваш профиль от GitHub.', - 'Login with my GitHub Account' => 'Аутентификация через GitHub', - 'Link my GitHub Account' => 'Привязать мой профиль к GitHub', - 'Unlink my GitHub Account' => 'Отвязать мой профиль от GitHub', + 'Login with my Github Account' => 'Аутентификация через Github', + 'Link my Github Account' => 'Привязать мой профиль к Github', + 'Unlink my Github Account' => 'Отвязать мой профиль от Github', 'Created by %s' => 'Создано %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Последнее изменение %d/%m/%Y в %H:%M', 'Tasks Export' => 'Экспорт задач', @@ -403,7 +396,7 @@ return array( 'Enabled' => 'Включен', 'Disabled' => 'Выключены', 'Google account linked' => 'Профиль Google связан', - 'Github account linked' => 'Профиль GitHub связан', + 'Github account linked' => 'Профиль Github связан', 'Username:' => 'Имя пользователя:', 'Name:' => 'Имя:', 'Email:' => 'E-mail:', @@ -417,7 +410,7 @@ return array( 'Password modification' => 'Изменение пароля', 'External authentications' => 'Внешняя аутентификация', 'Google Account' => 'Профиль Google', - 'Github Account' => 'Профиль GitHub', + 'Github Account' => 'Профиль Github', 'Never connected.' => 'Ранее не соединялось.', 'No account linked.' => 'Нет связанных профилей.', 'Account linked.' => 'Профиль связан.', @@ -458,12 +451,12 @@ return array( '%s changed the assignee of the task %s to %s' => '%s сменил назначенного для задачи %s на %s', 'New password for the user "%s"' => 'Новый пароль для пользователя "%s"', 'Choose an event' => 'Выберите событие', - 'Github commit received' => 'GitHub: коммит получен', - 'Github issue opened' => 'GitHub: новая проблема', - 'Github issue closed' => 'GitHub: проблема закрыта', - 'Github issue reopened' => 'GitHub: проблема переоткрыта', - 'Github issue assignee change' => 'GitHub: сменить ответственного за проблему', - 'Github issue label change' => 'GitHub: ярлык проблемы изменен', + 'Github commit received' => 'Github: коммит получен', + 'Github issue opened' => 'Github: новая проблема', + 'Github issue closed' => 'Github: проблема закрыта', + 'Github issue reopened' => 'Github: проблема переоткрыта', + 'Github issue assignee change' => 'Github: сменить ответственного за проблему', + 'Github issue label change' => 'Github: ярлык проблемы изменен', 'Create a task from an external provider' => 'Создать задачу из внешнего источника', 'Change the assignee based on an external username' => 'Изменить назначенного основываясь на внешнем имени пользователя', 'Change the category based on an external label' => 'Изменить категорию основываясь на внешнем ярлыке', @@ -508,8 +501,8 @@ return array( 'Everybody have access to this project.' => 'Любой может получить доступ к этому проекту.', 'Webhooks' => 'Webhooks', 'API' => 'API', - 'Github webhooks' => 'GitHub webhooks', - 'Help on Github webhooks' => 'Помощь по GitHub webhooks', + 'Github webhooks' => 'Github webhooks', + 'Help on Github webhooks' => 'Помощь по Github webhooks', 'Create a comment from an external provider' => 'Создать комментарий из внешнего источника', 'Github issue comment created' => 'Github issue комментарий создан', 'Project management' => 'Управление проектом', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Учет времени', 'You already have one subtask in progress' => 'У вас уже есть одна задача в разработке', 'Which parts of the project do you want to duplicate?' => 'Какие части проекта должны быть дублированы?', - 'Disable login form' => 'Выключить форму авторизации', - 'Show/hide calendar' => 'Показать/скрыть календарь', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', 'Bitbucket webhooks' => 'BitBucket webhooks', 'Help on Bitbucket webhooks' => 'Помощь по BitBucket webhooks', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index 758689c4..f3369341 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -126,7 +126,6 @@ return array( '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', - '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.', @@ -264,11 +263,10 @@ return array( '%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', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-mail', 'Link my Google Account' => 'Poveži sa Google nalogom', 'Unlink my Google Account' => 'Ukini vezu sa Google nalogom', @@ -338,14 +336,9 @@ return array( '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', + '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', @@ -615,8 +608,7 @@ return array( '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', - // 'Disable login form' => '', - // 'Show/hide calendar' => '', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', // 'Bitbucket webhooks' => '', // 'Help on Bitbucket webhooks' => '', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index 4690edea..db552359 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Ett projektnamn måste anges', 'This project must be unique' => 'Detta projekt måste vara unikt', 'The title is required' => 'En titel måste anges.', - 'There is no active project, the first step is to create a new project.' => 'Inget projekt är aktiverat, första steget är att skapa ett nytt projekt', 'Settings saved successfully.' => 'Inställningarna har sparats.', 'Unable to save your settings.' => 'Kunde inte spara dina ändringar', 'Database optimization done.' => 'Databasen har optimerats.', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d kommentarer', '%d comment' => '%d kommentar', 'Email address invalid' => 'Epost-adressen ogiltig', - 'Your Google Account is not linked anymore to your profile.' => 'Ditt Google-konto är inte längre länkat till din profil', - 'Unable to unlink your Google Account.' => 'Kunde inte ta bort länken till ditt Google-konto.', - 'Google authentication failed' => 'Autentiseringen för Google misslyckades', - 'Unable to link your Google Account.' => 'Kunde inte länka till ditt Google-konto', - 'Your Google Account is linked to your profile successfully.' => 'Ditt Google-konto har kopplats till din profil.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Epost', 'Link my Google Account' => 'Länka till mitt Google-konto', 'Unlink my Google Account' => 'Ta bort länken till mitt Google-konto', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'Maxstorlek: ', 'Unable to upload the file.' => 'Kunde inte ladda upp filen.', 'Display another project' => 'Visa ett annat projekt', - 'Your GitHub account was successfully linked to your profile.' => 'Ditt GitHub-konto har anslutits till din profil.', - 'Unable to link your GitHub Account.' => 'Kunde inte ansluta ditt GitHub-konto.', - 'GitHub authentication failed' => 'GitHub-verifiering misslyckades', - 'Your GitHub account is no longer linked to your profile.' => 'Ditt GitHub-konto är inte längre anslutet till din profil.', - 'Unable to unlink your GitHub Account.' => 'Kunde inte koppla ifrån ditt GitHub-konto.', - 'Login with my GitHub Account' => 'Logga in med mitt GitHub-konto', - 'Link my GitHub Account' => 'Anslut mitt GitHub-konto', - 'Unlink my GitHub Account' => 'Koppla ifrån mitt GitHub-konto', + 'Login with my Github Account' => 'Logga in med mitt Github-konto', + 'Link my Github Account' => 'Anslut mitt Github-konto', + 'Unlink my Github Account' => 'Koppla ifrån mitt Github-konto', 'Created by %s' => 'Skapad av %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Senaste ändring %Y-%m-%d kl %H:%M', 'Tasks Export' => 'Exportera uppgifter', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'Tidsbevakning', 'You already have one subtask in progress' => 'Du har redan en deluppgift igång', 'Which parts of the project do you want to duplicate?' => 'Vilka delar av projektet vill du duplicera?', - 'Disable login form' => 'Inaktivera loginformuläret', - 'Show/hide calendar' => 'Visa/dölj kalender', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Bitbucket bidrag mottaget', 'Bitbucket webhooks' => 'Bitbucket webhooks', 'Help on Bitbucket webhooks' => 'Hjälp för Bitbucket webhooks', @@ -865,8 +857,8 @@ return array( 'By @%s on Bitbucket' => 'Av @%s på Bitbucket', 'Bitbucket Issue' => 'Bitbucket fråga', 'Commit made by @%s on Bitbucket' => 'Bidrag gjort av @%s på Bitbucket', - 'Commit made by @%s on Github' => 'Bidrag gjort av @%s på GitHub', - 'By @%s on Github' => 'Av @%s på GitHub', + 'Commit made by @%s on Github' => 'Bidrag gjort av @%s på Github', + 'By @%s on Github' => 'Av @%s på Github', 'Commit made by @%s on Gitlab' => 'Bidrag gjort av @%s på Gitlab', 'Add a comment log when moving the task between columns' => 'Lägg till en kommentarslogg när en uppgift flyttas mellan kolumner', 'Move the task to another column when the category is changed' => 'Flyttas uppgiften till en annan kolumn när kategorin ändras', @@ -971,4 +963,39 @@ return array( 'Search by category: ' => 'Sök efter kategori:', 'Search by description: ' => 'Sök efter beskrivning', 'Search by due date: ' => 'Sök efter förfallodatum', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index c1eb3183..c4d608bd 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'ต้องการชื่อโปรเจค', 'This project must be unique' => 'ชื่อโปรเจคต้องไม่ซ้ำ', 'The title is required' => 'ต้องการหัวเรื่อง', - 'There is no active project, the first step is to create a new project.' => 'ไม่มีโปรเจคที่ทำงานอยู่, ต้องการสร้างโปรเจคใหม่', 'Settings saved successfully.' => 'บันทึกการตั้งค่าเรียบร้อยแล้ว', 'Unable to save your settings.' => 'ไม่สามารถบันทึกการตั้งค่าได้', 'Database optimization done.' => 'ปรับปรุงฐานข้อมูลเรียบร้อยแล้ว', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d ความคิดเห็น', '%d comment' => '%d ความคิดเห็น', 'Email address invalid' => 'อีเมลผิด', - 'Your Google Account is not linked anymore to your profile.' => 'กูเกิลแอคเคาท์ไม่ได้เชื่อมต่อกับประวัติของคุณ', - 'Unable to unlink your Google Account.' => 'ไม่สามารถยกเลิกการเชื่อมต่อกับกูเกิลแอคเคาท์', - 'Google authentication failed' => 'การยืนยันกับกูเกิลผิดพลาด', - 'Unable to link your Google Account.' => 'ไม่สามารถเชื่อมต่อกับกูเกิลแอคเคาท์', - 'Your Google Account is linked to your profile successfully.' => 'กูเกลิแอคเคาท์เชื่อมต่อกับประวัติของคุณเรียบร้อยแล้ว', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'อีเมล', 'Link my Google Account' => 'เชื่อมต่อกับกูเกิลแอคเคาท์', 'Unlink my Google Account' => 'ไม่เชื่อมต่อกับกูเกิลแอคเคาท์', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => 'ขนาดสูงสุด:', 'Unable to upload the file.' => 'ไม่สามารถอัพโหลดไฟล์ได้', 'Display another project' => 'แสดงโปรเจคอื่น', - 'Your GitHub account was successfully linked to your profile.' => 'กิทฮับแอคเคาท์เชื่อมต่อกับประวัติเรียบร้อยแล้ว', - 'Unable to link your GitHub Account.' => 'ไม่สามารถเชื่อมต่อกับกิทฮับแอคเคาท์ได้', - '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' => 'ยกเลิกการเชื่อมกับกิทอับแอคเคาท์', + 'Login with my Github Account' => 'เข้าใช้ด้วยกิทฮับแอคเคาท์', + 'Link my Github Account' => 'เชื่อมกับกิทฮับแอคเคาท์', + 'Unlink my Github Account' => 'ยกเลิกการเชื่อมกับกิทอับแอคเคาท์', 'Created by %s' => 'สร้างโดย %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'แก้ไขล่าสุดวันที่ %B %e, %Y เวลา %k:%M %p', 'Tasks Export' => 'ส่งออกงาน', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => 'ติดตามเวลา', 'You already have one subtask in progress' => 'คุณมีหนึ่งงานย่อยที่กำลังทำงาน', // 'Which parts of the project do you want to duplicate?' => '', - // 'Disable login form' => '', - 'Show/hide calendar' => 'แสดง/ซ่อน ปฎิทิน', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', // 'Bitbucket webhooks' => '', // 'Help on Bitbucket webhooks' => '', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 9335c201..afb88744 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -126,7 +126,6 @@ return array( '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', - '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ı.', @@ -264,11 +263,10 @@ return array( '%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ı', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'E-Posta', 'Link my Google Account' => 'Google hesabımla bağ oluştur', 'Unlink my Google Account' => 'Google hesabımla bağı kaldır', @@ -338,14 +336,9 @@ return array( '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' => '', + // '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', @@ -615,8 +608,7 @@ return array( '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?', - 'Disable login form' => 'Giriş formunu devre dışı bırak', - 'Show/hide calendar' => 'Takvimi göster/gizle', + // 'Disallow login form' => '', 'Bitbucket commit received' => 'Bitbucket commit alındı', 'Bitbucket webhooks' => 'Bitbucket webhooks', 'Help on Bitbucket webhooks' => 'Bitbucket webhooks için yardım', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 155628dc..cd2518fd 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => '需要指定项目名称', 'This project must be unique' => '项目名称必须唯一', 'The title is required' => '需要指定标题', - 'There is no active project, the first step is to create a new project.' => '尚无活跃项目,请首先创建一个新项目。', 'Settings saved successfully.' => '设置成功保存。', 'Unable to save your settings.' => '无法保存你的设置。', 'Database optimization done.' => '数据库优化完成。', @@ -264,11 +263,10 @@ return array( '%d comments' => '%d个评论', '%d comment' => '%d个评论', 'Email address invalid' => '电子邮件地址无效', - 'Your Google Account is not linked anymore to your profile.' => '您的google帐号不再与您的账户配置关联。', - 'Unable to unlink your Google Account.' => '无法去除您google帐号的关联', - 'Google authentication failed' => 'google验证失败', - 'Unable to link your Google Account.' => '无法关联您的google帐号。', - 'Your Google Account is linked to your profile successfully.' => '您的google帐号已成功与账户配置关联。', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => '电子邮件', 'Link my Google Account' => '关联我的google帐号', 'Unlink my Google Account' => '去除我的google帐号关联', @@ -338,14 +336,9 @@ return array( 'Maximum size: ' => '大小上限:', 'Unable to upload the file.' => '无法上传文件', 'Display another project' => '显示其它项目', - 'Your GitHub account was successfully linked to your profile.' => 'GitHub账号已经成功链接到您的用户', - 'Unable to link your GitHub Account.' => '无法链接到GitHub账户', - 'GitHub authentication failed' => 'GitHub认证失败', - 'Your GitHub account is no longer linked to your profile.' => 'Github账号已经不再链接到您的用户', - 'Unable to unlink your GitHub Account.' => '无法链接GitHub账号', - 'Login with my GitHub Account' => '用Github账号登录', - 'Link my GitHub Account' => '链接GitHub账号', - 'Unlink my GitHub Account' => '取消GitHub账号链接', + 'Login with my Github Account' => '用Github账号登录', + 'Link my Github Account' => '链接Github账号', + 'Unlink my Github Account' => '取消Github账号链接', 'Created by %s' => '创建者:%s', 'Last modified on %B %e, %Y at %k:%M %p' => '最后修改:%Y/%m/%d/ %H:%M', 'Tasks Export' => '任务导出', @@ -615,8 +608,7 @@ return array( 'Time Tracking' => '时间记录', 'You already have one subtask in progress' => '你已经有了一个进行中的子任务', 'Which parts of the project do you want to duplicate?' => '要复制项目的哪些内容?', - 'Disable login form' => '禁用登录界面', - 'Show/hide calendar' => '显示/隐藏日程表', + // 'Disallow login form' => '', 'Bitbucket commit received' => '收到Bitbucket提交', 'Bitbucket webhooks' => 'Bitbucket网络钩子', 'Help on Bitbucket webhooks' => 'Bitbucket网络钩子帮助', @@ -971,4 +963,39 @@ return array( // 'Search by category: ' => '', // 'Search by description: ' => '', // 'Search by due date: ' => '', + // 'Lead and Cycle time for "%s"' => '', + // 'Average time spent into each column for "%s"' => '', + // 'Average time spent into each column' => '', + // 'Average time spent' => '', + // 'This chart show the average time spent into each column for the last %d tasks.' => '', + // 'Average Lead and Cycle time' => '', + // 'Average lead time: ' => '', + // 'Average cycle time: ' => '', + // 'Cycle Time' => '', + // 'Lead Time' => '', + // 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '', + // 'Average time into each column' => '', + // 'Lead and cycle time' => '', + // 'Google Authentication' => '', + // 'Help on Google authentication' => '', + // 'Github Authentication' => '', + // 'Help on Github authentication' => '', + // 'Channel/Group/User (Optional)' => '', + // 'Lead time: ' => '', + // 'Cycle time: ' => '', + // 'Time spent into each column' => '', + // 'The lead time is the duration between the task creation and the completion.' => '', + // 'The cycle time is the duration between the start date and the completion.' => '', + // 'If the task is not closed the current time is used instead of the completion date.' => '', + // 'Set automatically the start date' => '', + // 'Edit Authentication' => '', + // 'Google Id' => '', + // 'Github Id' => '', + // 'Remote user' => '', + // 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '', + // 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '', + // 'By @%s on Gitlab' => '', + // 'Gitlab issue comment created' => '', + // 'New remote user' => '', + // 'New local user' => '', ); diff --git a/app/Model/Acl.php b/app/Model/Acl.php index 09638302..b9c06e98 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -18,12 +18,12 @@ class Acl extends Base */ private $public_acl = array( 'auth' => array('login', 'check'), - 'user' => array('google', 'github'), 'task' => array('readonly'), 'board' => array('readonly'), 'webhook' => '*', 'ical' => '*', 'feed' => '*', + 'oauth' => array('google', 'github'), ); /** @@ -70,7 +70,7 @@ class Acl extends Base * @var array */ private $admin_acl = array( - 'user' => array('index', 'create', 'save', 'remove'), + 'user' => array('index', 'create', 'save', 'remove', 'authentication'), 'config' => '*', 'link' => '*', 'project' => array('remove'), diff --git a/app/Model/Action.php b/app/Model/Action.php index d0607794..5e994c99 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -92,6 +92,7 @@ class Action extends Base GitlabWebhook::EVENT_COMMIT => t('Gitlab commit received'), GitlabWebhook::EVENT_ISSUE_OPENED => t('Gitlab issue opened'), GitlabWebhook::EVENT_ISSUE_CLOSED => t('Gitlab issue closed'), + GitlabWebhook::EVENT_ISSUE_COMMENT => t('Gitlab issue comment created'), BitbucketWebhook::EVENT_COMMIT => t('Bitbucket commit received'), BitbucketWebhook::EVENT_ISSUE_OPENED => t('Bitbucket issue opened'), BitbucketWebhook::EVENT_ISSUE_CLOSED => t('Bitbucket issue closed'), diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php index 8d7bdb44..d7d5148b 100644 --- a/app/Model/TaskFilter.php +++ b/app/Model/TaskFilter.php @@ -71,6 +71,9 @@ class TaskFilter extends Base case 'T_REFERENCE': $this->filterByReference($value); break; + case 'T_SWIMLANE': + $this->filterBySwimlaneName($value); + break; } } @@ -247,6 +250,30 @@ class TaskFilter extends Base } /** + * Filter by swimlane name + * + * @access public + * @param array $values List of swimlane name + * @return TaskFilter + */ + public function filterBySwimlaneName(array $values) + { + $this->query->beginOr(); + + foreach ($values as $swimlane) { + if ($swimlane === 'default') { + $this->query->eq(Task::TABLE.'.swimlane_id', 0); + } + else { + $this->query->ilike(Swimlane::TABLE.'.name', $swimlane); + $this->query->addCondition(Task::TABLE.'.swimlane_id=0 AND '.Project::TABLE.'.default_swimlane '.$this->db->getDriver()->getOperator('ILIKE')." '$swimlane'"); + } + } + + $this->query->closeOr(); + } + + /** * Filter by category id * * @access public diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 2b0453a5..47a67a35 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -88,11 +88,14 @@ class TaskFinder extends Base Category::TABLE.'.name AS category_name', Category::TABLE.'.description AS category_description', Board::TABLE.'.title AS column_name', + Swimlane::TABLE.'.name AS swimlane_name', + Project::TABLE.'.default_swimlane', Project::TABLE.'.name AS project_name' ) ->join(User::TABLE, 'id', 'owner_id', Task::TABLE) ->join(Category::TABLE, 'id', 'category_id', Task::TABLE) ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->join(Swimlane::TABLE, 'id', 'swimlane_id', Task::TABLE) ->join(Project::TABLE, 'id', 'project_id', Task::TABLE); } diff --git a/app/Model/User.php b/app/Model/User.php index 4c32942c..b6804abc 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -122,13 +122,13 @@ class User extends Base } /** - * Get a specific user by the GitHub id + * Get a specific user by the Github id * * @access public - * @param string $github_id GitHub user id + * @param string $github_id Github user id * @return array|boolean */ - public function getByGitHubId($github_id) + public function getByGithubId($github_id) { if (empty($github_id)) { return false; @@ -377,6 +377,7 @@ class User extends Base new Validators\Unique('username', t('The username must be unique'), $this->db->getConnection(), self::TABLE, 'id'), new Validators\Email('email', t('Email address invalid')), new Validators\Integer('is_admin', t('This value must be an integer')), + new Validators\Integer('is_ldap_user', t('This value must be an integer')), ); } @@ -409,7 +410,12 @@ class User extends Base new Validators\Required('username', t('The username is required')), ); - $v = new Validator($values, array_merge($rules, $this->commonValidationRules(), $this->commonPasswordValidationRules())); + if (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1) { + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); + } + else { + $v = new Validator($values, array_merge($rules, $this->commonValidationRules(), $this->commonPasswordValidationRules())); + } return array( $v->execute(), diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 8c55457d..ef7aa575 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -3,6 +3,7 @@ namespace ServiceProvider; use Core\Paginator; +use Core\OAuth2; use Model\Config; use Model\Project; use Model\Webhook; @@ -72,6 +73,7 @@ class ClassProvider implements ServiceProviderInterface 'Lexer', 'MemoryCache', 'Request', + 'Router', 'Session', 'Template', ), @@ -106,5 +108,9 @@ class ClassProvider implements ServiceProviderInterface $container['paginator'] = $container->factory(function ($c) { return new Paginator($c); }); + + $container['oauth'] = $container->factory(function ($c) { + return new OAuth2($c); + }); } } diff --git a/app/Template/app/overview.php b/app/Template/app/overview.php index fa7866af..1b160496 100644 --- a/app/Template/app/overview.php +++ b/app/Template/app/overview.php @@ -1,7 +1,7 @@ <div class="search"> - <form method="get" action="?" class="search"> + <form method="get" action="<?= $this->url->dir() ?>" class="search"> <?= $this->form->hidden('controller', array('controller' => 'search')) ?> - <?= $this->form->hidden('action', array('controller' => 'index')) ?> + <?= $this->form->hidden('action', array('action' => 'index')) ?> <?= $this->form->text('search', array(), array(), array('placeholder="'.t('Search').'"'), 'form-input-large') ?> </form> diff --git a/app/Template/auth/index.php b/app/Template/auth/index.php index 39d007f5..ca303df9 100644 --- a/app/Template/auth/index.php +++ b/app/Template/auth/index.php @@ -4,7 +4,8 @@ <p class="alert alert-error"><?= $this->e($errors['login']) ?></p> <?php endif ?> - <form method="post" action="<?= $this->url->href('auth', 'check', array('redirect_query' => $redirect_query)) ?>"> + <?php if (! HIDE_LOGIN_FORM): ?> + <form method="post" action="<?= $this->url->href('auth', 'check') ?>"> <?= $this->form->csrf() ?> @@ -16,17 +17,22 @@ <?= $this->form->checkbox('remember_me', t('Remember Me'), 1, true) ?><br/> + <div class="form-actions"> + <input type="submit" value="<?= t('Sign in') ?>" class="btn btn-blue"/> + </div> + </form> + <?php endif ?> + + <?php if (GOOGLE_AUTH || GITHUB_AUTH): ?> + <ul class="no-bullet"> <?php if (GOOGLE_AUTH): ?> - <?= $this->url->link(t('Login with my Google Account'), 'user', 'google') ?> + <li><?= $this->url->link(t('Login with my Google Account'), 'oauth', 'google') ?></li> <?php endif ?> <?php if (GITHUB_AUTH): ?> - <?= $this->url->link(t('Login with my GitHub Account'), 'user', 'gitHub') ?> + <li><?= $this->url->link(t('Login with my Github Account'), 'oauth', 'gitHub') ?></li> <?php endif ?> - - <div class="form-actions"> - <input type="submit" value="<?= t('Sign in') ?>" class="btn btn-blue"/> - </div> - </form> + </ul> + <?php endif ?> </div>
\ No newline at end of file diff --git a/app/Template/board/task_menu.php b/app/Template/board/task_menu.php index 97c0f8dc..a84b972d 100644 --- a/app/Template/board/task_menu.php +++ b/app/Template/board/task_menu.php @@ -9,7 +9,6 @@ <li><i class="fa fa-comment-o"></i> <?= $this->url->link(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li> <li><i class="fa fa-code-fork"></i> <?= $this->url->link(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li> <li><i class="fa fa-camera"></i> <?= $this->url->link(t('Add a screenshot'), 'board', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li> - <li><i class="fa fa-refresh fa-rotate-90"></i> <?= $this->url->link(t('Edit recurrence'), 'task', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li> <li><i class="fa fa-close"></i> <?= $this->url->link(t('Close this task'), 'task', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'task-board-popover') ?></li> </ul> </span> diff --git a/app/Template/config/integrations.php b/app/Template/config/integrations.php index 9c80b499..47b45149 100644 --- a/app/Template/config/integrations.php +++ b/app/Template/config/integrations.php @@ -6,30 +6,42 @@ <?= $this->form->csrf() ?> - <h3><img src="assets/img/mailgun-icon.png"/> <?= t('Mailgun (incoming emails)') ?></h3> + <h3><i class="fa fa-google"></i> <?= t('Google Authentication') ?></h3> <div class="listing"> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'mailgun', array('token' => $values['webhook_token'])) ?>"/><br/> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('oauth', 'google', array(), false, '', true) ?>"/><br/> + <p class="form-help"><a href="http://kanboard.net/documentation/google-authentication" target="_blank"><?= t('Help on Google authentication') ?></a></p> + </div> + + <h3><i class="fa fa-github"></i> <?= t('Github Authentication') ?></h3> + <div class="listing"> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('oauth', 'github', array(), false, '', true) ?>"/><br/> + <p class="form-help"><a href="http://kanboard.net/documentation/github-authentication" target="_blank"><?= t('Help on Github authentication') ?></a></p> + </div> + + <h3><img src="<?= $this->url->dir() ?>assets/img/mailgun-icon.png"/> <?= t('Mailgun (incoming emails)') ?></h3> + <div class="listing"> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'mailgun', array('token' => $values['webhook_token']), false, '', true) ?>"/><br/> <p class="form-help"><a href="http://kanboard.net/documentation/mailgun" target="_blank"><?= t('Help on Mailgun integration') ?></a></p> </div> - <h3><img src="assets/img/sendgrid-icon.png"/> <?= t('Sendgrid (incoming emails)') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/sendgrid-icon.png"/> <?= t('Sendgrid (incoming emails)') ?></h3> <div class="listing"> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'sendgrid', array('token' => $values['webhook_token'])) ?>"/><br/> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'sendgrid', array('token' => $values['webhook_token']), false, '', true) ?>"/><br/> <p class="form-help"><a href="http://kanboard.net/documentation/sendgrid" target="_blank"><?= t('Help on Sendgrid integration') ?></a></p> </div> - <h3><img src="assets/img/postmark-icon.png"/> <?= t('Postmark (incoming emails)') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/postmark-icon.png"/> <?= t('Postmark (incoming emails)') ?></h3> <div class="listing"> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'postmark', array('token' => $values['webhook_token'])) ?>"/><br/> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'postmark', array('token' => $values['webhook_token']), false, '', true) ?>"/><br/> <p class="form-help"><a href="http://kanboard.net/documentation/postmark" target="_blank"><?= t('Help on Postmark integration') ?></a></p> </div> - <h3><img src="assets/img/gravatar-icon.png"/> <?= t('Gravatar') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/gravatar-icon.png"/> <?= t('Gravatar') ?></h3> <div class="listing"> <?= $this->form->checkbox('integration_gravatar', t('Enable Gravatar images'), 1, $values['integration_gravatar'] == 1) ?> </div> - <h3><img src="assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> <div class="listing"> <?= $this->form->checkbox('integration_jabber', t('Send notifications to Jabber'), 1, $values['integration_jabber'] == 1) ?> @@ -55,7 +67,7 @@ <p class="form-help"><a href="http://kanboard.net/documentation/jabber" target="_blank"><?= t('Help on Jabber integration') ?></a></p> </div> - <h3><img src="assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> <div class="listing"> <?= $this->form->checkbox('integration_hipchat', t('Send notifications to Hipchat'), 1, $values['integration_hipchat'] == 1) ?> diff --git a/app/Template/config/webhook.php b/app/Template/config/webhook.php index 73ca3598..f1a98f8b 100644 --- a/app/Template/config/webhook.php +++ b/app/Template/config/webhook.php @@ -26,7 +26,7 @@ </li> <li> <?= t('URL for task creation:') ?> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'task', array('token' => $values['webhook_token'])) ?>"> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'task', array('token' => $values['webhook_token']), false, '', true) ?>"> </li> <li> <?= $this->url->link(t('Reset token'), 'config', 'token', array('type' => 'webhook'), true) ?> diff --git a/app/Template/feed/project.php b/app/Template/feed/project.php index 60b7ee96..76cf6cf0 100644 --- a/app/Template/feed/project.php +++ b/app/Template/feed/project.php @@ -2,15 +2,15 @@ <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"> <title><?= t('%s\'s activity', $project['name']) ?></title> <link rel="alternate" type="text/html" href="<?= $this->url->base() ?>"/> - <link rel="self" type="application/atom+xml" href="<?= $this->url->base().$this->url->href('feed', 'project', array('token' => $project['token'])) ?>"/> + <link rel="self" type="application/atom+xml" href="<?= $this->url->href('feed', 'project', array('token' => $project['token']), false, '', true) ?>"/> <updated><?= date(DATE_ATOM) ?></updated> - <id><?= $this->url->base().$this->url->href('feed', 'project', array('token' => $project['token'])) ?></id> + <id><?= $this->url->href('feed', 'project', array('token' => $project['token']), false, '', true) ?></id> <icon><?= $this->url->base() ?>assets/img/favicon.png</icon> <?php foreach ($events as $e): ?> <entry> <title type="text"><?= $e['event_title'] ?></title> - <link rel="alternate" href="<?= $this->url->base().$this->url->href('task', 'show', array('task_id' => $e['task_id'])) ?>"/> + <link rel="alternate" href="<?= $this->url->href('task', 'show', array('task_id' => $e['task_id']), false, '', true) ?>"/> <id><?= $e['id'].'-'.$e['event_name'].'-'.$e['task_id'].'-'.$e['date_creation'] ?></id> <published><?= date(DATE_ATOM, $e['date_creation']) ?></published> <updated><?= date(DATE_ATOM, $e['date_creation']) ?></updated> diff --git a/app/Template/feed/user.php b/app/Template/feed/user.php index b3279a0c..3e9606c6 100644 --- a/app/Template/feed/user.php +++ b/app/Template/feed/user.php @@ -2,15 +2,15 @@ <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"> <title><?= t('Project activities for %s', $user['name'] ?: $user['username']) ?></title> <link rel="alternate" type="text/html" href="<?= $this->url->base() ?>"/> - <link rel="self" type="application/atom+xml" href="<?= $this->url->base().$this->url->href('feed', 'user', array('token' => $user['token'])) ?>"/> + <link rel="self" type="application/atom+xml" href="<?= $this->url->href('feed', 'user', array('token' => $user['token']), false, '', true) ?>"/> <updated><?= date(DATE_ATOM) ?></updated> - <id><?= $this->url->base().$this->url->href('feed', 'user', array('token' => $user['token'])) ?></id> + <id><?= $this->url->href('feed', 'user', array('token' => $user['token']), false, '', true) ?></id> <icon><?= $this->url->base() ?>assets/img/favicon.png</icon> <?php foreach ($events as $e): ?> <entry> <title type="text"><?= $e['event_title'] ?></title> - <link rel="alternate" href="<?= $this->url->base().$this->url->href('task', 'show', array('task_id' => $e['task_id'])) ?>"/> + <link rel="alternate" href="<?= $this->url->href('task', 'show', array('task_id' => $e['task_id']), false, '', true) ?>"/> <id><?= $e['id'].'-'.$e['event_name'].'-'.$e['task_id'].'-'.$e['date_creation'] ?></id> <published><?= date(DATE_ATOM, $e['date_creation']) ?></published> <updated><?= date(DATE_ATOM, $e['date_creation']) ?></updated> diff --git a/app/Template/layout.php b/app/Template/layout.php index a9f1cbc3..d02ba08d 100644 --- a/app/Template/layout.php +++ b/app/Template/layout.php @@ -20,11 +20,11 @@ <?= $this->asset->css('assets/css/print.css', true, 'print') ?> <?= $this->asset->customCss() ?> - <link rel="icon" type="image/png" href="assets/img/favicon.png"> - <link rel="apple-touch-icon" href="assets/img/touch-icon-iphone.png"> - <link rel="apple-touch-icon" sizes="72x72" href="assets/img/touch-icon-ipad.png"> - <link rel="apple-touch-icon" sizes="114x114" href="assets/img/touch-icon-iphone-retina.png"> - <link rel="apple-touch-icon" sizes="144x144" href="assets/img/touch-icon-ipad-retina.png"> + <link rel="icon" type="image/png" href="<?= $this->url->dir() ?>assets/img/favicon.png"> + <link rel="apple-touch-icon" href="<?= $this->url->dir() ?>assets/img/touch-icon-iphone.png"> + <link rel="apple-touch-icon" sizes="72x72" href="<?= $this->url->dir() ?>assets/img/touch-icon-ipad.png"> + <link rel="apple-touch-icon" sizes="114x114" href="<?= $this->url->dir() ?>assets/img/touch-icon-iphone-retina.png"> + <link rel="apple-touch-icon" sizes="144x144" href="<?= $this->url->dir() ?>assets/img/touch-icon-ipad-retina.png"> <title><?= isset($title) ? $this->e($title) : 'Kanboard' ?></title> </head> diff --git a/app/Template/listing/show.php b/app/Template/listing/show.php index 06940678..fc8a607b 100644 --- a/app/Template/listing/show.php +++ b/app/Template/listing/show.php @@ -10,13 +10,12 @@ <table class="table-fixed table-small"> <tr> <th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> - <th class="column-8"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> - <th class="column-8"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> <th><?= $paginator->order(t('Title'), 'tasks.title') ?></th> <th class="column-10"><?= $paginator->order(t('Assignee'), 'users.username') ?></th> <th class="column-10"><?= $paginator->order(t('Due date'), 'tasks.date_due') ?></th> - <th class="column-10"><?= $paginator->order(t('Date created'), 'tasks.date_creation') ?></th> - <th class="column-10"><?= $paginator->order(t('Date completed'), 'tasks.date_completed') ?></th> <th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th> </tr> <?php foreach ($paginator->getCollection() as $task): ?> @@ -25,6 +24,9 @@ <?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> </td> <td> + <?= $this->e($task['swimlane_name'] ?: $task['default_swimlane']) ?> + </td> + <td> <?= $this->e($task['column_name']) ?> </td> <td> @@ -44,14 +46,6 @@ <?= dt('%B %e, %Y', $task['date_due']) ?> </td> <td> - <?= dt('%B %e, %Y', $task['date_creation']) ?> - </td> - <td> - <?php if ($task['date_completed']): ?> - <?= dt('%B %e, %Y', $task['date_completed']) ?> - <?php endif ?> - </td> - <td> <?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?> <?= t('Open') ?> <?php else: ?> diff --git a/app/Template/notification/footer.php b/app/Template/notification/footer.php index 69d2cf82..c3b37884 100644 --- a/app/Template/notification/footer.php +++ b/app/Template/notification/footer.php @@ -2,6 +2,6 @@ Kanboard <?php if (isset($application_url) && ! empty($application_url)): ?> - - <a href="<?= $application_url.$this->url->href('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><?= t('view the task on Kanboard') ?></a> - - <a href="<?= $application_url.$this->url->href('board', 'show', array('project_id' => $task['project_id'])) ?>"><?= t('view the board on Kanboard') ?></a> + - <a href="<?= $this->url->href('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', true) ?>"><?= t('view the task on Kanboard') ?></a> + - <a href="<?= $this->url->href('board', 'show', array('project_id' => $task['project_id']), false, '', true) ?>"><?= t('view the board on Kanboard') ?></a> <?php endif ?> diff --git a/app/Template/notification/task_overdue.php b/app/Template/notification/task_overdue.php index dc2659dc..a231937b 100644 --- a/app/Template/notification/task_overdue.php +++ b/app/Template/notification/task_overdue.php @@ -5,7 +5,7 @@ <li> (<strong>#<?= $task['id'] ?></strong>) <?php if ($application_url): ?> - <a href="<?= $application_url.$this->url->href('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><?= $this->e($task['title']) ?></a> + <a href="<?= $this->url->href('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', true) ?>"><?= $this->e($task['title']) ?></a> <?php else: ?> <?= $this->e($task['title']) ?> <?php endif ?> diff --git a/app/Template/project/filters.php b/app/Template/project/filters.php index 3beb2f44..e2fdc751 100644 --- a/app/Template/project/filters.php +++ b/app/Template/project/filters.php @@ -5,13 +5,14 @@ <ul> <?php if (isset($is_board)): ?> <li> - <?php if ($this->board->isCollapsed($project['id'])): ?> + <span class="filter-display-mode" <?= $this->board->isCollapsed($project['id']) ? '' : 'style="display: none;"' ?>> <i class="fa fa-expand fa-fw"></i> <?= $this->url->link(t('Expand tasks'), 'board', 'expand', array('project_id' => $project['id']), false, 'board-display-mode', t('Keyboard shortcut: "%s"', 's')) ?> - <?php else: ?> + </span> + <span class="filter-display-mode" <?= $this->board->isCollapsed($project['id']) ? 'style="display: none;"' : '' ?>> <i class="fa fa-compress fa-fw"></i> <?= $this->url->link(t('Collapse tasks'), 'board', 'collapse', array('project_id' => $project['id']), false, 'board-display-mode', t('Keyboard shortcut: "%s"', 's')) ?> - <?php endif ?> + </span> </li> <li> <span class="filter-compact"> @@ -40,10 +41,10 @@ <?= $this->url->link(t('List'), 'listing', 'show', array('project_id' => $project['id'], 'search' => $filters['search']), false, 'view-listing', t('Keyboard shortcut: "%s"', 'v l')) ?> </li> </ul> - <form method="get" action="?" class="search"> - <?= $this->form->hidden('project_id', $filters) ?> + <form method="get" action="<?= $this->url->dir() ?>" class="search"> <?= $this->form->hidden('controller', $filters) ?> <?= $this->form->hidden('action', $filters) ?> + <?= $this->form->hidden('project_id', $filters) ?> <?= $this->form->text('search', $filters, array(), array('placeholder="'.t('Filter').'"'), 'form-input-large') ?> </form> <?= $this->render('app/filters_helper', array('reset' => 'status:open')) ?> diff --git a/app/Template/project/integrations.php b/app/Template/project/integrations.php index 445e7bfb..12a7ee4e 100644 --- a/app/Template/project/integrations.php +++ b/app/Template/project/integrations.php @@ -8,26 +8,26 @@ <h3><i class="fa fa-github fa-fw"></i> <?= t('Github webhooks') ?></h3> <div class="listing"> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'github', array('token' => $webhook_token, 'project_id' => $project['id'])) ?>"/><br/> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'github', array('token' => $webhook_token, 'project_id' => $project['id']), false, '', true) ?>"/><br/> <p class="form-help"><a href="http://kanboard.net/documentation/github-webhooks" target="_blank"><?= t('Help on Github webhooks') ?></a></p> </div> - <h3><img src="assets/img/gitlab-icon.png"/> <?= t('Gitlab webhooks') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/gitlab-icon.png"/> <?= t('Gitlab webhooks') ?></h3> <div class="listing"> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'gitlab', array('token' => $webhook_token, 'project_id' => $project['id'])) ?>"/><br/> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'gitlab', array('token' => $webhook_token, 'project_id' => $project['id']), false, '', true) ?>"/><br/> <p class="form-help"><a href="http://kanboard.net/documentation/gitlab-webhooks" target="_blank"><?= t('Help on Gitlab webhooks') ?></a></p> </div> <h3><i class="fa fa-bitbucket fa-fw"></i> <?= t('Bitbucket webhooks') ?></h3> <div class="listing"> - <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->base().$this->url->href('webhook', 'bitbucket', array('token' => $webhook_token, 'project_id' => $project['id'])) ?>"/><br/> + <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'bitbucket', array('token' => $webhook_token, 'project_id' => $project['id']), false, '', true) ?>"/><br/> <p class="form-help"><a href="http://kanboard.net/documentation/bitbucket-webhooks" target="_blank"><?= t('Help on Bitbucket webhooks') ?></a></p> </div> - <h3><img src="assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> <div class="listing"> <?= $this->form->checkbox('jabber', t('Send notifications to Jabber'), 1, isset($values['jabber']) && $values['jabber'] == 1) ?> @@ -58,7 +58,7 @@ </div> - <h3><img src="assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> + <h3><img src="<?= $this->url->dir() ?>assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> <div class="listing"> <?= $this->form->checkbox('hipchat', t('Send notifications to Hipchat'), 1, isset($values['hipchat']) && $values['hipchat'] == 1) ?> diff --git a/app/Template/search/index.php b/app/Template/search/index.php index 3d0d6ff9..8940a24e 100644 --- a/app/Template/search/index.php +++ b/app/Template/search/index.php @@ -9,7 +9,7 @@ </div> <div class="search"> - <form method="get" action="?" class="search"> + <form method="get" action="<?= $this->url->dir() ?>" class="search"> <?= $this->form->hidden('controller', $values) ?> <?= $this->form->hidden('action', $values) ?> <?= $this->form->text('search', $values, array(), array(empty($values['search']) ? 'autofocus' : '', 'placeholder="'.t('Search').'"'), 'form-input-large') ?> diff --git a/app/Template/search/results.php b/app/Template/search/results.php index 1d8cc6e2..04cb6a19 100644 --- a/app/Template/search/results.php +++ b/app/Template/search/results.php @@ -1,14 +1,13 @@ <table class="table-fixed table-small"> <tr> <th class="column-8"><?= $paginator->order(t('Project'), 'tasks.project_id') ?></th> - <th class="column-8"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> - <th class="column-8"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> - <th class="column-8"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> + <th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> + <th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Column'), 'tasks.column_id') ?></th> + <th class="column-10"><?= $paginator->order(t('Category'), 'tasks.category_id') ?></th> <th><?= $paginator->order(t('Title'), 'tasks.title') ?></th> <th class="column-10"><?= $paginator->order(t('Assignee'), 'users.username') ?></th> <th class="column-10"><?= $paginator->order(t('Due date'), 'tasks.date_due') ?></th> - <th class="column-10"><?= $paginator->order(t('Date created'), 'tasks.date_creation') ?></th> - <th class="column-10"><?= $paginator->order(t('Date completed'), 'tasks.date_completed') ?></th> <th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th> </tr> <?php foreach ($paginator->getCollection() as $task): ?> @@ -20,6 +19,9 @@ <?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> </td> <td> + <?= $this->e($task['swimlane_name'] ?: $task['default_swimlane']) ?> + </td> + <td> <?= $this->e($task['column_name']) ?> </td> <td> @@ -39,14 +41,6 @@ <?= dt('%B %e, %Y', $task['date_due']) ?> </td> <td> - <?= dt('%B %e, %Y', $task['date_creation']) ?> - </td> - <td> - <?php if ($task['date_completed']): ?> - <?= dt('%B %e, %Y', $task['date_completed']) ?> - <?php endif ?> - </td> - <td> <?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?> <?= t('Open') ?> <?php else: ?> diff --git a/app/Template/task/edit_recurrence.php b/app/Template/task/edit_recurrence.php index c261e368..e7c4c8f8 100644 --- a/app/Template/task/edit_recurrence.php +++ b/app/Template/task/edit_recurrence.php @@ -15,7 +15,7 @@ <?php if ($task['recurrence_status'] != \Model\Task::RECURRING_STATUS_PROCESSED): ?> - <form method="post" action="<?= $this->url->href('task', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => $ajax)) ?>" autocomplete="off"> + <form method="post" action="<?= $this->url->href('task', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" autocomplete="off"> <?= $this->form->csrf() ?> @@ -40,12 +40,7 @@ <div class="form-actions"> <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> <?= t('or') ?> - - <?php if ($ajax): ?> - <?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $task['project_id'])) ?> - <?php else: ?> - <?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> - <?php endif ?> + <?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> </div> </form> diff --git a/app/Template/user/authentication.php b/app/Template/user/authentication.php new file mode 100644 index 00000000..a62c8f93 --- /dev/null +++ b/app/Template/user/authentication.php @@ -0,0 +1,32 @@ +<div class="page-header"> + <h2><?= t('Edit Authentication') ?></h2> +</div> +<form method="post" action="<?= $this->url->href('user', 'authentication', array('user_id' => $user['id'])) ?>" autocomplete="off"> + + <?= $this->form->csrf() ?> + + <?= $this->form->hidden('id', $values) ?> + <?= $this->form->hidden('username', $values) ?> + + <?= $this->form->label(t('Google Id'), 'google_id') ?> + <?= $this->form->text('google_id', $values, $errors) ?> + + <?= $this->form->label(t('Github Id'), 'github_id') ?> + <?= $this->form->text('github_id', $values, $errors) ?> + + <?= $this->form->checkbox('is_ldap_user', t('Remote user'), 1, isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1) ?> + <?= $this->form->checkbox('disable_login_form', t('Disallow login form'), 1, isset($values['disable_login_form']) && $values['disable_login_form'] == 1) ?> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + <?= t('or') ?> + <?= $this->url->link(t('cancel'), 'user', 'show', array('user_id' => $user['id'])) ?> + </div> + + <div class="alert alert-info"> + <ul> + <li><?= t('Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.') ?></li> + <li><?= t('If you check the box "Disallow login form", credentials entered in the login form will be ignored.') ?></li> + </ul> + </div> +</form>
\ No newline at end of file diff --git a/app/Template/user/new.php b/app/Template/user/create_local.php index 0db1e824..aeec300f 100644 --- a/app/Template/user/new.php +++ b/app/Template/user/create_local.php @@ -2,6 +2,7 @@ <div class="page-header"> <ul> <li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('All users'), 'user', 'index') ?></li> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New remote user'), 'user', 'create', array('remote' => 1)) ?></li> </ul> </div> <section> diff --git a/app/Template/user/create_remote.php b/app/Template/user/create_remote.php new file mode 100644 index 00000000..52661585 --- /dev/null +++ b/app/Template/user/create_remote.php @@ -0,0 +1,57 @@ +<section id="main"> + <div class="page-header"> + <ul> + <li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('All users'), 'user', 'index') ?></li> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New local user'), 'user', 'create') ?></li> + </ul> + </div> + <form method="post" action="<?= $this->url->href('user', 'save') ?>" autocomplete="off"> + + <?= $this->form->csrf() ?> + <?= $this->form->hidden('is_ldap_user', array('is_ldap_user' => 1)) ?> + + <div class="form-column"> + <?= $this->form->label(t('Username'), 'username') ?> + <?= $this->form->text('username', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?><br/> + + <?= $this->form->label(t('Name'), 'name') ?> + <?= $this->form->text('name', $values, $errors) ?><br/> + + <?= $this->form->label(t('Email'), 'email') ?> + <?= $this->form->email('email', $values, $errors) ?><br/> + + <?= $this->form->label(t('Google Id'), 'google_id') ?> + <?= $this->form->password('google_id', $values, $errors) ?><br/> + + <?= $this->form->label(t('Github Id'), 'github_id') ?> + <?= $this->form->password('github_id', $values, $errors) ?><br/> + </div> + + <div class="form-column"> + <?= $this->form->label(t('Add project member'), 'project_id') ?> + <?= $this->form->select('project_id', $projects, $values, $errors) ?><br/> + + <?= $this->form->label(t('Timezone'), 'timezone') ?> + <?= $this->form->select('timezone', $timezones, $values, $errors) ?><br/> + + <?= $this->form->label(t('Language'), 'language') ?> + <?= $this->form->select('language', $languages, $values, $errors) ?><br/> + + <?= $this->form->checkbox('notifications_enabled', t('Enable notifications'), 1, isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1 ? true : false) ?> + <?= $this->form->checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1 ? true : false) ?> + <?= $this->form->checkbox('disable_login_form', t('Disallow login form'), 1, isset($values['disable_login_form']) && $values['disable_login_form'] == 1) ?> + </div> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + <?= t('or') ?> + <?= $this->url->link(t('cancel'), 'user', 'index') ?> + </div> + </form> + <div class="alert alert-info"> + <ul> + <li><?= t('Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.') ?></li> + <li><?= t('If you check the box "Disallow login form", credentials entered in the login form will be ignored.') ?></li> + </ul> + </div> +</section>
\ No newline at end of file diff --git a/app/Template/user/edit.php b/app/Template/user/edit.php index 2462308f..ea7e3875 100644 --- a/app/Template/user/edit.php +++ b/app/Template/user/edit.php @@ -6,7 +6,6 @@ <?= $this->form->csrf() ?> <?= $this->form->hidden('id', $values) ?> - <?= $this->form->hidden('is_ldap_user', $values) ?> <?= $this->form->label(t('Username'), 'username') ?> <?= $this->form->text('username', $values, $errors, array('required', $values['is_ldap_user'] == 1 ? 'readonly' : '', 'maxlength="50"')) ?><br/> @@ -23,13 +22,9 @@ <?= $this->form->label(t('Language'), 'language') ?> <?= $this->form->select('language', $languages, $values, $errors) ?><br/> - <div class="alert alert-error"> - <?= $this->form->checkbox('disable_login_form', t('Disable login form'), 1, isset($values['disable_login_form']) && $values['disable_login_form'] == 1) ?><br/> - - <?php if ($this->user->isAdmin()): ?> - <?= $this->form->checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1) ?><br/> - <?php endif ?> - </div> + <?php if ($this->user->isAdmin()): ?> + <?= $this->form->checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1) ?><br/> + <?php endif ?> <div class="form-actions"> <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> diff --git a/app/Template/user/external.php b/app/Template/user/external.php index df85ace7..3b872e85 100644 --- a/app/Template/user/external.php +++ b/app/Template/user/external.php @@ -8,9 +8,9 @@ <p class="listing"> <?php if ($this->user->isCurrentUser($user['id'])): ?> <?php if (empty($user['google_id'])): ?> - <?= $this->url->link(t('Link my Google Account'), 'user', 'google', array(), true) ?> + <?= $this->url->link(t('Link my Google Account'), 'oauth', 'google', array(), true) ?> <?php else: ?> - <?= $this->url->link(t('Unlink my Google Account'), 'user', 'unlinkGoogle', array(), true) ?> + <?= $this->url->link(t('Unlink my Google Account'), 'oauth', 'unlink', array('backend' => 'google'), true) ?> <?php endif ?> <?php else: ?> <?= empty($user['google_id']) ? t('No account linked.') : t('Account linked.') ?> @@ -24,9 +24,9 @@ <p class="listing"> <?php if ($this->user->isCurrentUser($user['id'])): ?> <?php if (empty($user['github_id'])): ?> - <?= $this->url->link(t('Link my GitHub Account'), 'user', 'github', array(), true) ?> + <?= $this->url->link(t('Link my Github Account'), 'oauth', 'github', array(), true) ?> <?php else: ?> - <?= $this->url->link(t('Unlink my GitHub Account'), 'user', 'unlinkGitHub', array(), true) ?> + <?= $this->url->link(t('Unlink my Github Account'), 'oauth', 'unlink', array('backend' => 'github'), true) ?> <?php endif ?> <?php else: ?> <?= empty($user['github_id']) ? t('No account linked.') : t('Account linked.') ?> diff --git a/app/Template/user/index.php b/app/Template/user/index.php index fc575466..edf043a6 100644 --- a/app/Template/user/index.php +++ b/app/Template/user/index.php @@ -2,7 +2,8 @@ <div class="page-header"> <?php if ($this->user->isAdmin()): ?> <ul> - <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New user'), 'user', 'create') ?></li> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New local user'), 'user', 'create') ?></li> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New remote user'), 'user', 'create', array('remote' => 1)) ?></li> </ul> <?php endif ?> </div> diff --git a/app/Template/user/layout.php b/app/Template/user/layout.php index e60ab77d..a27f359b 100644 --- a/app/Template/user/layout.php +++ b/app/Template/user/layout.php @@ -3,7 +3,8 @@ <?php if ($this->user->isAdmin()): ?> <ul> <li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('All users'), 'user', 'index') ?></li> - <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New user'), 'user', 'create') ?></li> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New local user'), 'user', 'create') ?></li> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New remote user'), 'user', 'create', array('remote' => 1)) ?></li> </ul> <?php endif ?> </div> diff --git a/app/Template/user/sidebar.php b/app/Template/user/sidebar.php index e61a43bf..3e79fda3 100644 --- a/app/Template/user/sidebar.php +++ b/app/Template/user/sidebar.php @@ -58,6 +58,9 @@ <?php if ($this->user->isAdmin()): ?> <li> + <?= $this->url->link(t('Edit Authentication'), 'user', 'authentication', array('user_id' => $user['id'])) ?> + </li> + <li> <?= $this->url->link(t('Hourly rates'), 'hourlyrate', 'index', array('user_id' => $user['id'])) ?> </li> <li> diff --git a/app/common.php b/app/common.php index b5871673..734f094b 100644 --- a/app/common.php +++ b/app/common.php @@ -12,7 +12,7 @@ if (getenv('DATABASE_URL')) { define('DB_PASSWORD', $dbopts["pass"]); define('DB_HOSTNAME', $dbopts["host"]); define('DB_PORT', isset($dbopts["port"]) ? $dbopts["port"] : null); - define('DB_NAME', ltrim($dbopts["path"],'/')); + define('DB_NAME', ltrim($dbopts["path"], '/')); } // Include custom config file @@ -28,3 +28,97 @@ $container->register(new ServiceProvider\LoggingProvider); $container->register(new ServiceProvider\DatabaseProvider); $container->register(new ServiceProvider\ClassProvider); $container->register(new ServiceProvider\EventDispatcherProvider); + +if (ENABLE_URL_REWRITE) { + + // Dashboard + $container['router']->addRoute('dashboard', 'app', 'index'); + $container['router']->addRoute('dashboard/:user_id', 'app', 'index', array('user_id')); + $container['router']->addRoute('dashboard/:user_id/projects', 'app', 'projects', array('user_id')); + $container['router']->addRoute('dashboard/:user_id/tasks', 'app', 'tasks', array('user_id')); + $container['router']->addRoute('dashboard/:user_id/subtasks', 'app', 'subtasks', array('user_id')); + $container['router']->addRoute('dashboard/:user_id/calendar', 'app', 'calendar', array('user_id')); + $container['router']->addRoute('dashboard/:user_id/activity', 'app', 'activity', array('user_id')); + + // Search routes + $container['router']->addRoute('search', 'search', 'index'); + $container['router']->addRoute('search/:search', 'search', 'index', array('search')); + + // Project routes + $container['router']->addRoute('projects', 'project', 'index'); + $container['router']->addRoute('project/create', 'project', 'create'); + $container['router']->addRoute('project/create/:private', 'project', 'create', array('private')); + $container['router']->addRoute('project/:project_id', 'project', 'show', array('project_id')); + $container['router']->addRoute('p/:project_id', 'project', 'show', array('project_id')); + $container['router']->addRoute('project/:project_id/share', 'project', 'share', array('project_id')); + $container['router']->addRoute('project/:project_id/edit', 'project', 'edit', array('project_id')); + $container['router']->addRoute('project/:project_id/integration', 'project', 'integration', array('project_id')); + $container['router']->addRoute('project/:project_id/users', 'project', 'users', array('project_id')); + $container['router']->addRoute('project/:project_id/duplicate', 'project', 'duplicate', array('project_id')); + $container['router']->addRoute('project/:project_id/remove', 'project', 'remove', array('project_id')); + $container['router']->addRoute('project/:project_id/disable', 'project', 'disable', array('project_id')); + $container['router']->addRoute('project/:project_id/enable', 'project', 'enable', array('project_id')); + + // Action routes + $container['router']->addRoute('project/:project_id/actions', 'action', 'index', array('project_id')); + $container['router']->addRoute('project/:project_id/action/:action_id/confirm', 'action', 'confirm', array('project_id', 'action_id')); + + // Column routes + $container['router']->addRoute('project/:project_id/columns', 'column', 'index', array('project_id')); + $container['router']->addRoute('project/:project_id/column/:column_id/edit', 'column', 'edit', array('project_id', 'column_id')); + $container['router']->addRoute('project/:project_id/column/:column_id/confirm', 'column', 'confirm', array('project_id', 'column_id')); + $container['router']->addRoute('project/:project_id/column/:column_id/move/:direction', 'column', 'move', array('project_id', 'column_id', 'direction')); + + // Swimlane routes + $container['router']->addRoute('project/:project_id/swimlanes', 'swimlane', 'index', array('project_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/edit', 'swimlane', 'edit', array('project_id', 'swimlane_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/confirm', 'swimlane', 'confirm', array('project_id', 'swimlane_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/disable', 'swimlane', 'disable', array('project_id', 'swimlane_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/enable', 'swimlane', 'enable', array('project_id', 'swimlane_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/up', 'swimlane', 'moveup', array('project_id', 'swimlane_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/down', 'swimlane', 'movedown', array('project_id', 'swimlane_id')); + + // Category routes + $container['router']->addRoute('project/:project_id/categories', 'category', 'index', array('project_id')); + $container['router']->addRoute('project/:project_id/category/:category_id/edit', 'category', 'edit', array('project_id', 'category_id')); + $container['router']->addRoute('project/:project_id/category/:category_id/confirm', 'category', 'confirm', array('project_id', 'category_id')); + + // Task routes + $container['router']->addRoute('project/:project_id/task/:task_id', 'task', 'show', array('project_id', 'task_id')); + $container['router']->addRoute('t/:task_id', 'task', 'show', array('task_id')); + $container['router']->addRoute('project/:project_id/swimlane/:swimlane_id/column/:column_id', 'task', 'create', array('project_id', 'swimlane_id', 'column_id')); + $container['router']->addRoute('public/task/:task_id/:token', 'task', 'readonly', array('task_id', 'token')); + + // Board routes + $container['router']->addRoute('board/:project_id', 'board', 'show', array('project_id')); + $container['router']->addRoute('b/:project_id', 'board', 'show', array('project_id')); + $container['router']->addRoute('board/:project_id/filter/:search', 'board', 'show', array('project_id', 'search')); + $container['router']->addRoute('public/board/:token', 'board', 'readonly', array('token')); + + // Calendar routes + $container['router']->addRoute('calendar/:project_id', 'calendar', 'show', array('project_id')); + $container['router']->addRoute('c/:project_id', 'calendar', 'show', array('project_id')); + $container['router']->addRoute('calendar/:project_id/:search', 'calendar', 'show', array('project_id', 'search')); + + // Listing routes + $container['router']->addRoute('list/:project_id', 'listing', 'show', array('project_id')); + $container['router']->addRoute('l/:project_id', 'listing', 'show', array('project_id')); + $container['router']->addRoute('list/:project_id/:search', 'listing', 'show', array('project_id', 'search')); + + // Subtask routes + $container['router']->addRoute('project/:project_id/task/:task_id/subtask/:subtask_id', 'subtask', 'remove', array('project_id', 'task_id', 'subtask_id')); + + // Feed routes + $container['router']->addRoute('feed/project/:token', 'feed', 'project', array('token')); + $container['router']->addRoute('feed/user/:token', 'feed', 'user', array('token')); + + // Ical routes + $container['router']->addRoute('ical/project/:token', 'ical', 'project', array('token')); + $container['router']->addRoute('ical/user/:token', 'ical', 'user', array('token')); + + // Auth routes + $container['router']->addRoute('oauth/google', 'oauth', 'google'); + $container['router']->addRoute('oauth/github', 'oauth', 'github'); + $container['router']->addRoute('login', 'auth', 'login'); + $container['router']->addRoute('logout', 'auth', 'logout'); +} diff --git a/app/constants.php b/app/constants.php index 9b66b746..83fba468 100644 --- a/app/constants.php +++ b/app/constants.php @@ -7,9 +7,6 @@ defined('DEBUG_FILE') or define('DEBUG_FILE', __DIR__.'/../data/debug.log'); // Application version defined('APP_VERSION') or define('APP_VERSION', 'master'); -// Base directory -define('BASE_URL_DIRECTORY', dirname($_SERVER['PHP_SELF'])); - // Database driver: sqlite, mysql or postgres defined('DB_DRIVER') or define('DB_DRIVER', 'sqlite'); @@ -38,13 +35,14 @@ defined('LDAP_ACCOUNT_FULLNAME') or define('LDAP_ACCOUNT_FULLNAME', 'displayname defined('LDAP_ACCOUNT_EMAIL') or define('LDAP_ACCOUNT_EMAIL', 'mail'); defined('LDAP_ACCOUNT_ID') or define('LDAP_ACCOUNT_ID', ''); defined('LDAP_USERNAME_CASE_SENSITIVE') or define('LDAP_USERNAME_CASE_SENSITIVE', false); +defined('LDAP_ACCOUNT_CREATION') or define('LDAP_ACCOUNT_CREATION', true); // Google authentication defined('GOOGLE_AUTH') or define('GOOGLE_AUTH', false); defined('GOOGLE_CLIENT_ID') or define('GOOGLE_CLIENT_ID', ''); defined('GOOGLE_CLIENT_SECRET') or define('GOOGLE_CLIENT_SECRET', ''); -// GitHub authentication +// Github authentication defined('GITHUB_AUTH') or define('GITHUB_AUTH', false); defined('GITHUB_CLIENT_ID') or define('GITHUB_CLIENT_ID', ''); defined('GITHUB_CLIENT_SECRET') or define('GITHUB_CLIENT_SECRET', ''); @@ -84,3 +82,9 @@ defined('MARKDOWN_ESCAPE_HTML') or define('MARKDOWN_ESCAPE_HTML', true); // API alternative authentication header, the default is HTTP Basic Authentication defined in RFC2617 defined('API_AUTHENTICATION_HEADER') or define('API_AUTHENTICATION_HEADER', ''); + +// Enable/disable url rewrite +defined('ENABLE_URL_REWRITE') or define('ENABLE_URL_REWRITE', isset($_SERVER['HTTP_MOD_REWRITE'])); + +// Hide login form +defined('HIDE_LOGIN_FORM') or define('HIDE_LOGIN_FORM', false); |